Documentation forSolarWinds Observability

.NET Library instrumentation SDK

Get started

Two different NuGet packages can be used to make the custom SDK available to your application. However, only one should be added to your project. Which NuGet package you should use depends on the installation method used for the .NET APM library. For an overview of the installation options, see Add a .NET service.

The SDK namespace provided by both NuGet packages is AppOptics.Instrumentation.

SolarWindsAPM.Agent.Api NuGet package

If you install the .NET APM library using the Windows installer (SolarWindsAPM_DotNetAgent_Setup.exe) or a Linux compressed archive (for example, solarwinds-apm-dotnet-agent-package.linux.x86_64.tgz), SolarWinds recommends you use the SolarWindsAPM.Agent.Api NuGet package to add custom instrumentation to your .NET Framework or .NET 6+ application.

To use the custom SDK in your application code, add the SolarWindsAPM.Agent.Api NuGet package to your application's project file and reference the AppOptics.Instrumentation namespace.

If you have custom SDK calls in your application, the .NET Library must be installed and enabled when your application is executed.

SolarWindsAPM.Agent NuGet package

The custom SDK is also part of the SolarWindsAPM.Agent NuGet package , which provides both manual and automatic instrumentation. If you install the .NET APM Library by adding the SolarWindsAPM.Agent NuGet package to your project, the custom SDK will be available to use in your application immediately. Add custom instrumentation to your application by referencing the AppOptics.Instrumentation namespace.

Configure the APM Library

If the application you are adding the custom instrumentation to is a Windows service or stand-alone application (for example, NON-IIS) you must ensure that you have enabled instrumentation for your application. For detailed instructions see Configure the .NET Library.

Customize out-of-box instrumentation

Customization involves adding hooks from our public SDK to your code so that you can take advantage of additional filtering capabilities on the dashboard, change how requests are traced, or capture additional information during the trace.

Starting a trace

Sometimes the default instrumentation might not capture traces on certain systems (custom web framework or console applications, for example), but traces can still be created by using the Trace.StartTrace() and Trace.EndTrace() SDK methods, and the optional Trace.WaitUntilAgentReady() call to ensure library readiness.

Also see the section tracing across external spans on how to use the Trace.StartTrace() method to continue a trace from an upstream service.

Custom spans

By default, the .NET Framework instrumentation creates a span for the code itself. For example, IIS, WCF-Service, ado-mssql and the .NET Core SDK Middleware create a root span for requests, aspnet-core. If these spans do not provide enough visibility, you can further divide your code into sub-spans. How you segment your application modules and sub-system into spans is entirely up to you. For example, the default instrumentation might not recognize calls to external processes, so you could use the SDK to manually create spans for them. Similarly, a multi-threaded app can have individual spans for each of its asynchronous operations. To create a custom span, identify the section of code you would like to appear as a span, and wrap it in a pair of entry and exit events as shown.

EntryTraceEvent event = Trace.CreateEntryEvent("my_span_name");
event.AddInfo("something", "interesting");
event.Report();
...
ExitTraceEvent event = Trace.CreateExitEvent("my_span_name");
event.Report();

Two ways to create a span

The attribute method of adding a custom span is only applicable to the .NET Library SDK.

If you want to create a custom span for a particular method, there are two ways to do this. The first is to wrap it in a pair of entry and exit events. But this technique becomes burdensome if the method is called more than once and you want to trace each of those calls. Instead, you can use the second method, which is the TraceAttribute attribute class. Attribute classes are a convenient way of associating declarative information with program entities, in this case the method you want to trace. The syntax for associating the TraceAttribute with a method is shown below. Try to declare the association as close to the method as possible, for example within the class just above the method definition. TraceAttribute requires one positional parameter, which must be the method name. The method name also becomes the custom span name. TraceAttribute accepts to two optional named parameters. For more information, see Backtraces and return values.

