diff options
author | Jan Tattermusch <jtattermusch@google.com> | 2015-02-24 08:21:57 -0800 |
---|---|---|
committer | Jan Tattermusch <jtattermusch@google.com> | 2015-02-25 09:45:38 -0800 |
commit | 5339814591c41c845996cba7ed9d83c506922de4 (patch) | |
tree | c323177e9e479e44a192b814d46f9d55fe8e02ce | |
parent | afae27cf5ec1d8b7d5b7f6a349b47502a12360de (diff) |
Added ability for c# to redirect C core logs to arbitrary sink
-rw-r--r-- | src/csharp/Grpc.Core/Grpc.Core.csproj | 7 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/GrpcEnvironment.cs | 1 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/GrpcLog.cs | 94 | ||||
-rw-r--r-- | src/csharp/ext/grpc_csharp_ext.c | 24 |
4 files changed, 120 insertions, 6 deletions
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 135ce26cbd..6156b2f38b 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -33,6 +33,7 @@ <Reference Include="System" /> </ItemGroup> <ItemGroup> + <Compile Include="Internal\GrpcLog.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="RpcException.cs" /> <Compile Include="Calls.cs" /> @@ -66,8 +67,4 @@ <Compile Include="Utils\ExceptionHelper.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> - <ItemGroup> - <Folder Include="Internal\" /> - <Folder Include="Utils\" /> - </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index 0e3a0a581c..d3a8da4729 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -107,6 +107,7 @@ namespace Grpc.Core /// </summary> private GrpcEnvironment() { + GrpcLog.RedirectNativeLogs(Console.Error); grpcsharp_init(); threadPool = new GrpcThreadPool(THREAD_POOL_SIZE); threadPool.Start(); diff --git a/src/csharp/Grpc.Core/Internal/GrpcLog.cs b/src/csharp/Grpc.Core/Internal/GrpcLog.cs new file mode 100644 index 0000000000..98768d05c6 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/GrpcLog.cs @@ -0,0 +1,94 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Grpc.Core.Internal +{ + internal delegate void GprLogDelegate(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr); + + /// <summary> + /// Logs from gRPC C core library can get lost if your application is not a console app. + /// This class allows redirection of logs to arbitrary destination. + /// </summary> + internal static class GrpcLog + { + static object staticLock = new object(); + static GprLogDelegate writeCallback; + static TextWriter dest; + + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + /// <summary> + /// Sets text writer as destination for logs from native gRPC C core library. + /// Only first invocation has effect. + /// </summary> + /// <param name="textWriter"></param> + public static void RedirectNativeLogs(TextWriter textWriter) + { + lock (staticLock) + { + if (writeCallback == null) + { + writeCallback = new GprLogDelegate(HandleWrite); + dest = textWriter; + grpcsharp_redirect_log(writeCallback); + } + } + } + + private static void HandleWrite(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr) + { + try + { + // TODO: DateTime format used here is different than in C core. + dest.WriteLine(string.Format("{0}{1} {2} {3}:{4}: {5}", + Marshal.PtrToStringAnsi(severityStringPtr), DateTime.Now, + threadId, + Marshal.PtrToStringAnsi(fileStringPtr), + line, + Marshal.PtrToStringAnsi(msgPtr))); + } + catch (Exception e) + { + Console.WriteLine("Caught exception in native callback " + e); + } + } + } +} diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 18e0431e3b..3cdeaef715 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -35,9 +35,10 @@ #include <grpc/support/port_platform.h> #include <grpc/support/alloc.h> -#include <grpc/grpc.h> #include <grpc/support/log.h> #include <grpc/support/slice.h> +#include <grpc/support/thd.h> +#include <grpc/grpc.h> #include <string.h> @@ -579,6 +580,27 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, &(ctx->server_rpc_new.request_metadata), cq, ctx); } +/* Logging */ + +typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, + gpr_int32 line, + gpr_uint64 thd_id, + const char *severity_string, + const char *msg); +static grpcsharp_log_func log_func = NULL; + +/* Redirects gpr_log to log_func callback */ +static void grpcsharp_log_handler(gpr_log_func_args *args) { + log_func(args->file, args->line, gpr_thd_currentid(), + gpr_log_severity_string(args->severity), args->message); +} + +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_redirect_log(grpcsharp_log_func func) { + GPR_ASSERT(func); + log_func = func; + gpr_set_log_function(grpcsharp_log_handler); +} /* For testing */ GPR_EXPORT void GPR_CALLTYPE |