{"id":21152990,"url":"https://github.com/opentracing-contrib/csharp-grpc","last_synced_at":"2025-07-09T10:33:28.271Z","repository":{"id":32458467,"uuid":"132520040","full_name":"opentracing-contrib/csharp-grpc","owner":"opentracing-contrib","description":"OpenTracing Instrumentation for gRPC","archived":false,"fork":false,"pushed_at":"2023-10-25T09:06:21.000Z","size":174,"stargazers_count":43,"open_issues_count":1,"forks_count":10,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-06-27T20:06:49.269Z","etag":null,"topics":["grpc","grpc-csharp","opentracing"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opentracing-contrib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-07T21:49:40.000Z","updated_at":"2023-10-26T05:15:05.000Z","dependencies_parsed_at":"2024-11-20T11:23:25.051Z","dependency_job_id":"ae4e10df-aecb-46ce-97f2-9748594f3a64","html_url":"https://github.com/opentracing-contrib/csharp-grpc","commit_stats":{"total_commits":21,"total_committers":6,"mean_commits":3.5,"dds":0.7619047619047619,"last_synced_commit":"4878d603222ed929d3b9c1f4254a2f3349627165"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/opentracing-contrib/csharp-grpc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentracing-contrib%2Fcsharp-grpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentracing-contrib%2Fcsharp-grpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentracing-contrib%2Fcsharp-grpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentracing-contrib%2Fcsharp-grpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opentracing-contrib","download_url":"https://codeload.github.com/opentracing-contrib/csharp-grpc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentracing-contrib%2Fcsharp-grpc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264440459,"owners_count":23608717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["grpc","grpc-csharp","opentracing"],"created_at":"2024-11-20T10:47:58.938Z","updated_at":"2025-07-09T10:33:27.929Z","avatar_url":"https://github.com/opentracing-contrib.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build status][ci-img]][ci] [![NuGet][nuget-img]][nuget]\n\n**WARNING: This project is a work in progress and not yet ready for production**\n\n# OpenTracing gRPC Instrumentation\n\nOpenTracing instrumentation for gRPC.\n\n## Installation\n\nInstall the [NuGet package](https://www.nuget.org/packages/OpenTracing.Contrib.Grpc/):\n\n    Install-Package OpenTracing.Contrib.Grpc\n\n## Usage\n\n### Server\n\n- Instantiate tracer\n- Create a `ServerTracingInterceptor`\n- Intercept a service\n\n```csharp\nusing Grpc.Core;\nusing Grpc.Core.Interceptors;\nusing OpenTracing.Contrib.Grpc;\n\n    public class YourServer {\n\n        private readonly string host;\n        private readonly int port;\n        private readonly Server server;\n        private readonly Tracer tracer;\n\n        private void Start() {\n            ServerTracingInterceptor tracingInterceptor = new ServerTracingInterceptor(this.tracer);\n\n            Server server = new Server\n            {\n                Ports = { new ServerPort(this.host, this.port, ServerCredentials.Insecure) },\n                Services = { SomeService.BindService(new SomeServiceImpl()).Intercept(tracingInterceptor) }\n            };\n            server.Start();\n        }\n    }\n```\n\n### Client\n\n- Instantiate a tracer\n- Create a `ClientTracingInterceptor`\n- Intercept the client channel\n\n```csharp\nusing Grpc.Core;\nusing Grpc.Core.Interceptors;\nusing OpenTracing.Contrib.Grpc;\n\n    public class YourClient {\n\n        private readonly Channel channel;\n        private readonly Tracer tracer;\n        private readonly SomeServiceClient client;\n\n        public YourClient(string host, int port) {\n            this.channel = new Channel(host, port, ChannelCredentials.Insecure);\n\n            ClientTracingInterceptor tracingInterceptor = new ClientTracingInterceptor(this.tracer);\n            this.client = new SomeService.SomeServiceClient(this.channel.Intercept(tracingInterceptor));\n        }\n    }\n```\n\n## Server Tracing\n\nA `ServerTracingInterceptor` uses default settings, which you can override by creating it using a `ServerTracingInterceptor.Builder`.\n\n- `WithOperationName(IOperationNameConstructor operationName)`: Define how the operation name is constructed for all spans created for this intercepted server. Default is the name of the RPC method. More details in the `Operation Name` section.\n- `WithStreaming()`: Logs to the server span whenever a message is received or a response sent. *Note:* This package supports streaming but has not been rigorously tested. If you come across any issues, please let us know.\n- `WithStreamingInputSpans()`: Creates a child span for each incoming message. This is adviced when using long-running streams as the calls' span is only finished when the connection is closed.\n- `WithStreamingOutputSpans()`: Creates a child span for each outgoing message. This is adviced when using long-running streams as the calls' span is only finished when the connection is closed.\n- `WithVerbosity()`: Logs to the server span additional events, such as message received, headers received and call complete. Default only logs if a call is cancelled.\n- `WithTracedAttributes(params ServerRequestAttribute[] attrs)`: Sets tags on the server span in case you want to track information about the RPC call.\n\n### Example\n\n```csharp\nServerTracingInterceptor tracingInterceptor = new ServerTracingInterceptor\n    .Builder(tracer)\n    .WithStreaming()\n    .WithStreamingInputSpans()\n    .WithStreamingOutputSpans()\n    .WithVerbosity()\n    .WithOperationName(new PrefixOperationNameConstructor(\"Server\"))\n    .WithTracedAttributes(ServerTracingConfiguration.RequestAttribute.Headers,\n        ServerTracingConfiguration.RequestAttribute.MethodType)\n    .Build();\n```\n\n## Client Tracing\n\nA `ClientTracingInterceptor` also has default settings, which you can override by creating it using a `ClientTracingInterceptor.Builder`.\n\n- `WithOperationName(IOperationNameConstructor operationName)`: Define how the operation name is constructed for all spans created for this intercepted client. Default is the name of the RPC method. More details in the `Operation Name` section.\n- `WithStreaming()`: Logs to the client span whenever a message is sent or a response is received. *Note:* This package supports streaming but has not been rigorously tested. If you come across any issues, please let us know.\n- `WithStreamingInputSpans()`: Creates a child span for each incoming message. This is adviced when using long-running streams as the calls' span is only finished when the connection is closed.\n- `WithStreamingOutputSpans()`: Creates a child span for each outgoing message. This is adviced when using long-running streams as the calls' span is only finished when the connection is closed.\n- `WithVerbosity()`: Logs to the client span additional events, such as call started, message sent, headers received, response received, and call complete. Default only logs if a call is cancelled.\n- `WithTracedAttributes(params ClientRequestAttribute[] attrs)`: Sets tags on the client span in case you want to track information about the RPC call.\n- `WithWaitForReady()`: Enables WaitForReady on all RPC calls.\n- `WithFallbackCancellationToken(CancellationToken cancellationToken)`: Sets the cancellation token if the RPC call hasn't defined one.\n\n### Example\n```csharp\npublic class CustomOperationNameConstructor : IOperationNameConstructor\n{\n    public string ConstructOperationName\u003cTRequest, TResponse\u003e(Method\u003cTRequest, TResponse\u003e method)\n    {\n        // construct some operation name from the method descriptor\n    }\n}\n\nClientTracingInterceptor tracingInterceptor = new ClientTracingInterceptor\n    .Builder(tracer)\n    .WithStreaming()\n    .WithStreamingInputSpans()\n    .WithStreamingOutputSpans()\n    .WithVerbosity()\n    .WithOperationName(new CustomOperationNameConstructor())\n    .WithTracingAttributes(ClientTracingConfiguration.RequestAttribute.AllCallOptions,\n        ClientTracingConfiguration.ClientRequestAttribute.Headers)\n    .WithWaitForReady()\n    .WithFallbackCancellationToken(cancellationToken)\n    .Build();\n```\n\n## Current Span Context\n\nIn your server request handler, you can access the current active span for that request by calling\n\n```csharp\nSpan span = tracer.ActiveSpan;\n```\n\nThis is useful if you want to manually set tags on the span, log important events, or create a new child span for internal units of work. You can also use this key to wrap these internal units of work with a new context that has a user-defined active span.\n\n## Operation Names\n\nThe default operation name for any span is the RPC method name (`Grpc.Core.Method\u003cTRequest, TResponse\u003e.FullName`). However, you may want to add your own prefixes, alter the name, or define a new name. For examples of good operation names, check out the OpenTracing `semantics`.\n\nTo alter the operation name, you need to add an implementation of the interface `IOperationNameConstructor` to the `ClientTracingInterceptor.Builder` or `ServerTracingInterceptor.Builder`. For example, if you want to add a prefix to the default operation name of your ClientInterceptor, your code would look like this:\n\n```csharp\npublic class CustomPrefixOperationNameConstructor : IOperationNameConstructor\n{\n    public string ConstructOperationName\u003cTRequest, TResponse\u003e(Method\u003cTRequest, TResponse\u003e method)\n    {\n        return \"your-prefix\" + method.FullName;\n    }\n    public string ConstructOperationName(string method)\n    {\n        return \"your-prefix\" + method;\n    }\n}\n\nClientTracingInterceptor interceptor = ClientTracingInterceptor.Builder ...\n    .WithOperationName(new CustomPrefixOperationNameConstructor())\n    .With....\n    .Build()\n```\n\nYou can also use the default implementation using `PrefixOperationNameConstructor`:\n\n\n```csharp\nClientTracingInterceptor interceptor = ClientTracingInterceptor.Builder ...\n    .WithOperationName(new PrefixOperationNameConstructor(\"your-prefix\"))\n    .With....\n    .Build()\n```\n\nDue to how the C# version of GRPC interceptors are written, it's currently not possible get more information on the method than the method name in an `ServerTracingInterceptor`.\n\n## Integrating with Other Interceptors\nGRPC provides `Intercept(Interceptor)` methods that allow you chaining multiple interceptors. Preferably put the tracing interceptor at the top of the interceptor stack so that it traces the entire request lifecycle, including other interceptors:\n\n### Server\n```csharp\nServer server = new Server\n{\n    Services = { SomeService.BindService(new SomeServiceImpl()).Intercept(someInterceptor).Intercept(someOtherInterceptor).Intercept(serverTracingInterceptor) }\n    Ports = ...\n};\n```\n\n### Client\n```csharp\nclient = new SomeService.SomeServiceClient(this.channel.Intercept(someInterceptor).Intercept(someOtherInterceptor).Intercept(clientTracingInterceptor));\n```\n\n[ci-img]: https://ci.appveyor.com/api/projects/status/github/opentracing-contrib/csharp-grpc?svg=true\n[ci]: https://ci.appveyor.com/project/opentracing/csharp-grpc\n[nuget-img]: https://img.shields.io/nuget/v/OpenTracing.Contrib.Grpc.svg\n[nuget]: https://www.nuget.org/packages/OpenTracing.Contrib.Grpc/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentracing-contrib%2Fcsharp-grpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopentracing-contrib%2Fcsharp-grpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentracing-contrib%2Fcsharp-grpc/lists"}