class MyClass {
[TraceAttribute("AnnotatedMethodcharRef", Backtrace = true, ReturnValue = true)]
  public void AnnotatedMethodcharRef(ref char value)
  {
    // your method definition goes here
  }
}

Tracing multi-threaded applications

The following steps are only applicable for .NET Framework 3.5 applications. For .NET Framework 4.6.2 and .NET 6.0+, the context is automatically propagated to child threads.

You might want to report events from background or child threads and associate them with the thread that spawned them. Assuming that a trace was already started in the parent thread, complete the following steps:

  1. Pass the trace context to the child thread using TraceContext.GetCurrent().
  2. Set the context within the child thread using Trace.SetAsCurrent().
  3. Mark the thread as asynchronous by calling EntryTraceEvent.SetAsync() on the entry event of the child span.
  4. Clean up the thread by calling TraceContext.ClearCurrentContext() before returning it to the threadpool.

If the context needs to be passed to the exit event creation, TraceContext.GetCurrent() must be called after the entry event is reported to get the latest context. The latest context can then be passed to the exit event creation. SetAsCurrent() must be called on the passed context, and then the exit event can be created.

System.Threading.Thread myThread = new System.Threading.Thread(this.DoSomeWork1);
myThread.Start(TraceContext.GetCurrent());

public void DoSomeWork1(object data)
{
  TraceContext currentContext = data as TraceContext;
  if(currentContext != null)
  {
    currentContext.SetAsCurrent();
    
    var asyncEntryEvent = Trace.CreateEntryEvent("my_span_name");
    asyncEntryEvent.AddInfo("something", "interesting");
    asyncEntryEvent.SetAsync();
    asyncEntryEvent.Report();
    
    // Code that needs to be traced
    var exitEvent = Trace.CreateExitEvent("my_span_name");
    exitEvent.AddInfo("something", "interesting");
    exitEvent.Report();
    TraceContext.ClearCurrent();
  }
}

Tracing across external spans

