Elastic APM .NET Agent

repository·main·Indexed 20 days ago

https://github.com/elastic/apm-agent-dotnet

The Elastic APM .NET Agent provides application performance monitoring for .NET applications. It supports auto-instrumentation for frameworks like ASP.NET Core and Entity Framework, and clients including Elasticsearch, Redis, MongoDB, and Azure services. The agent is distributed via NuGet packages (such as Elastic.Apm and Elastic.Apm.NetCoreAll) and offers a Public Agent API for manual instrumentation. It also includes a CLR profiler and a .NET runtime startup hook for enabling instrumentation without code changes.

Tokens
49.3K
Snippets
154
Records
232
Agent score
67%

What's inside elastic-apm-agent-dotnet

  1. Overview of Profiler Auto-Instrumentation

    main

    Profiler auto-instrumentation allows you to add Elastic APM to .NET or .NET Framework applications without modifying source code or adding NuGet packages. By setting environment variables, the profiler automatically captures transactions, HTTP calls, database queries, and more using the CLR Profiling APIs.

    Key Characteristics

    • Zero-code change: No source code modifications or NuGet package additions required for basic instrumentation.
    • Use cases: Quick starts, instrumenting third-party applications, or applying configuration across all services on a host.
    • Constraint: Only one profiler can be attached to a .NET process at a time. You cannot use multiple solutions that rely on the .NET CLR Profiling API simultaneously.

    Supported Runtimes and Architectures

    ArchitectureWindowsLinux
    x64.NET Framework 4.6.2-4.8.1* <br> .NET 8+.NET 8+
    • Note on .NET Framework: Version 4.7.2 or higher is recommended for best compatibility and to ensure configuration options like VerifyServerCert and ServerCert function correctly.
    • Note on .NET: The profiler is officially tested for .NET 8 and newer (recommend .NET 10).
    • Unsupported: ARM, 32-bit processes, and IIS web garden (multi-worker process) mode.
  2. Authenticate with APM Server using ApiKey or SecretToken

    main

    The agent supports two primary authentication methods for connecting to the APM Server:

    1. ApiKey (Recommended): Generated by Kibana when configuring the APM integration.
    2. SecretToken: Used if your APM Server is configured with a secret token instead.

    Security Warning: Never commit ApiKey or SecretToken values to source control. Use a secrets management system (e.g., Azure Key Vault, AWS Secrets Manager, or Kubernetes Secrets) to inject these at runtime.

    If the agent cannot reach the APM Server due to incorrect authentication or URL settings, it will continue to run but will not send data. Check the agent logs to troubleshoot.

  3. How Duck Typing works in the library

    main

    The Duck Typing library allows you to access fields, properties, and methods of an object without having its type definition available at compile time. It achieves this by creating a runtime proxy type that wraps the target object instance.

    To use it, you define a proxy (an interface, abstract class, or class with virtual members) that describes the members you want to access. You then use the .As<T>() extension method on your target object to create a proxy instance that implements your definition.

    // 1. Define the proxy interface
    public interface IDuckAnonymous 
    {
        string Name { get; }
        string Version { get; }
    }
    
    // 2. Use the .As<T>() extension method on the target object
    var anonymousObject = new { Name = ".NET Core", Version = "3.1" };
    var proxyInstance = anonymousObject.As<IDuckAnonymous>();
    
    // 3. Access members via the proxy
    Console.WriteLine($"Name: {proxyInstance.Name}");
  4. Use a custom configuration reader in .NET Full Framework

    main

    For .NET Full Framework applications, you can implement the IConfigurationReader interface from the Elastic.Apm.Config namespace to provide a custom configuration source.

    To activate your custom reader, use the FullFrameworkConfigurationReaderType setting. You must provide the type name in AssemblyQualifiedName format (e.g., MyClass, MyNamespace).

  5. Proxy definition types and resulting proxy types

    main

    The library generates different proxy types based on the definition you provide:

    Proxy Definition TypeResulting Proxy Type
    InterfaceStruct implementing the interface
    Abstract classClass inheriting and overriding the abstract class
    Class with virtual membersClass inheriting and overriding the virtual class

    All generated proxy types implement the IDuckType interface, which allows you to retrieve the original target instance and its type.

  6. Understand Agent configuration precedence

    main

    The Agent resolves configuration options using two layers in the following order of precedence:

    1. IConfiguration Layer: This is checked first. It includes all registered sources such as appsettings.json, ElasticApm__* environment variables (using double underscores as the section separator), command-line arguments, and in-memory collections.
      • Note: Values added via AddInMemoryCollection win over all other IConfiguration sources.
    2. ELASTIC_APM_* Environment Variables: The Agent's native environment variable format is checked only if no value was found in the IConfiguration layer.

    To allow deployment-time environment variables to still override in-memory values, check for the existence of both the IConfiguration key and the ELASTIC_APM_* variable before injecting an in-memory override.

  7. How Azure Service Bus transactions and spans are captured

    main

    The agent captures messaging operations using transactions and spans to provide distributed tracing.

    Transactions

    Transactions represent top-level operations. A new transaction is created when:

    • A receive operation is initiated against a queue or topic subscription.
    • A receive deferred operation is initiated.
    • A message is processed via ServiceBusProcessor or ServiceBusSessionProcessor (push-based model).

    Note: If a receive operation occurs within an existing transaction, a span is created instead of a new transaction.

    Spans

    Spans represent child operations within an existing transaction. A new span is created when:

    • One or more messages are sent to a queue or topic.
    • One or more messages are scheduled to a queue or topic.

    When receiving or processing a batch of messages, the agent creates a span link for each message back to the producer span that sent it. This allows you to follow a message end-to-end from producer to consumer in Kibana.

  8. Handle breaking changes in cookie parsing and redaction

    main

    In version 1.29.0, the agent changed how it parses and sends transaction cookies to prevent data loss caused by period characters in cookie names (common in ASP.NET Core sessions/auth).

    Changes:

    • The agent no longer parses individual cookies into a dictionary.
    • The cookie Dictionary has been removed from the data model, meaning cookies are no longer indexed individually.
    • Redaction still works: Any cookies with names matching the SanitizeFieldNames configuration will still be redacted within the Cookie header string.

    Impact: If your monitoring or custom logic relies on parsed individual cookie fields, you must update your implementation to work with the raw Cookie header value instead.

  9. Use ECS logging with System.Diagnostics.Activity

    main

    You can use the ecs-logging-dotnet library to implement the ECS logging format independently of the Elastic APM .NET Agent.

    When using ECS logging in .NET, correlation IDs are provided through System.Diagnostics.Activity. If the Elastic APM .NET Agent is also running in your application, it will automatically pick up these System.Diagnostics.Activity correlation features to provide full service correlation.