Tests — OtelHelper (.NET)
179 unit tests (xUnit), 0 failed, 0 warnings.
docker run --rm -v " $( pwd ) :/src" -w /src mcr.microsoft.com/dotnet/sdk:8.0 dotnet test OtelHelper.Tests
OptionsTests
Validate defaults and env var resolution.
Test
Description
Default_ServiceName_Is_MyService
Default ServiceName is "my-service"
Default_CollectorEndpoint_Is_Empty_When_No_EnvVar
Default endpoint stays empty (Prometheus fallback)
Default_DebugLevel_Is_False
Debug disabled by default
ResolveEnvironment_Parses_Correctly × 6
LOCAL, DEV, HML, PRD, prd, dev
ResolveEnvironment_Invalid_Falls_Back_To_LOCAL × 3
Invalid values → LOCAL
RegistrationTests
Test
Description
AddOtelHelper_Parameterless_Uses_Defaults
Parameterless registration works
AddOtelHelper_Registers_Options
IOptions registered
AddOtelHelper_Registers_Validator
TelemetryOptionsValidator registered
TelemetryPipelineTests
Environments
Test
Description
All_Environments_Register_Pipeline_Without_Error × 4
LOCAL, DEV, HML, PRD register pipeline
Log Level
Test
Description
LogLevel_Matches_Environment × 4
LOCAL=Debug, DEV/HML=Info, PRD=Warning
DebugLevel_Forces_Debug_LogLevel
Debug mode forces LogLevel.Debug in PRD
Test
Description
ExtraInstrumentation_Default_Has_SQL
SQL enabled, AWS disabled by default
ExtraInstrumentation_Multiple_Values
SQL,AWS enables both
ExtraInstrumentation_Case_Insensitive
sql,aws works
ExtraInstrumentation_Empty_Disables_All
Empty string disables all
DebugLevel_Enables_All_Extra_Instrumentation
Debug mode enables all
Endpoint Resolution
Test
Description
Default_Endpoint_Is_Empty_Without_EnvVar
No env var → endpoint stays empty
Endpoint_Extracts_Host_And_Appends_Port
Extracts host and adds :4317
Endpoint_With_Trailing_Slash_Is_Cleaned
Removes trailing slash
PostConfigure_Endpoint_NonURI_Uses_RawValue
Non-URI value (e.g. "just-a-hostname") falls back to raw value
Full Pipeline
Test
Description
Full_Pipeline_Registers_All_Signals
Logging + Options registered
Custom_Sampler_Is_Accepted
TraceIdRatioBasedSampler accepted
Custom_MinimumLogLevel_Overrides_Environment
MinimumLogLevel override works
ResourceAttributes_Default_Is_Empty
Empty by default
ResourceAttributes_Accepted_In_Pipeline
Custom attributes accepted
ActivitySources
Test
Description
AdditionalActivitySources_Default_Is_Empty
Empty list by default
AdditionalActivitySources_Accepted_In_Pipeline
Additional sources accepted
DI Registration
Test
Description
ActivitySource_Registered_Via_DI
ActivitySource singleton with ServiceName
Meter_Registered_Via_DI
Meter singleton with ServiceName
GetDefaultLogLevel
Test
Description
GetDefaultLogLevel_Returns_Correct_Values
LOCAL=Debug, DEV=Info, PRD=Warning, debug override
StartRootActivity
Test
Description
StartRootActivity_Creates_Root_Span_Without_Parent
Clears parent, creates root
StartRootActivity_Generates_New_TraceId_Each_Call
Each call generates new traceId
DebugTraceStateProcessor
Test
Description
DebugMode_Sets_TraceState_And_Attribute_On_Root_Span
Sets tracestate + attribute debug=true
DebugMode_Does_Not_Set_On_Child_Span
Does not set on child spans
OTEL_HELPER_SAMPLE_RATIO
Test
Description
SampleRatio_EnvVar_Sets_TraceIdRatioBasedSampler
0.5 → TraceIdRatioBased
SampleRatio_Default_Keeps_AlwaysOn
No env var → AlwaysOn
SampleRatio_Invalid_EnvVar_Keeps_AlwaysOn
Invalid value → AlwaysOn
Double Registration
Test
Description
Double_AddOtelHelper_Does_Not_Duplicate_Registration
Second call is no-op
PostConfigure
Test
Description
PostConfigure_Resolves_Environment_From_EnvVar
ENVIRONMENT=PRD → DeploymentEnvironment.PRD
PostConfigure_Resolves_DisabledSignals_From_EnvVar
OTEL_HELPER_DISABLED_SIGNALS resolves the list
PostConfigure_Resolves_DisabledMetrics_From_EnvVar
OTEL_HELPER_DISABLED_METRICS resolves wildcard patterns
PostConfigure_DisabledMetrics_Stays_Empty_When_EnvVar_Not_Set
Stays empty when unset
Validator
Test
Description
Validator_Fails_On_Empty_ServiceName
Empty ServiceName fails
Validator_Succeeds_On_Empty_Endpoint_Prometheus_Mode
Empty endpoint is valid (Prometheus fallback mode)
Validator_Fails_On_Invalid_URI
Invalid URI fails
Validator_Fails_On_Zero_Timeout
ExportTimeoutMs ≤ 0 fails
IsSignalEnabled
Test
Description
IsSignalEnabled_Returns_True_When_DisabledSignals_Empty
All signals enabled when DisabledSignals is empty
IsSignalEnabled_Returns_False_When_Signal_In_DisabledSignals
Signal in DisabledSignals → disabled
IsSignalEnabled_Is_Case_Insensitive
Case-insensitive matching
Disabled Signals — Full Pipeline
Test
Description
Pipeline_Registers_When_Metrics_Disabled
Metrics disabled, pipeline still registers
Pipeline_Registers_With_DisabledMetrics_Pattern
Wildcard drop pattern accepted
Pipeline_Registers_When_Traces_Disabled
Traces disabled, pipeline still registers
Pipeline_Registers_When_Logs_Disabled
Logs disabled, pipeline still registers
Pipeline_Registers_When_All_Signals_Disabled
All three disabled at once
HasInstrumentation("REDIS")
Test
Description
HasInstrumentation_Redis_Works_Like_SQL_AWS
REDIS enables like SQL/AWS
HasInstrumentation_Redis_Case_Insensitive
"redis" (lowercase) works
Test
Description
Pipeline_Registers_With_AWS_Instrumentation
ExtraInstrumentation=SQL,AWS registers cleanly
Pipeline_Registers_With_Redis_Instrumentation
ExtraInstrumentation=SQL,REDIS registers cleanly
TracingAndOptionsHelperTests
Tracing helpers (StartRootActivity, DebugTraceStateProcessor) and TelemetryOptions helper methods, tested directly (not through AddOtelHelper).
StartRootActivity
Test
Description
StartRootActivity_Creates_Root_Span_Without_Parent
Clears parent, creates root
StartRootActivity_Generates_New_TraceId_Each_Call
Each call generates a new traceId
DebugTraceStateProcessor
Test
Description
DebugMode_Sets_TraceState_And_Attribute_On_Root_Span
Sets tracestate + attribute debug=true
DebugMode_Does_Not_Set_On_Child_Span
Does not set on child spans
IsSignalEnabled
Test
Description
IsSignalEnabled_Returns_True_When_DisabledSignals_Empty
All signals enabled when empty
IsSignalEnabled_Returns_False_When_Signal_Disabled
Disabled signal reports false
IsSignalEnabled_Is_Case_Insensitive
Case-insensitive matching
HasInstrumentation
Test
Description
HasInstrumentation_Default_Has_SQL
SQL enabled, AWS/REDIS disabled by default
HasInstrumentation_Multiple_Values
SQL,AWS,REDIS all enable
HasInstrumentation_Case_Insensitive
Mixed case works
HasInstrumentation_Empty_Disables_All
Empty string disables all
DebugLevel_Enables_All_Instrumentation
Debug mode bypasses the list check entirely
GetDefaultLogLevel
Test
Description
GetDefaultLogLevel_Returns_Correct_Values
LOCAL=Debug, DEV/HML=Info, PRD=Warning, debug override
Validator
Test
Description
Validator_Fails_On_Empty_ServiceName
Empty ServiceName fails
Validator_Succeeds_On_Empty_Endpoint_Prometheus_Mode
Empty endpoint is valid
Validator_Fails_On_Invalid_URI
Invalid URI fails
Validator_Fails_On_Zero_Timeout
ExportTimeoutMs ≤ 0 fails
SignalIntegrationTests
Integration tests verifying signals are actually collected or dropped via in-memory exporters. Uses [Collection("EnvVarTests")] to prevent parallel execution (env var conflicts).
Test
Description
Meter_Name_Matches_ServiceName
DI-resolved Meter name equals ServiceName
ActivitySource_Name_Matches_ServiceName
DI-resolved ActivitySource name equals ServiceName
Custom_Metrics_Via_DI_Meter_Are_Collected
A counter created via the DI Meter is exported
Traces_Via_DI_ActivitySource_Are_Collected
A span created via the DI ActivitySource is exported with its tags
ValidateOnStart_Throws_With_Empty_ServiceName
Invalid ServiceName fails fast inside AddOtelHelper() (P9)
ValidateOnStart_Throws_With_Invalid_Endpoint
Invalid endpoint URI fails fast inside AddOtelHelper() (P9)
LogLevel_Above_Minimum_Are_Enabled × 3
LOCAL/DEV/PRD minimum log level enabled, level below disabled
Full_Pipeline_Registers_All_Signals
Logging, Options, ActivitySource, Meter all resolve from the built provider
DebugLevel_Forces_Debug_LogLevel
Debug mode forces Debug level even in PRD
Custom_MinimumLogLevel_Overrides_Environment
Explicit MinimumLogLevel overrides the env-based default
DisabledMetrics_Pattern_Drops_Matching_Metric
A metric matching the drop pattern is excluded; a non-matching one is kept
SubpackageExtensionsTests
Opt-in subpackage extensions (AWS, SQL, Redis) — each verifies the fluent IServiceCollection return and that TracerProvider resolves after registration.
Test
Description
AddOtelHelperAws_Registers_And_Returns_Services
AWS extension registers, TracerProvider resolves
AddOtelHelperSql_Registers_And_Returns_Services
SQL extension registers, TracerProvider resolves
AddOtelHelperRedis_Explicit_Connection_Registers
Redis extension with an explicit IConnectionMultiplexer
AddOtelHelperRedis_FromDI_Registers_And_Returns_Services
Redis extension resolving the connection from DI
TlsEndpointResolutionTests
TelemetryOptionsPostConfigure's TLS scheme resolution — secure by default, OTEL_EXPORTER_OTLP_INSECURE override, explicit scheme always wins. Uses [Collection("EnvVarTests")].
Test
Description
HttpsScheme_Preserved_When_Explicit
https://gw:4317 kept as-is
HttpScheme_Preserved_When_Explicit
http://gw:4317 kept as-is (plaintext)
Schemeless_Defaults_To_Https_SecureByDefault
gw:4317 (no scheme) → https://gw:4317
Schemeless_With_Insecure_True_Uses_Http
Schemeless + INSECURE=true → http://
Schemeless_With_Insecure_False_Uses_Https
Schemeless + INSECURE=false → https://
Schemeless_HostOnly_Defaults_Port_4317_And_Https
Host-only (no port) → https://host:4317
HttpsScheme_Preserves_Custom_Port
https://gw:4318 keeps the custom port
Schemeless_With_Custom_Port_And_Insecure
gw:4318 + INSECURE=true → http://gw:4318
ConsumerSet_Endpoint_Not_Overridden
Endpoint set in code is not overwritten by PostConfigure
Insecure_EnvVar_Ignored_When_Scheme_Explicit_Https
Explicit https:// scheme wins over INSECURE=true
HttpsScheme_DefaultPort_Gets_4317
https://gw (no port) normalizes to :4317
ResolveEndpoint_Unit_Schemeless_Host_Port
ResolveEndpoint static helper: schemeless host:port
ResolveEndpoint_Unit_Schemeless_Host_Only
ResolveEndpoint static helper: schemeless host only
ResolveEndpoint_Unit_Http_Explicit
ResolveEndpoint static helper: explicit http://
ProfilingTests
OtelHelper.Profiling's ProfilingPrerequisites and extension registration. Uses [Collection("EnvVarTests")].
Test
Description
ProfilingPrerequisites_FromEnvironment_AllSet_IsSatisfied
All required env vars set → satisfied
ProfilingPrerequisites_Missing_ServerAddress_NotSatisfied
Missing server address → not satisfied
ProfilingPrerequisites_Missing_ClrProfiler_NotSatisfied
Missing CLR profiler env var → not satisfied
ProfilingPrerequisites_Missing_ProfilingEnabled_NotSatisfied
Missing "profiling enabled" var → not satisfied
ProfilingPrerequisites_DescribeMissing_ListsMissingVars
DescribeMissing() lists all missing vars when nothing is set
ProfilingPrerequisites_DescribeMissing_OnlyListsMissing
DescribeMissing() omits vars that are already set
ProfilingPrerequisites_DescribeMissing_ReturnsNull_When_Satisfied
DescribeMissing() returns null when fully satisfied
ProfilingPrerequisites_Truthy_AcceptsBothOneAndTrue × 4
"1", "true", "True", "TRUE" all count as enabled
ProfilingPrerequisites_NotTruthy_Rejects_InvalidValues × 5
"0", "false", "", "yes", "on" are all rejected
ProfilingPrerequisites_ApplicationName_IsRead
ApplicationName read from its env var
ProfilingPrerequisites_IsSatisfied_Without_ApplicationName
ApplicationName is optional — not required for IsSatisfied
AddOtelHelperProfiling_Registers_HostedService_When_Prerequisites_Missing
Missing prerequisites → ProfilingPrerequisiteWarning hosted service registered
ProfilingPrerequisiteWarning_LogsWarning_OnStart
The warning hosted service starts/stops without exception
AddOtelHelperProfiling_Registers_IProfilingProvider
IProfilingProvider resolves from DI after registration
MetricsContractTests
OTEL_METRICS_EXPORTER contract (US-1, US-2, US-6). Cross-language parity with python/tests/test_metrics_contract.py and go/metrics_contract_test.go. Uses [Collection("EnvVarTests")].
Exporter resolution
Test
Description
Unset_WithEndpoint_IsOtlp
Unset + endpoint set → otlp (legacy inference)
Unset_WithoutEndpoint_IsPrometheus
Unset + no endpoint → prometheus
PrometheusOnly_EvenWithEndpoint
prometheus wins even with an endpoint set
DualMode_BothExporters
otlp,prometheus → both active
None_DisablesMetrics
none → empty resolved list
CaseAndWhitespace_Tolerated
" OTLP , Prometheus " parses correctly
ExplicitOption_BeatsEnv
MetricExporters property wins over the env var
UnknownValue_FailsValidation
Unknown value → validation error listing valid values
OtlpWithoutEndpoint_FailsValidation
otlp without an endpoint → validation error
NoneCombined_FailsValidation
none,prometheus → validation error
Export interval
Test
Description
Interval_DefaultIs30s
Default is 30000ms
Interval_EnvHonored
OTEL_METRIC_EXPORT_INTERVAL resolves the interval
Interval_ExplicitBeatsEnv
Explicit ExportIntervalMs wins over the env var
Interval_InvalidEnvFallsBack
Non-numeric env value falls back to 30000
Interval_NonPositive_FailsValidation
ExportIntervalMs = 0 → validation error
Listener / port
Test
Description
PortZero_IsValid
PrometheusMetricsPort = 0 passes validation (listener disabled)
Dual-mode pipeline
Test
Description
DualMode_CounterVisible_InInMemoryAndPrometheusReaders
Single provider, two readers — same counter visible via an in-memory exporter AND a live Prometheus HTTP scrape, no double counting
ConfigureMetrics_PrometheusOnly_WithEndpoint_Builds
prometheus-only with an endpoint set builds cleanly and serves /metrics
ConfigureMetrics_PortZero_SkipsListener
Port 0 builds without binding any listener
SamplerPrecedenceTests
OTEL_TRACES_SAMPLER (standard SDK var) precedence over OTEL_HELPER_SAMPLE_RATIO (US-2). Verified against the real Sdk.CreateTracerProviderBuilder() behavior (empirically confirmed, not assumed — see ANALISE-PROBLEMAS.md P9). Uses [Collection("EnvVarTests")].
Test
Description
HelperVarOnly_AppliesRatio
Only OTEL_HELPER_SAMPLE_RATIO set → ratio applied, TraceIdRatioBasedSampler
StandardVarOnly_Wins
Only OTEL_TRACES_SAMPLER=always_off set → span not sampled
StandardVarBeatsHelperVar
Both set → standard var wins, helper ratio ignored
ExplicitRatioBeatsStandardVar
Explicit Sampler in code wins over the standard env var
NoEnvNoOverride_DefaultsToAlwaysOn
Neither set → AlwaysOnSampler, span sampled
OtlpProtocolTests
OTLP wire protocol selection (grpc vs http/protobuf) — tracing and metrics. Cross-language parity with python/tests/test_otlp_protocol.py and go/otlp_protocol_test.go. Uses [Collection("EnvVarTests")].
ResolvedOtlpProtocol precedence
Test
Description
DefaultIsGrpc
Endpoint on port 4317, no env var → grpc
NoEndpoint_DefaultsToGrpc
No endpoint at all → grpc
Port4318_InfersHttp
Endpoint on port 4318 → http/protobuf
Port4317_InfersGrpc
Endpoint on port 4317 → grpc
OtherPort_InfersGrpc
Endpoint on an unrelated port → grpc
EnvVar_BeatsPortInference
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf wins over a :4317 endpoint that would infer grpc
EnvVarGrpc_BeatsHttpPortInference
OTEL_EXPORTER_OTLP_PROTOCOL=grpc wins over a :4318 endpoint that would infer http
ExplicitOption_BeatsEnv
TelemetryOptions.OtlpProtocol set in code wins over the env var
EnvVar_CaseAndWhitespaceTolerant
" HTTP/PROTOBUF " normalizes correctly
Validation
Test
Description
UnknownValue_FailsValidation
Unknown protocol value → validation error
HttpJson_RejectedEvenThoughSpecValid
http/json is a valid OTel spec value but unsupported here → fails validation
GrpcAndHttpProtobuf_PassValidation × 2
grpc and http/protobuf both pass validation
Live integration — HTTP protocol delivers to /v1/{signal}
Test
Description
Tracing_Http_DeliversToV1Traces
ConfigureTracing with http/protobuf sends the request to /v1/traces on a real HttpListener
Metrics_Http_DeliversToV1Metrics
ConfigureMetrics with http/protobuf sends the request to /v1/metrics on a real HttpListener