While instrumenting your code, you might want to trace a request across processes or hosts. This can be done by passing the traceparent and tracestate between them.

  1. The client should call Trace.GetCurrent(), which returns the current context as a TraceContext object. If the request has been sampled, a TraceContext object is returned regardless of whether the request is being traced or not. If a request is being traced, the Traceparent property of the TraceContext object ends in 01. The .NET Library uses the trace context headers defined by the W3C Trace Context (https://www.w3.org/TR/trace-context/#trace-context-http-headers-format).
  2. The client should then send the Traceparent and Tracestate values to the remote process by any means, but probably through the traceparent and tracestate HTTP header.
  3. The remote process should read the identifiers (traceparent and tracestate) and input it to Trace.StartTrace().
  4. When the remote process is done, it should end the trace using Trace.EndTrace().

Collecting additional trace details

Any additional information you collect is presented on the trace details page.

Backtraces and return values

Backtraces and return values can be included when you are creating a custom span for an individual function by way of the TraceAttribute class. To include a backtrace in the entry event of the span, set the backtrace parameter of the TraceAttribute class to true. To include a return value in the exit event of the span, set ReturnValue to true.

Add info events

There are two reasons you might want to create an info event. The first is to attach any meta data that might be of interest to you during later analysis of a trace. The other reason is to take full advantage of Traces Explorer filtering capability. You can classify spans by attaching a pre-defined set of specified key/value pairs. Then from the Traces Explorer, you can filter for traces with that span type. See Special span types for more information. To add info to an span, after creating the info event, call .AddInfo() on it one or more times as shown. In this case the information events are displayed on the raw span data tab on the trace details page. If all of the key/value pairs for special interpretation are present, the span type is reflected in the span details tab.

InfoTraceEvent event = Trace.CreateInfoEvent("my_span_name");
event.AddInfo("something", "interesting");
event.AddInfo("something_else", "also_interesting");
event.Report();

Report errors

Create an error event for an exception, including a backtrace.

try {
  // your code that might throw an exception goes here ...
} catch(exceptionType exception) {
  Trace.ReportException(exception);
  // the rest of your exception handler ...
}

Complete examples

The following examples use the .NET instrumentation SDK to illustrate custom instrumentation concepts such as starting a trace and adding spans for an application.

.NET Console App

This demonstrates instrumenting a simple console application written in C#. Note that once the trace is started via SDK, any execution path through supported components will be auto-instrumented without needing extra SDK calls. The example code can be used in either a .NET Framework, .NET Core, or .NET application.

using AppOptics.Instrumentation;

namespace ConsoleExampleApp
{
  class Program
  {
    private const string CONSOLE_SPAN_NAME = "console-example-app";
    
    static void Main(string[] args)
    {
      // The Trace.WaitUntilAgentReady method is used to ensure that the library is ready before the
      // console application is ran so that a trace will be generated.
      // The timeout parameter is set to 2000 milliseconds, if the library is not ready in 2000 milliseconds
      // the method will stop waiting and return false.
      var agentReady = Trace.WaitUntilAgentReady(2000, out int statusCode);
      
      // Debug logging if library ready returns false
      if (!agentReady)
      {
        System.Console.WriteLine("Agent isn't ready. Status code returned: {0}", statusCode);
      }
      
      // Start the trace by creating a StartTraceEvent and reporting it
      StartTraceEvent startTraceEvent = Trace.StartTrace(CONSOLE_SPAN_NAME);

      // The optional key "TransactionName" can be added to the start trace event
      // If a transaction name isn't specified, the transaction name is set to "custom_<start trace span name>"
      startTraceEvent.AddInfo("TransactionName", "console_test_command");
      startTraceEvent.Report();

      // The transaction name can also be set anytime before the end of the trace using the Trace.SetTransactionName method
      // Example: Trace.SetTransactionName("transaction_name");
      // Note: Thread.Sleep is used in the console example application so that spans with different timings
      //    are displayed when viewing traces in SolarWinds Observability
      System.Threading.Thread.Sleep(200);
      
      ProcessCommand(args);
      
      System.Threading.Thread.Sleep(100);
      // End the trace by creating a EndTraceEvent and reporting it
      // Note: Span name used for start trace event must match the span name for the end trace event
      EndTraceEvent endTraceEvent = Trace.EndTrace(CONSOLE_SPAN_NAME);
      endTraceEvent.Report();
    }

    public static void ProcessCommand(string[] args)
    {
      // The EntryTraceEvent and ExitTraceEvent can be used to create additional spans in the trace
      // The span name of the EntryTraceEvent must match the span name of the ExitTraceEvent
      EntryTraceEvent entryTraceEvent = Trace.CreateEntryEvent("command_one");
      entryTraceEvent.Report();
      
      // do command work
      System.Threading.Thread.Sleep(500);
      
      ExitTraceEvent exitTraceEvent = Trace.CreateExitEvent("command_one");
      exitTraceEvent.Report();
    }
  }
}
.NET Core: Distributed tracing with StartTrace, traceparent, and tracestate

This demonstrates propagating trace context between two simple console applications written in C# for .NET Core. The calling application uses StartTrace to start tracing and TraceContext.GetCurrent to get the current trace context. Then the caller passes the Traceparent and Tracestate from the TraceContext to the called external application.

using System;
using AppOptics.Instrumentation;
using System.Diagnostics;
using System.IO;

namespace coretestapp
{
  public class Example
  {
    string spanName = "example-trace";
    
    public void StartTrace()
    {
      System.Console.WriteLine("Starting trace");
      StartTraceEvent startEvent = AppOptics.Instrumentation.Trace.StartTrace(spanName);
      startEvent.Report();
    }
    
    public void EndTrace()
    {
      System.Console.WriteLine("Ending trace");
      EndTraceEvent endEvent = AppOptics.Instrumentation.Trace.EndTrace(spanName);
      endEvent.Report();
    }
    
    public void ExternalServiceSpan()
    {
      System.Console.WriteLine("\n****** Enter ExternalServiceSpan ***** \n");
      System.Console.WriteLine("Starting span for ExternalServiceSpan");
      
      string spanName = "example-span";
      
      EntryTraceEvent eventEntry = AppOptics.Instrumentation.Trace.CreateEntryEvent(spanName);
      eventEntry.Report();
      
      // Launch external app and pass the current trace id
      var traceContext = AppOptics.Instrumentation.Trace.GetCurrentTraceContext();
      string traceparent;
      string tracestate;
      if (traceContext != null)
      {
        traceparent = traceContext.Traceparent;
        tracestate = traceContext.Tracestate;
      }
      LaunchExternalApp(traceparent, tracestate);
      
      System.Console.WriteLine("Ending span");
      ExitTraceEvent eventExit = AppOptics.Instrumentation.Trace.CreateExitEvent(spanName);      
      eventExit.Report();
      
      System.Console.WriteLine("\n****** Exit ExternalServiceSpan ***** \n");
    }
    
    public bool LaunchExternalApp(string traceparent, string tracestate)
    {     
      // Path to external application directory
      
      string path = Directory.GetCurrentDirectory();
      
      #if DEBUG
      path += @"\..\..\..\coretestappexternal\bin\Debug\netcoreapp3.1\";
      
      #else
      path += @"\..\..\..\coretestappexternal\bin\Release\netcoreapp3.1\";
      
      #endif
      
      ProcessStartInfo processStartInfo = new ProcessStartInfo();
      processStartInfo.Arguments = path + "coretestappexternal.dll" + " " + traceparent + " " + tracestate;
      processStartInfo.FileName = "dotnet.exe";
      processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
      processStartInfo.CreateNoWindow = true;
      processStartInfo.RedirectStandardOutput = true;
      processStartInfo.WorkingDirectory = path;
      int exitCode;
      
      // Run the external process & wait for it to finish
      
      try
      {
        Process process = Process.Start(processStartInfo);
        
     
  
       
        
        // wait for process to exit
        
        process.WaitForExit();
        
        // retrieve application exit code
        
        exitCode = process.ExitCode;
        
        // when application exit with success process std output
        
        if(exitCode == 0)
        {
		return true;
          
        }
      }
      catch (Exception e)
      {
        Console.WriteLine("Exception: {0}.", e);
      }
      return false;
    }
    
    public void Run()
    {
      StartTrace();
      ExternalServiceSpan();
      EndTrace();
    }
  }
  
  public class Program
  {
    private const int WAIT_AGENT_TIMEOUT = 5000; // Wait timeout for library to be ready
    
    public static void Main(string[] args)
    {
      System.Console.WriteLine("Running application...");
      
      // Wait until library is ready
      
      System.Console.WriteLine("Waiting until agent is ready...");
      bool bIsReady = AppOptics.Instrumentation.Trace.WaitUntilAgentReady(WAIT_AGENT_TIMEOUT);
      if (!bIsReady)
      {
        System.Console.WriteLine("Agent is not ready. Exit application.");
        return;
      }
      System.Console.WriteLine("Agent is ready.");
      
      // Run example
      
      Example test = new Example();
      test.Run();
      
      System.Console.WriteLine("Application has stopped.");
    }
  }
}

The called external application passes the received trace context to StartTrace to add more spans to the trace in progress. On exit, it returns the updated trace context to the caller by writing it to standard output.

using System;
using System.Threading;
using AppOptics.Instrumentation;

namespace coretestappexternal
{
  public class Program
  {
    private const int WAIT_AGENT_TIMEOUT = 5000; // Wait timeout for library to be ready
    
    private static string spanName = "example-trace-external";
    
    public static int Main(string[] args)
    {
      if (args.Length != 1)
      {
        System.Console.WriteLine("Invalid number of arguments. Expecting x-trace-id passed as argument.");
        return -1;
      }
      System.Console.WriteLine("Running external application...");
      
      // Extract x-trace-id as first argument for the program
      
      string xTraceId = args[0];
      System.Console.WriteLine("External application launched with trace id {0}.", xTraceId);
      
      // Wait until library is ready
      
      System.Console.WriteLine("Waiting until agent is ready...");
      bool bIsReady = Trace.WaitUntilAgentReady(WAIT_AGENT_TIMEOUT);
      if (!bIsReady)
      {
        System.Console.WriteLine("Agent is not ready. Exit external application.");
        return -1;
      }
      System.Console.WriteLine("Agent is ready.");
      
      // Continue trace using the provided x-trace-id
      
      ContinueTraceEvent continueTraceEvent = Trace.ContinueTrace(spanName, xTraceId);
      continueTraceEvent.Report();
      
      // Do some work
      
      int count = 5;
      
      while(--count > 0)
      {
        Thread.Sleep(1000);
      }
      
      // End trace
      
      EndTraceEvent endTraceEvent = Trace.EndTrace(spanName);
      
      // Retrieve the x-trace-id to be returned to launching process
      
      string returnXTraceId = endTraceEvent.ReportAndReturnTraceId();
      
      // Write x-trace-id to standard output to be extracted by launching process
      
      if (!string.IsNullOrEmpty(returnXTraceId))
      {
        System.Console.WriteLine("x-trace-id={0}", returnXTraceId);
      }
      
      System.Console.WriteLine("External application has stopped.");
      return 0;
    }
  }
}

.NET SDK reference

The following methods are provided by the .NET instrumentation public SDK. The SDK namespace is AppOptics.Instrumentation.

Trace.StartTrace()

Method

Trace.StartTrace()

Description

If a trace is already in progress, reporting the StartTraceEvent adds a span to the trace already started. If a trace isn’t already in progress, reporting the StartTraceEvent either starts a new trace, or if a valid traceparent and tracestate are provided the trace is continued. The reporting of the StartTraceEvent should typically be done when a new request enters your system. For the .NET Framework and .NET 6+, your incoming requests are usually fielded by a web server and so traces are initiated there by our instrumentation. If you do need to start or continue traces within your application code, the first span is created by the reporting of StartTraceEvent automatically. You don't need to add a separate entry event for it.

Returns

An event that can be populated with key-value pairs and reported.

Parameters
traceparent Optional incoming W3C traceparent (https://www.w3.org/TR/trace-context/#traceparent-header). If your application receives requests from a higher span, such as an instrumented web server, you’ll receive a trace context for that trace. The trace context consists of two identifiers. One is the traceparent and the other is tracestate. Both must be provided to Trace.StartTrace() if a trace needs to be continued. See Tracing across external spans. If traceparent and tracestate are not provided and a trace is not already in progress, a new trace is started.
tracestate Optional incoming W3C tracestate (https://www.w3.org/TR/trace-context/#tracestate-header). The tracestate is part of the trace context and must be provided along with the traceparent to continue a trace. See Tracing across external spans.
spanName The name of the highest span. It is required and cannot be null.
url (Optional) The URL of the request that is being sampled.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
StartTraceEvent event = Trace.StartTrace("my_span_name");
event.AddInfo('something', 'interesting');
event.Report();
Notes
  • A start event initializes a trace that must ultimately be terminated by a corresponding end trace.
  • You can use .AddInfo() to attach key/value pairs for special interpretation or to attach any other desired information.
  • This method does not report the event. It must be reported by invoking StartTraceEvent.Report().
Related

Trace.EndTrace()

Method

Trace.EndTrace()

Description

Ends a trace.

Returns

An event that can be populated with key/value pairs and reported. Similar to Trace.StartTrace(), requests usually egress your application stack at your web server and so our instrumentation will take care of ending traces. But you will need this method for tracing across external spans.

Parameters
spanName The name of the highest span. It is required, and must match the span provided to Trace.StartTrace() or CreateEntryEvent().
hasError (Optional) A Boolean value indicating whether the traced request had an unhandled exception.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
EndTraceEvent event= Trace.EndTrace("my_span_name");
event.AddInfo("something", "interesting");
event.Report();
Notes
Related

Trace.EndTraceHttpService()

Method Trace.EndTraceHttpService() 
Description Ends a trace. 
Returns An event that can be populated with key/value pairs and reported. Similar to Trace.StartTrace(), requests usually egress your application stack at your web server and so our instrumentation will take care of ending traces. But this method is needed for tracing across external spans.
Parameters 
spanName The name of the highest span. It is required, and it must match the span provided to Trace.StartTrace() or CreateEntryEvent().
httpMethod The HTTP method of the request (for example, GET, POST).
httpResponseStatusCode The response status code that the request returns (for example, 200, 404).
url (Optional) The URL of the request.
hasError (optional) Indicates if the request resulted in an error.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example 
123EndTraceEvent event= Trace.EndTraceHttpService("my_span_name", "GET", 200, "https://mydomain.com/api/product/1",false); 
event.AddInfo("something", "interesting"); 
event.Report(); 
Notes 
  • This method terminates a trace, which must have already been initialized by a Trace.StartTrace()
  • If a trace was already in progress when the matching Trace.StartTrace() was called, then this call ends a trace without clearing the context. 
  • If a trace was started by the matching Trace.StartTrace(), this call ends a trace and clears the trace context. 
  • You can use .AddInfo() to attach key/value pairs for special interpretation or to attach any other desired information. 
  • This method does not report the event. It must be reported by invoking EndTraceEvent.Report() or EndTraceEvent.ReportAndReturnContext()
Related 

Trace.CreateEntryEvent()

Method

Trace.CreateEntryEvent()

Description

Starts a new span. It's up to you, the application developer, to decide how to segment your application modules and sub-systems into spans.

Returns

An event that can be populated with key/value pairs and reported.

Parameters
spanName Name for the span you are initiating. It is required and cannot be null.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
EntryTraceEvent event = Trace.CreateEntryEvent("my_span_name");
event.AddInfo("something", "interesting");
event.Report();
Notes
  • This method initializes a span, which must be completed by creating a corresponding exit event.
  • You may use EntryTraceEvent.AddInfo() to attach key/value pairs for special interpretation or to attach any other desired information.
  • This method does not report the event. It must be reported by invoking EntryTraceEvent.Report().
  • For an alternate method of creating custom spans see two ways to create a span.
Related
  • Trace.CreateExitEvent()
  • EntryTraceEvent.AddInfo()
  • EntryTraceEvent.Report()

Trace.CreateExitEvent()

Method

Trace.CreateExitEvent()

Description

Completes the specified span.

Returns

An event that can be populated with key/value pairs and reported.

Parameters
spanName The name of the span you provided in the corresponding entry event.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
ExitTraceEvent event = Trace.CreateExitEvent("my_span_name");
event.AddInfo("something", "interesting");
event.Report();
Notes
  • The specified span must already have a corresponding entry event.
  • You can use ExitTraceEvent.AddInfo() to attach key/value pairs for special interpretation or to attach any other desired information.
  • This method does not report the event. It must be reported by invoking ExitTraceEvent.Report().
Related

Trace.CreateInfoEvent()

Method

Trace.CreateInfoEvent()

Description

Info events can be used to report information in between the entry and exit events of a span, particularly for special interpretation.

Returns

An event that can be populated with key/value pairs and reported.

Parameters
spanName

The name of the span to which key/value pairs will be added, as you specified it in the entry event.

Set this parameter to null to use the current span.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
InfoTraceEvent event = Trace.CreateInfoEvent("my_span_name");
event.AddInfo("something", "interesting");
event.Report();
Notes
Related

Trace.ReportException()

Method

Trace.ReportException()

Description

Reports an exception, including a backtrace.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example

See report errors.

Notes
  • This is a convenience method that is equivalent to attaching error event key-value pairs as described in Special span types.
  • Key-value pairs unrelated to special interpretation can be viewed in the raw span data tab on the trace details page.

Trace.SetTransactionName()

Method

Trace.SetTransactionName()

Description

The .NET Library out-of-the-box instrumentation assigns a transaction name based on URL and Controller/Action values detected. However, you might want to override the transaction name to better describe your instrumented operation. If multiple transaction names are set on the same trace, then the last one is used.

Returns

A Boolean value indicating whether the setting of the transaction name was successful.

Parameters
transactionName

The transaction name to assign to the current request.
Empty string and null are considered invalid transaction name values and are ignored.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
Trace.SetTransactionName("my-custom-transaction");
Notes
  • The transaction name when viewed in the Traces Explorer is converted to lowercase. Invalid characters in transaction names are replaced and the names might be truncated.
  • The configuration PrependDomain can be set to Enabled to have the domain name prepended to the transaction name.

Trace.IsAgentAvailable()

Method Trace.IsAgentAvailable()
Description Used to determine if the .NET Library is available.
Returns A Boolean value indicating whether the .NET Library is available.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Trace.WaitUntilAgentReady(timeout)

Method

Trace.WaitUntilAgentReady()

Description

Blocks until the library is ready (has established a connection with the data collector) or the timeout is reached.

Parameters
timeout Maximum period to wait while checking whether the library is ready (the value is in milliseconds).
Returns

A Boolean value indicating if the .NET Library is ready.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Trace.WaitUntilAgentReady(timeout, statusCode)

Method

Trace.WaitUntilAgentReady()

Description

Blocks until the library is ready (has established a connection with the data collector) or the timeout is reached.

Parameters
timeout Maximum period to wait while checking whether the library is ready (the value is in milliseconds).
statusCode

(Out parameter) The status code returned by the check to see if the library is ready. If the timeout is reached then the status code is set to 0 (Unknown).

Status code values:

0 Unknown, or if the SDK is no-op which indicates the APM library did not attach or initialize successfully in the application process
1 Ok
2 TryLater
3 LimitExceeded
4 InvalidApiKey
5 ConnectionError
Returns

A Boolean value indicating whether the .NET Library is ready.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

EntryTraceEvent.SetAsync()

Method

EntryTraceEvent.SetAsync()

Description

Declares the span initiated by the entry event as asynchronous. See Tracing multi-threaded applications.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
EntryTraceEvent event = Trace.CreateEntryEvent("my_span_name");
event.SetAsync();
event.AddInfo("something", "interesting");
event.Report();

ExitTraceEvent.AddEdge()

Method

ExitTraceEvent.AddEdge()

Description

Associates an external span with the current trace. See Tracing across external spans.

Parameters
traceparent Use the return value from EndTraceEvent.ReportAndReturnContext().
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
ExitTraceEvent event = Trace.CreateExitEvent("my_span_name");
event.AddEdge(traceId);
event.Report();

.AddInfo()

Method .AddInfo()
Description Attaches information to events in the form of key/value pairs particularly for special interpretation, but also to attach any other desired information.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example See add info events.
Notes Duplicate keys are ignored, and keys cannot be null.

.AddBackTrace()

Method

.AddBackTrace()

Description

Use this method to report the backtraces of a certain time frame of the application. This adds the backtrace of the current thread to the event.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
EntryTraceEvent event = Trace.CreateEntryEvent("my_span_name");
event.AddBackTrace();

.Report()

Method

.Report()

Description

Use this method to report events, because they are not automatically reported upon creation.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
EntryTraceEvent event = Trace.CreateEntryEvent("my_span_name");
event.AddInfo("something", "interesting");
event.Report();

.ReportAndReturnTraceContext()

Method

EndTraceEvent.ReportAndReturnTraceId()

Description

Reports the end trace event and return the trace context as a TraceContext object. See Tracing across external spans.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
EndTraceEvent event = Trace.EndTrace("my_span_name");
event.AddInfo("something", "interesting");
string traceId = TraceContext traceContext = event.ReportAndReturnTraceContext();
Related

.SummaryMetric()

Method

.SummaryMetric()

Description

Use this method to report a metric value. The metric values reported are aggregated and flushed every 60 seconds.

Parameters
name Name of the metric. Must be 255 or fewer characters and consist only of A-Za-z0-9.:-*.
value Metric value to report count.
count (Optional) Count of metrics being reported (the default is 1).
hostTag (Optional) Indicates if the host name should be included as a tag for the metric (the default is false).
tags (Optional) List of key/value pairs to describe the metric. The key must be 64 characters or fewer and the value must be 255 characters or fewer. Both the key and value must only consist of A-Za-z0-9.:-*.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
DateTime startTime = DateTime.UtcNow();
// some work here...
TimeSpan diff = stopTime - startTime;
long microseconds = diff.Ticks / (TimeSpan.TicksPerMillisecond / 1000);
// report the metric value
Trace.SummaryMetric("my-work-duration", duration);

.IncrementMetric()

Method

.IncrementMetric()

Description

Use this method to report the number of times an action occurs. The metric counts reported are summed and flushed every 60 seconds.

Parameters
name Name of the metric count. Must be 255 or fewer characters and consist only of A-Za-z0-9.:-*.
count (Optional) Count of actions being reported (the default is 1).
hostTag (Optional) Indicates if the host name should be included as a tag for the metric (the default is false).
tags (Optional) List of key/value pairs to describe the metric. The key must be 64 characters or fewer and the value must be 255 characters or fewer. Both the key and value must only consist of A-Za-z0-9.:-*.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Example
// report the action
Trace.IncrementMetric("my-work-count");

Trace.GetCurrentLogTraceId()

Method

Trace.GetCurrentLogTraceId()

Description

Gets a current trace context in the following format: TraceId:<trace_id> SpanId:<span_id> TraceFlags:<trace_flags>, which is suitable for logging. This method should not be used for any purpose other than logging.

Parameters
sampledOnly

When true, returns the compact current trace ID only for sampled requests.

Returns

A string representing a compact form of the current trace ID, or an empty string if no trace is active.

History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

TraceContext.GetCurrent()

Method TraceContext.GetCurrent()
Description

Returns the current tracing context as a TraceContext object. The traceContext can be passed to a background or child thread. See tracing multi-threaded applications for usage information.

Returns A TraceContext object representing the current trace. A TraceContext should always be returned even if the request isn't being sampled. The TraceContext object contains the fields Traceparent, Tracestate, and Sampled.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

TraceContext.ClearCurrentContext()

Method TraceContext.ClearCurrentContext()
Description Used to unset the trace context before returning a thread back to the threadpool. See tracing multi-threaded applications for usage information.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

TraceContext.SetAsCurrent()

Method TraceContext.SetAsCurrent()
Description Sets the context contained in the TraceContext object as the current trace context. This setting of the context can be done for a background or child thread. See tracing multi-threaded applications for usage information.
History

Introduced with version 5.0.0 of the .NET Instrumentation Library.

Troubleshooting

See the Troubleshoot the .NET Library for more information.

The scripts are not supported under any SolarWinds support program or service. The scripts are provided AS IS without warranty of any kind. SolarWinds further disclaims all warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The risk arising out of the use or performance of the scripts and documentation stays with you. In no event shall SolarWinds or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the scripts or documentation.