{"id":20317569,"url":"https://github.com/dynatrace/oneagent-sdk-for-dotnet","last_synced_at":"2025-09-09T19:27:54.017Z","repository":{"id":45452139,"uuid":"123405757","full_name":"Dynatrace/OneAgent-SDK-for-dotnet","owner":"Dynatrace","description":"Enables custom tracing of .NET applications in Dynatrace","archived":false,"fork":false,"pushed_at":"2025-07-31T09:07:34.000Z","size":195,"stargazers_count":19,"open_issues_count":5,"forks_count":7,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-07-31T12:54:11.224Z","etag":null,"topics":["agent","apm","data-ingestion","dev-program","dynatrace","oneagent","sdk","sdk-dotnet"],"latest_commit_sha":null,"homepage":"https://www.dynatrace.com/support/help/extend-dynatrace/oneagent-sdk/what-is-oneagent-sdk/","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/Dynatrace.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-03-01T08:32:28.000Z","updated_at":"2025-07-31T09:07:39.000Z","dependencies_parsed_at":"2024-06-19T05:26:42.634Z","dependency_job_id":"5044f852-83bf-4198-9e46-fe6442d85409","html_url":"https://github.com/Dynatrace/OneAgent-SDK-for-dotnet","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/Dynatrace/OneAgent-SDK-for-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dynatrace","download_url":"https://codeload.github.com/Dynatrace/OneAgent-SDK-for-dotnet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynatrace%2FOneAgent-SDK-for-dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274348833,"owners_count":25268972,"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","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["agent","apm","data-ingestion","dev-program","dynatrace","oneagent","sdk","sdk-dotnet"],"created_at":"2024-11-14T18:33:24.004Z","updated_at":"2025-09-09T19:27:53.996Z","avatar_url":"https://github.com/Dynatrace.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dynatrace OneAgent SDK for .NET\n\nThis SDK allows Dynatrace customers to instrument .NET applications. This is useful to enhance the visibility for\nproprietary frameworks or custom frameworks not directly supported by\n[Dynatrace OneAgent](https://www.dynatrace.com/technologies/net-monitoring/) out-of-the-box.\n\nThis is the official .NET implementation of the [Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK).\n\n## Table of Contents\n\n* [Package contents](#package-contents)\n* [Requirements](#requirements)\n* [Integration](#integration)\n  * [Dependencies](#dependencies)\n  * [Troubleshooting](#troubleshooting)\n* [API Concepts](#api-concepts)\n  * [IOneAgentSDK object](#ioneagentsdk-object)\n  * [Trace Context](#tracecontext)\n  * [Tracers](#tracers)\n* [Features](#features)\n  * [Trace SQL database requests](#trace-sql-database-requests)\n  * [Trace remote calls](#trace-remote-calls)\n  * [Trace messaging](#trace-messaging)\n  * [Trace web requests](#trace-web-requests)\n  * [In-process linking](#in-process-linking)\n  * [Add custom request attributes](#add-custom-request-attributes)\n  * [Logging callback](#logging-callback)\n  * [SdkState and IOneAgentInfo](#sdkstate-and-ioneagentinfo)\n* [Further reading](#further-readings)\n* [Help \u0026 Support](#help--support)\n* [Release notes](#release-notes)\n\n## Package contents\n\n* `samples`: sample application which demonstrates the usage of the SDK\n* `src`: source code of the SDK (API and implementation stub - for reference only,\n    not intended to be edited/extended/built by the user)\n* `LICENSE`: license under which the SDK and sample applications are published\n\nThe SDK implementation is provided by the installed OneAgent at runtime. The classes in `src/DummyImpl` are a stub\nthat is used if no OneAgent is installed on the host so that your application is not affected by any\nmissing OneAgent dependency.\n\n## Requirements\n\n* Dynatrace OneAgent (required versions see below)\n* .NET Full Framework \u003e= 4.5 or .NET Core \u003e= 1.0 (the SDK is built using .NET Standard 1.0)\n\n|OneAgent SDK for .NET|Required OneAgent version|Support status|\n|:-----------------------|:------------------------|:-----------------------|\n| 1.8.0                  | \u003e=1.233                 | Supported              |\n| 1.7.0                  | \u003e=1.179                 | Supported              |\n| 1.6.0                  | \u003e=1.173                 | Supported              |\n| 1.5.0                  | \u003e=1.171                 | Supported              |\n| 1.4.0                  | \u003e=1.167                 | Supported              |\n| 1.3.0                  | \u003e=1.165                 | Supported              |\n| 1.2.0                  | \u003e=1.161                 | Supported              |\n| 1.1.0                  | \u003e=1.157                 | Supported              |\n| 1.0.0-alpha            | 1.153-1.155             | EAP (not supported)    |\n\n## Integration\n\nUsing this SDK should not cause any errors if no OneAgent is present (e.g. in testing).\n\n### Dependencies\n\nIf you want to integrate the OneAgent SDK into your application, just add the following NuGet dependency:\n\n[Dynatrace.OneAgent.Sdk NuGet package](https://www.nuget.org/packages/Dynatrace.OneAgent.Sdk)\n\nThe Dynatrace OneAgent SDK for .NET has no further dependencies.\n\n### Troubleshooting\n\nMake sure that:\n\n* OneAgent is installed on the host running your application\n* the installed version of OneAgent is compatible with the SDK version you are using\n  (see [Requirements](#requirements), check using [SdkState and IOneAgentInfo](#sdkstate-and-ioneagentinfo))\n* process monitoring is enabled in Dynatrace\n* you have set the OneAgent SDK [logging callback](#logging-callback) and check its output\n\nAlso note that injection of the OneAgent code module will not work if you start your application from within Visual\nStudio. In that case the SDK will behave as if OneAgent is not installed. If you need to debug your application with\nthe code module injected, you can start the application from Explorer or `cmd.exe` and then attach Visual Studio as\ndebugger to the running process (Debug -\u003e Attach to Process...).\n\n## API Concepts\n\nCommon concepts of the Dynatrace OneAgent SDK are explained the\n[Dynatrace OneAgent SDK repository](https://github.com/Dynatrace/OneAgent-SDK).\n\n### IOneAgentSdk object\n\nUse `OneAgentSdkFactory.CreateInstance` to obtain an instance of `IOneAgentSDK`, which is used to create tracers\nand info objects.\nYou should reuse this object over the whole application and if possible CLR lifetime:\n\n```csharp\nIOneAgentSdk oneAgentSdk = OneAgentSdkFactory.CreateInstance();\n```\n\n\u003ca name=\"tracecontext\"\u003e\u003c/a\u003e\n\n## Trace Context\n\nAn instance of the `OneAgentSDK` can be used to get the current `ITraceContextInfo` which holds information\nabout the *Trace-Id* and *Span-Id* of the current PurePath node.\nThis information can then be used to provide e.g. additional context in log messages.\n\nPlease note that `TraceContextInfo` is not intended for tagging or context-propagation use cases.\nDedicated APIs (e.g. [remote calls](#remoting) or [web requests](#webreqeusts)) as well as\nbuilt-in OneAgent sensors take care of linking services correctly.\n\n```csharp\nITraceContextInfo traceContextInfo = oneAgentSdk.TraceContextInfo;\nstring traceId = traceContextInfo.TraceId;\nstring spanId = traceContextInfo.SpanId;\n_logger.LogInformation($\"[!dt dt.trace_id={traceId},dt.span_id={spanId}] sending request ...\");\n```\n\n### Tracers\n\nTo trace any kind of call you first need to create a Tracer. The Tracer object represents the logical and physical\nendpoint that you want to call. A Tracer serves two purposes. First to time the call (duration, cpu and more) and\nreport errors. That is why each Tracer has these four methods. Either one of the `Error` methods must be called at\nmost once, and it must be in between `Start` and `End`. Each Tracer can only be used once and you need to create a\nnew instance for each request/call that you want to trace (i.e., `Start` cannot be called twice on the same instance).\n\n```csharp\nvoid Start();\n\nvoid Error(Exception exception);\n\nvoid Error(String message);\n\nvoid End();\n```\n\nThe `Start` method only supports synchronous methods (in other words C# methods without the `async` keyword).\nIf you call `Start()` in an async method, then with high probability the SDK won't capture the specific data.\n\nSample usage:\n\n```csharp\npublic static void SampleMethod()\n{\n    IOneAgentSdk oneAgentSdk = OneAgentSdkFactory.CreateInstance();\n    IDatabaseInfo dbInfo = oneAgentSdk.CreateDatabaseInfo(\"MyDb\", \"MyVendor\", ChannelType.TCP_IP, \"database.example.com:1234\");\n    IDatabaseRequestTracer dbTracer = oneAgentSdk.TraceSQLDatabaseRequest(dbInfo, \"Select * From AA\");\n\n    dbTracer.Start();\n    try\n    {\n        DatabaseApi.DatabaseCall();\n    }\n    catch (Exception e)\n    {\n        dbTracer.Error(e);\n        // handle or rethrow\n    }\n    finally\n    {\n        dbTracer.End();\n    }\n}\n\n```\n\n\u003e **Note:** Previous versions of the OneAgent SDK supported tracing of asynchronous methods (which are C# methods\n\u003e that are marked with the `async` keyword) using the method `StartAsync()`. This method has been **removed** for\n\u003e technical reasons and the way of tracing asynchronous code is the `TraceAsync` method (see below).\n\nThe SDK also offers a convenient `Trace` method. This method can be called in both asynchronous and\nsynchronous methods. In case of an async method you can pass the given async method to the `TraceAsync` method and\nawait on the result of the `TraceAsync` method.\n\n```csharp\nvoid Trace(Action action);\n\nT Trace\u003cT\u003e(Func\u003cT\u003e func);\n\nTask TraceAsync(Func\u003cTask\u003e func);\n\nTask\u003cT\u003e TraceAsync\u003cT\u003e(Func\u003cTask\u003cT\u003e\u003e func);\n```\n\nSample usage:\n\n```csharp\npublic static async Task SampleMethodAsync()\n{\n    IOneAgentSdk oneAgentSdk = OneAgentSdkFactory.CreateInstance();\n    IDatabaseInfo dbInfo = oneAgentSdk.CreateDatabaseInfo(\"MyDb\", \"MyVendor\", ChannelType.TCP_IP, \"database.example.com:1234\");\n    IDatabaseRequestTracer dbTracer = oneAgentSdk.TraceSQLDatabaseRequest(dbInfo, \"Select * From AA\");\n\n    var result = await dbTracer.TraceAsync(() =\u003e DatabaseApi.AsyncDatabaseCall());\n}\n```\n\nThe `Trace` method internally calls the `Start` method.\nIn case of an exception it also calls the `Error` method and it finally calls the `End` method.\n\nTo summarize this, in case of\n\n* synchronous methods you should use the `Trace` method but can also use the `Start`, `End` and `Error` methods\n* asynchronous methods you can use the `TraceAsync` method.\n\n\u003e NOTE: Due to internal limitations `TraceAsync` does not currently reliably connect child nodes. If there are child nodes\n\u003e started during a call to `TraceAsync`, they might be connected to the parent of the `TraceAsync`, if any, might become\n\u003e separate root paths, or might be suppressed entirely.\n\u003e\n\u003e Consider using `Trace` as a workaround, but note that asynchronous parts of the execution after `Trace` returns will\n\u003e not be tracked by the node created by `Trace`. In particular, exceptions thrown in the asynchronous part\n\u003e (approximately after `Trace` returns) are potentially missed.\n\nSome tracers offer methods to provide information in addition to the parameters required for creating the tracer using\nthe `IOneAgentSdk` object. These additional pieces of information might be relevant for service detection and naming.\nIf this is the case, they can only be set *before* starting the tracer as stated in the respective method documentation.\nAfter ending a tracer, it must not be used any longer. Since none of its methods must be called, no further information\ncan be provided to an ended tracer.\n\nTo allow tracing across process and technology boundaries, tracers can be supplied with so-called tags.\nTags are strings or byte arrays generated by the SDK that enable Dynatrace to trace a transaction end-to-end.\nThe user has to take care of transporting the tag from one process to the other.\n\n## Features\n\nThe feature sets differ slightly with each language implementation. More functionality will be added over time, see\n[Planned features for OneAgent SDK](https://answers.dynatrace.com/spaces/483/dynatrace-product-ideas/idea/198106/planned-features-for-oneagent-sdk.html)\nfor details on upcoming features.\n\nA more detailed specification of the features can be found in\n[Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK).\n\n|Feature                                                                         |Required OneAgent SDK for .NET  version|\n|:-------------------------------------------------------------------------------|:--------------------------------------|\n|ITraceContextInfo                                                               |\u003e=1.8.0                                |\n|Support for W3C Trace Context (`IOutgoingWebRequestTracer.InjectTracingHeaders`)|\u003e=1.6.0                                |\n|Trace incoming web requests                                                     |\u003e=1.5.0                                |\n|Trace outgoing web requests                                                     |\u003e=1.4.0                                |\n|Custom request attributes                                                       |\u003e=1.4.0                                |\n|In-process linking, `SdkState` and `IOneAgentInfo`                              |\u003e=1.3.0                                |\n|Trace messaging                                                                 |\u003e=1.2.0                                |\n|Trace remote calls                                                              |\u003e=1.1.0                                |\n|Logging callback                                                                |\u003e=1.1.0                                |\n|Trace SQL database requests                                                     |\u003e=1.0.0-alpha                          |\n\n### Trace SQL database requests\n\nA SQL database request is traced by calling `TraceSQLDatabaseRequest`.\nSee [DatabaseRequestTracerSamples.cs](/sample/Dynatrace.OneAgent.Sdk.Sample/DatabaseRequestTracerSamples.cs)\nfor the full list of examples (sync/async/lambda/exception/...)\n\n**Example of a synchronous database call (see [DatabaseRequestTracerSamples.cs](/sample/Dynatrace.OneAgent.Sdk.Sample/DatabaseRequestTracerSamples.cs) for more details):**\n\n```csharp\nIDatabaseInfo dbInfo = oneAgentSdk.CreateDatabaseInfo(\"MyDb\", \"MyVendor\", ChannelType.TCP_IP, \"database.example.com:1234\");\nIDatabaseRequestTracer dbTracer = oneAgentSdk.TraceSQLDatabaseRequest(dbInfo, \"Select * From AA\");\n\ndbTracer.Trace(() =\u003e ExecuteDbCallVoid());\n```\n\n**Example of tracing database call in an async lambda expression (see [DatabaseRequestTracerSamples.cs](/sample/Dynatrace.OneAgent.Sdk.Sample/DatabaseRequestTracerSamples.cs) for more details):**\n\n```csharp\nIDatabaseInfo dbInfo = oneAgentSdk.CreateDatabaseInfo(\"MyDb\", \"MyVendor\", ChannelType.TCP_IP, \"database.example.com:1234\");\nIDatabaseRequestTracer dbTracer = oneAgentSdk.TraceSQLDatabaseRequest(dbInfo, \"Select * From AA\");\n\nint res = dbTracer.Trace(() =\u003e ExecuteDbCallInt());\n```\n\nSee also our initial blog post about the OneAgent SDK for .NET, which shows how databases can be traced using the\n`IDatabaseRequestTracer` and how these traces are presented and analyzed in Dynatrace:\n[Extend framework support with OneAgent SDK for .NET](https://www.dynatrace.com/news/blog/extend-framework-support-with-oneagent-sdk-for-net-eap/)\n\nPlease note that SQL database traces are only created if they occur within some other SDK trace (e.g. incoming remote call)\nor a OneAgent built-in trace (e.g. incoming web request).\n\n### Trace remote calls\n\nYou can use the SDK to trace proprietary IPC communication from one process to the other.\nThis will enable you to see full Service Flow, PurePath and Smartscape topology for remoting technologies\nthat Dynatrace is not aware of.\n\nTo trace any kind of remote call you first need to create a Tracer. The Tracer object represents the endpoint\nthat you want to call, as such you need to supply the name of the remote service and remote method.\nIn addition you need to transport the tag in your remote call to the server side if you want to trace it end-to-end.\n\n```csharp\nIOutgoingRemoteCallTracer outgoingRemoteCallTracer = oneAgentSdk.TraceOutgoingRemoteCall(\n    \"RemoteMethod\", \"RemoteServiceName\",\n    \"mrcp://endpoint/service\", ChannelType.TCP_IP, \"myRemoteHost:1234\");\noutgoingRemoteCallTracer.SetProtocolName(\"MyRemoteCallProtocol\");\n\noutgoingRemoteCallTracer.Start();\ntry\n{\n    string tag = outgoingRemoteCallTracer.GetDynatraceStringTag();\n    // make the call and transport the tag across to the server to link both sides of the remote call together\n}\ncatch (Exception e)\n{\n    outgoingRemoteCallTracer.Error(e);\n    // handle or rethrow\n}\nfinally\n{\n    outgoingRemoteCallTracer.End();\n}\n```\n\nOn the server side you need to wrap the handling and processing of your remote call as well.\nThis will not only trace the server side call and everything that happens, it will also connect it to the calling side.\n\n```csharp\nIIncomingRemoteCallTracer incomingRemoteCallTracer = oneAgentSdk\n    .TraceIncomingRemoteCall(\"RemoteMethod\", \"RemoteServiceName\", \"mrcp://endpoint/service\");\n\nstring incomingDynatraceStringTag = ...; // retrieve from incoming call metadata\n // link both sides of the remote call together\nincomingRemoteCallTracer.SetDynatraceStringTag(incomingDynatraceStringTag);\nincomingRemoteCallTracer.SetProtocolName(\"MyRemoteCallProtocol\");\n\nincomingRemoteCallTracer.Start();\ntry\n{\n    ProcessRemoteCall();\n}\ncatch (Exception e)\n{\n    incomingRemoteCallTracer.Error(e);\n    // handle or rethrow\n}\nfinally\n{\n    incomingRemoteCallTracer.End();\n}\n```\n\n### Trace messaging\n\nYou can use the SDK to trace messages sent or received via messaging \u0026 queuing systems.\nWhen tracing messages, we distinguish between:\n\n* sending a message\n* receiving a message\n* processing a received message\n\nTo trace an outgoing message, you need to create an `IMessagingSystemInfo` and call `TraceOutgoingMessage`\nwith that instance:\n\n```csharp\nstring serverEndpoint = \"messageserver.example.com:1234\";\nstring topic = \"my-topic\";\nIMessagingSystemInfo messagingSystemInfo = oneAgentSdk\n    .CreateMessagingSystemInfo(\"MyCustomMessagingSystem\", topic, MessageDestinationType.TOPIC, ChannelType.TCP_IP, serverEndpoint);\n\nIOutgoingMessageTracer outgoingMessageTracer = oneAgentSdk.TraceOutgoingMessage(messagingSystemInfo);\n\noutgoingMessageTracer.Start();\ntry\n{\n    Message message = new Message();\n    message.CorrelationId = \"my-correlation-id-1234\"; // optional, determined by application\n\n    // transport the Dynatrace tag along with the message to allow the outgoing message tracer to be linked\n    // with the message processing tracer on the receiving side\n    message.Headers[OneAgentSdkConstants.DYNATRACE_MESSAGE_PROPERTYNAME] = outgoingMessageTracer.GetDynatraceByteTag();\n\n    SendResult result = MyMessagingSystem.SendMessage(message);\n\n    outgoingMessageTracer.SetCorrelationId(message.CorrelationId);    // optional\n    outgoingMessageTracer.SetVendorMessageId(result.VendorMessageId); // optional\n}\ncatch (Exception e)\n{\n    outgoingMessageTracer.Error(e);\n    // handle or rethrow\n    throw e;\n}\nfinally\n{\n    outgoingMessageTracer.End();\n}\n```\n\nOn the incoming side, we need to differentiate between the blocking receiving part and processing the received message.\nTherefore two different tracers are used: `IIncomingMessageReceiveTracer` and `IIncomingMessageProcessTracer`.\n\n```csharp\nstring serverEndpoint = \"messageserver.example.com:1234\";\nstring topic = \"my-topic\";\nIMessagingSystemInfo messagingSystemInfo = oneAgentSdk\n    .CreateMessagingSystemInfo(\"MyCustomMessagingSystem\", topic, MessageDestinationType.TOPIC, ChannelType.TCP_IP, serverEndpoint);\n\nIIncomingMessageReceiveTracer receiveTracer = oneAgentSdk.TraceIncomingMessageReceive(messagingSystemInfo);\n\nreceiveTracer.Start();\ntry\n{\n    // blocking call until message is available:\n    ReceiveResult receiveResult = MyMessagingSystem.ReceiveMessage();\n    Message message = receiveResult.Message;\n\n    IIncomingMessageProcessTracer processTracer = oneAgentSdk.TraceIncomingMessageProcess(messagingSystemInfo);\n\n    // retrieve Dynatrace tag created using the outgoing message tracer to link both sides together:\n    if (message.Headers.ContainsKey(OneAgentSdkConstants.DYNATRACE_MESSAGE_PROPERTYNAME))\n    {\n        processTracer.SetDynatraceByteTag(message.Headers[OneAgentSdkConstants.DYNATRACE_MESSAGE_PROPERTYNAME]);\n    }\n    // start processing:\n    processTracer.Start();\n    processTracer.SetCorrelationId(message.CorrelationId);           // optional\n    processTracer.SetVendorMessageId(receiveResult.VendorMessageId); // optional\n    try\n    {\n        ProcessMessage(message); // do the work ...\n    }\n    catch (Exception e)\n    {\n        processTracer.Error(e);\n        // handle or rethrow\n        throw e;\n    }\n    finally\n    {\n        processTracer.End();\n    }\n}\ncatch (Exception e)\n{\n    receiveTracer.Error(e);\n    // handle or rethrow\n    throw e;\n}\nfinally\n{\n    receiveTracer.End();\n}\n```\n\nIn case of a non-blocking receive (e.g. via an event handler), there is no need to use\n`IIncomingMessageReceiveTracer` - just trace processing of the message by using the `IIncomingMessageProcessTracer`:\n\n```csharp\nvoid OnMessageReceived(ReceiveResult receiveResult)\n{\n    string serverEndpoint = \"messageserver.example.com:1234\";\n    string topic = \"my-topic\";\n    IMessagingSystemInfo messagingSystemInfo = oneAgentSdk\n        .CreateMessagingSystemInfo(\"MyCustomMessagingSystem\", topic, MessageDestinationType.TOPIC, ChannelType.TCP_IP, serverEndpoint);\n\n    Message message = receiveResult.Message;\n\n    IIncomingMessageProcessTracer processTracer = oneAgentSdk.TraceIncomingMessageProcess(messagingSystemInfo);\n\n    // retrieve Dynatrace tag created using the outgoing message tracer to link both sides together:\n    if (message.Headers.ContainsKey(OneAgentSdkConstants.DYNATRACE_MESSAGE_PROPERTYNAME))\n    {\n        processTracer.SetDynatraceByteTag(message.Headers[OneAgentSdkConstants.DYNATRACE_MESSAGE_PROPERTYNAME]);\n    }\n    // start processing:\n    processTracer.Start();\n    processTracer.SetCorrelationId(message.CorrelationId);           // optional\n    processTracer.SetVendorMessageId(receiveResult.VendorMessageId); // optional\n    try\n    {\n        ProcessMessage(message); // do the work ...\n    }\n    catch (Exception e)\n    {\n        processTracer.Error(e);\n        // handle or rethrow\n        throw e;\n    }\n    finally\n    {\n        processTracer.End();\n    }\n}\n```\n\nSee also:\n\n* The documentation on [messaging tracers in the specification repository](https://github.com/Dynatrace/OneAgent-SDK#messaging).\n* This blog post explaining [end-to-end tracing for additional message queues with the OneAgent SDK\n](https://www.dynatrace.com/news/blog/end-to-end-tracing-for-additional-message-queues-with-oneagent-sdk/).\n\n### Trace web requests\n\n#### Trace outgoing web requests\n\nYou can use the SDK to trace outgoing web requests. This allows tracing web requests performed using HTTP client\nlibraries which are not supported by the Dynatrace OneAgent out-of-the-box.\nAlways include the Dynatrace header with the request as it is required to match the request on the server side.\nThis ensures requests are traced end-to-end when the server is monitored using a OneAgent or OneAgent SDK.\n\n```csharp\nIOutgoingWebRequestTracer tracer = SampleApplication.OneAgentSdk.TraceOutgoingWebRequest(request.Url, request.Method);\n\nforeach (KeyValuePair\u003cstring, string\u003e header in request.Headers)\n{\n    tracer.AddRequestHeader(header.Key, header.Value);\n}\n\nawait tracer.TraceAsync(async () =\u003e\n{\n    // add the Dynatrace tag or W3C Trace Context (based on your configuration) to request headers to allow\n    // the agent in the web server to link the request together for end-to-end tracing\n    tracer.InjectTracingHeaders((key, value) =\u003e request.Headers[key] = value);\n\n    MyCustomHttpResponse response = await request.ExecuteAsync();\n\n    tracer.SetStatusCode(response.StatusCode);\n\n    foreach (KeyValuePair\u003cstring, string\u003e header in response.Headers)\n    {\n        tracer.AddResponseHeader(header.Key, header.Value);\n    }\n});\n```\n\n#### Trace incoming web requests\n\nYou can use the SDK to trace incoming web requests. This might be useful if Dynatrace does not support\nthe web server framework or language processing the incoming web requests.\n\nTo trace an incoming web request you first need to create an `IWebApplicationInfo` object.\nThis info object represents the endpoint of your web server (web server name, application name and context root; see our\n[documentation](https://www.dynatrace.com/support/help/how-to-use-dynatrace/services-and-transactions/basic-concepts/service-detection-and-naming/#web-request-services)\nfor further information).\nThis object should be reused for all traced web requests within the same application.\n\n```csharp\nIWebApplicationInfo webAppInfo =\n    oneAgentSdk.CreateWebApplicationInfo(\"WebShopProduction\", \"AuthenticationService\", \"/api/auth\");\n//                                       Web server name      Application ID           Context Root\n```\n\nTo trace an incoming web request you then need to create a Tracer object.\nMake sure you provide all HTTP headers from the request to the SDK by calling `AddRequestHeader`.\nThis allows both sides of the web requests to be linked together for end-to-end tracing.\n\n```csharp\nIIncomingWebRequestTracer tracer = oneAgentSdk.TraceIncomingWebRequest(webAppInfo, request.Url, request.Method);\ntracer.SetRemoteAddress(request.RemoteClientAddress);\n\n// adding all request headers ensures that tracing headers required\n// for end-to-end linking of requests are provided to the SDK\nforeach (KeyValuePair\u003cstring, string\u003e header in request.Headers)\n{\n    tracer.AddRequestHeader(header.Key, header.Value);\n}\nforeach (KeyValuePair\u003cstring, string\u003e param in request.PostParameters)\n{\n    tracer.AddParameter(param.Key, param.Value);\n}\n\n// start tracer\nreturn tracer.Trace(() =\u003e\n{\n    // handle request and build response ...\n\n    foreach (KeyValuePair\u003cstring, string\u003e header in response.Headers)\n    {\n        tracer.AddResponseHeader(header.Key, header.Value);\n    }\n    tracer.SetStatusCode(response.StatusCode);\n\n    return response;\n});\n```\n\n### In-process linking\n\nIn order to trace interactions between different threads, so-called in-process links are used.\nAn in-process link is created on the originating thread and then used for creating an `IInProcessLinkTracer`\non the target thread.\n\nCalls detected while the tracer is active (i.e., between `Start` and `End` or within any of the `Trace` methods) are\ntraced as part of the originating service call.\nThis works for calls detected out-of-the-box by the OneAgent as well as calls traced using the OneAgent SDK.\n\n```csharp\n// create an in-process link on the originating thread\nIInProcessLink inProcessLink = oneAgentSdk.CreateInProcessLink();\n\n// delegate work to another thread, in this case we use a custom background worker implementation\ncustomBackgroundWorker.EnqueueWorkItem(() =\u003e\n{\n    // use the in-process link to link the PurePath on the target thread to its origin\n    IInProcessLinkTracer inProcessLinkTracer = oneAgentSdk.TraceInProcessLink(inProcessLink);\n    inProcessLinkTracer.Start();\n    // processing and performing further calls...\n    inProcessLinkTracer.End();\n\n    // calls executed after ending the IInProcessLinkTracer will\n    // *not* be traced as part of the originating service call\n});\n```\n\nNote that you can re-use in-process links to create multiple in-process link tracers.\n\n### Add custom request attributes\n\nYou can use the SDK to add custom request attributes to the currently traced service call.\nThese attributes (key-value pairs) can be used to search and filter requests in Dynatrace.\n\nIn order to add a custom request attribute, the `AddCustomRequestAttribute` methods are used.\nNo reference to a tracer is needed as OneAgent SDK will select the currently active PurePath.\nThis may be a PurePath created by OneAgent SDK or a PurePath created by built-in sensors of the OneAgent.\nThe methods take two arguments - a key, specifying the name of the attribute, and a value,\nwhich can be either a `string`, `long` or `double`.\nThese methods can be called several times to add multiple attributes to the same request.\nIf the same attribute key is used several times, all values will be recorded.\n\n```csharp\noneAgentSdk.AddCustomRequestAttribute(\"region\", \"EMEA\");\noneAgentSdk.AddCustomRequestAttribute(\"salesAmount\", 2500);\noneAgentSdk.AddCustomRequestAttribute(\"service-quality\", 0.707106);\n\noneAgentSdk.AddCustomRequestAttribute(\"account-group\", 1);\noneAgentSdk.AddCustomRequestAttribute(\"account-group\", 2);\noneAgentSdk.AddCustomRequestAttribute(\"account-group\", 3);\n```\n\nIf no service call is currently being traced, the attributes will be discarded.\nTherefore, for calls traced with OneAgent SDK, custom request attributes have to be added *after*\nstarting the tracer (or from within an `ITracer.Trace` method) in order to have an active PurePath.  \nStrings exceeding the lengths specified [here](https://github.com/Dynatrace/OneAgent-SDK#string-length)\nwill be truncated.\n\nSee also our blog post explaining how custom request attributes are configured, displayed and\nanalyzed in Dynatrace:\n[Capture any request attributes using OneAgent SDK\n](https://www.dynatrace.com/news/blog/capture-any-request-attributes-using-oneagent-sdk/)\n\n### Logging callback\n\nThe SDK provides a logging-callback to give information back to the calling application in case of an error.\nThe user application has to provide a callback like the following:\n\n```csharp\nclass StdErrLoggingCallback : ILoggingCallback\n{\n    public void Error(string message) =\u003e Console.Error.WriteLine(\"[OneAgent SDK] Error:   \" + message);\n    public void Warn (string message) =\u003e Console.Error.WriteLine(\"[OneAgent SDK] Warning: \" + message);\n}\n\npublic static void Main(string[] args)\n{\n    IOneAgentSdk oneAgentSdk = OneAgentSdkFactory.CreateInstance();\n    var loggingCallback = new StdErrLoggingCallback();\n    oneAgentSdk.SetLoggingCallback(loggingCallback);\n}\n```\n\nIn general it is a good idea to forward these logging events to your application specific logging framework.\n\n### SdkState and IOneAgentInfo\n\nFor troubleshooting and avoiding any ineffective tracing calls you can check the state of the SDK as follows:\n\n```csharp\nIOneAgentSdk oneAgentSdk = OneAgentSdkFactory.CreateInstance();\nSdkState state = oneAgentSdk.CurrentState;\nswitch (state)\n{\n    case SdkState.ACTIVE:               // SDK ready for use\n    case SdkState.TEMPORARILY_INACTIVE: // capturing disabled, tracing calls can be spared\n    case SdkState.PERMANENTLY_INACTIVE: // SDK permanently inactive, tracing calls can be spared\n}\n```\n\nIt is good practice to check the SDK state regularly as it may change at every point of time\n(except PERMANENTLY_INACTIVE, which never changes over application lifetime).\n\nInformation about the OneAgent used by the SDK can be retrieved using `IOneAgentInfo`:\n\n```csharp\nIOneAgentSdk oneAgentSdk = OneAgentSdkFactory.CreateInstance();\nIOneAgentInfo agentInfo = oneAgentSdk.AgentInfo;\nif (agentInfo.AgentFound)\n{\n    Console.WriteLine($\"OneAgent Version: {agentInfo.Version}\");\n    if (agentInfo.AgentCompatible)\n    {\n        // agent is fully compatible with current SDK version\n    }\n}\n```\n\nSee [SdkState.cs](./src/Api/Enums/SdkState.cs) and [IOneAgentInfo.cs](./src/Api/Infos/IOneAgentInfo.cs)\nfor further information.\n\n## Further readings\n\n* [What is the OneAgent SDK?](https://www.dynatrace.com/support/help/extend-dynatrace/oneagent-sdk/what-is-oneagent-sdk/) in the Dynatrace documentation\n* [Feedback \u0026 Roadmap thread in AnswerHub](https://answers.dynatrace.com/spaces/483/dynatrace-product-ideas/idea/198106/planned-features-for-oneagent-sdk.html)\n\n## Help \u0026 Support\n\n**Support policy**\n\nThe Dynatrace OneAgent SDK for .NET has GA status. The features are fully supported by Dynatrace.\n\nFor detailed support policy see [Dynatrace OneAgent SDK help](https://github.com/Dynatrace/OneAgent-SDK#help).\n\n### Get Help\n\n* Ask a question in the [product forums](https://answers.dynatrace.com/spaces/482/view.html)\n* Read the [product documentation](https://www.dynatrace.com/support/help/)\n\n### Open a [GitHub issue](https://github.com/Dynatrace/OneAgent-SDK-for-dotnet/issues) to\n\n* Report minor defects, minor items or typos\n* Ask for improvements or changes in the SDK API\n* Ask any questions related to the community effort\n\nSLAs don't apply for GitHub tickets\n\n### Customers can open a ticket on the [Dynatrace support portal](https://support.dynatrace.com/supportportal/) to\n\n* Get support from the Dynatrace technical support engineering team\n* Manage and resolve product-related technical issues\n\nSLAs apply according to the customer's support level.\n\n## Release Notes\n\nsee also [Releases](https://github.com/Dynatrace/OneAgent-SDK-for-dotnet/releases)\n\n|Version    |Description                                  |\n|:----------|:--------------------------------------------|\n|1.8.0      |Removes deprecated APIs and types. Adds `TraceContextInfo`. |\n|1.7.1      |Deprecates metrics-related types and APIs |\n|1.7.0      |Adds metrics support (preview only) and deprecates `ITracer.StartAsync` API method |\n|1.6.0      |Adds W3C Trace Context support (`IOutgoingWebRequestTracer.InjectTracingHeaders`)|\n|1.5.0      |Adds incoming web request tracing |\n|1.4.0      |Adds custom request attributes and outgoing web request tracing |\n|1.3.0      |Adds in-process linking, `ITracer.Error(Exception)`, `SdkState` and `IOneAgentInfo` |\n|1.2.0      |Adds message tracing                         |\n|1.1.0      |First GA release - starting with this version OneAgent SDK for .NET is now officially supported by Dynatrace|\n|1.1.0-alpha|Adds remote call tracing and logging callback|\n|1.0.0-alpha|EAP release                                  |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdynatrace%2Foneagent-sdk-for-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdynatrace%2Foneagent-sdk-for-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdynatrace%2Foneagent-sdk-for-dotnet/lists"}