< Summary

Information
Class: ProjectTemplate.Web.Extensions.OpenTelemetryServiceExtensions
Assembly: ProjectTemplate.Web
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Extensions/OpenTelemetryServiceExtensions.cs
Line coverage
100%
Covered lines: 76
Uncovered lines: 0
Coverable lines: 76
Total lines: 132
Line coverage: 100%
Branch coverage
65%
Covered branches: 13
Total branches: 20
Branch coverage: 65%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddApplicationOpenTelemetry(...)87.5%88100%
ConfigureOtlpExporter(...)100%22100%
ResolveServiceVersion(...)40%1010100%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Extensions/OpenTelemetryServiceExtensions.cs

#LineLine coverage
 1using System.Reflection;
 2using OpenTelemetry;
 3using OpenTelemetry.Exporter;
 4using OpenTelemetry.Metrics;
 5using OpenTelemetry.Resources;
 6using OpenTelemetry.Trace;
 7using ProjectTemplate.Web.Options;
 8
 9namespace ProjectTemplate.Web.Extensions;
 10
 11/// <summary>
 12/// Provides extension methods to register OpenTelemetry services for the application.
 13/// </summary>
 14public static class OpenTelemetryServiceExtensions
 15{
 16    /// <summary>
 17    /// Adds baseline OpenTelemetry tracing and metrics support.
 18    /// </summary>
 19    /// <param name="services">The service collection to add OpenTelemetry services to.</param>
 20    /// <param name="configuration">The application configuration source.</param>
 21    /// <param name="environment">The current hosting environment.</param>
 22    /// <returns>The same service collection instance so calls can be chained.</returns>
 23    public static IServiceCollection AddApplicationOpenTelemetry(
 24        this IServiceCollection services,
 25        IConfiguration configuration,
 26        IHostEnvironment environment)
 27    {
 11628        services
 11629            .AddOptions<ApplicationOpenTelemetryOptions>()
 11630            .Bind(configuration.GetSection(ApplicationOpenTelemetryOptions.SectionName))
 11631            .Validate(options => !string.IsNullOrWhiteSpace(options.ServiceName),
 11632                "ProjectTemplate:OpenTelemetry:ServiceName must not be empty.")
 11633            .Validate(options => !options.Otlp.Enabled || Uri.TryCreate(options.Otlp.Endpoint, UriKind.Absolute, out _),
 11634                "ProjectTemplate:OpenTelemetry:Otlp:Endpoint must be a valid absolute URI when OTLP export is enabled.")
 11635            .ValidateOnStart();
 36
 11637        ApplicationOpenTelemetryOptions options = configuration
 11638            .GetSection(ApplicationOpenTelemetryOptions.SectionName)
 11639            .Get<ApplicationOpenTelemetryOptions>() ?? new ApplicationOpenTelemetryOptions();
 40
 11641        if (!options.Enabled)
 42        {
 343            return services;
 44        }
 45
 11346        string serviceVersion = ResolveServiceVersion(options);
 47
 11348        OpenTelemetryBuilder openTelemetryBuilder = services
 11349            .AddOpenTelemetry()
 11350            .ConfigureResource(resource => resource
 11351                .AddService(
 11352                    serviceName: options.ServiceName,
 11353                    serviceVersion: serviceVersion)
 11354                .AddAttributes(new Dictionary<string, object>
 11355                {
 11356                    ["deployment.environment.name"] = environment.EnvironmentName
 11357                }));
 58
 11359        if (options.EnableTracing)
 60        {
 11261            openTelemetryBuilder.WithTracing(tracing =>
 11262            {
 11263                if (options.EnableAspNetCoreInstrumentation)
 11264                {
 11265                    tracing.AddAspNetCoreInstrumentation();
 11266                }
 11267
 11268                if (options.EnableHttpClientInstrumentation)
 11269                {
 11270                    tracing.AddHttpClientInstrumentation();
 11271                }
 11272
 11273                if (options.Otlp.Enabled)
 11274                {
 11275                    tracing.AddOtlpExporter(exporterOptions => ConfigureOtlpExporter(exporterOptions, options.Otlp));
 11276                }
 11277            });
 78        }
 79
 11380        if (options.EnableMetrics)
 81        {
 11282            openTelemetryBuilder.WithMetrics(metrics =>
 11283            {
 11284                if (options.EnableAspNetCoreInstrumentation)
 11285                {
 11286                    metrics.AddAspNetCoreInstrumentation();
 11287                }
 11288
 11289                if (options.EnableHttpClientInstrumentation)
 11290                {
 11291                    metrics.AddHttpClientInstrumentation();
 11292                }
 11293
 11294                if (options.Otlp.Enabled)
 11295                {
 11296                    metrics.AddOtlpExporter(exporterOptions => ConfigureOtlpExporter(exporterOptions, options.Otlp));
 11297                }
 11298            });
 99        }
 100
 113101        return services;
 102    }
 103
 104    private static void ConfigureOtlpExporter(
 105        OtlpExporterOptions exporterOptions,
 106        ApplicationOtlpExporterOptions options)
 107    {
 4108        exporterOptions.Endpoint = new Uri(options.Endpoint);
 4109        exporterOptions.Protocol = string.Equals(
 4110            options.Protocol,
 4111            "HttpProtobuf",
 4112            StringComparison.OrdinalIgnoreCase)
 4113            ? OtlpExportProtocol.HttpProtobuf
 4114            : OtlpExportProtocol.Grpc;
 4115    }
 116
 117    private static string ResolveServiceVersion(ApplicationOpenTelemetryOptions options)
 118    {
 117119        if (!string.IsNullOrWhiteSpace(options.ServiceVersion))
 120        {
 114121            return options.ServiceVersion.Trim();
 122        }
 123
 3124        Assembly assembly = typeof(Program).Assembly;
 125
 3126        string? informationalVersion = assembly
 3127            .GetCustomAttribute<AssemblyInformationalVersionAttribute>()
 3128            ?.InformationalVersion;
 129
 3130        return !string.IsNullOrWhiteSpace(informationalVersion) ? informationalVersion : assembly.GetName().Version?.ToS
 131    }
 132}