Skip to content

Commit 7b707ac

Browse files
committed
Attempt to give more time for flushing logs
1 parent 3a29f10 commit 7b707ac

2 files changed

Lines changed: 28 additions & 26 deletions

File tree

tracer/test/test-applications/integrations/Samples.OpenTelemetrySdk/CustomTracerProviderBuilderExtensions.cs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using OpenTelemetry.Metrics;
66
#endif
77
#if OTEL_1_9
8+
using Microsoft.Extensions.DependencyInjection;
89
using OpenTelemetry.Logs;
910
#endif
1011
using Microsoft.Extensions.Logging;
@@ -61,33 +62,30 @@ public static MeterProviderBuilder AddOtlpExporterIfEnvironmentVariablePresent(t
6162
#if OTEL_1_9
6263
public static class CustomLoggerFactoryBuilderExtensions
6364
{
64-
public static ILoggerFactory AddOtlpExporterIfEnvironmentVariablePresent()
65+
// Returns an IServiceProvider rather than an ILoggerFactory so callers can resolve
66+
// the underlying OpenTelemetry.Logs.LoggerProvider and call ForceFlush before disposal.
67+
// LoggerProviderSdk.Dispose() caps its shutdown flush at 5s; with gRPC, the first export
68+
// can exceed that due to TCP/HTTP/2/TLS handshake, causing batched logs to be dropped.
69+
public static ServiceProvider CreateLoggerServices()
6570
{
66-
// Check if OpenTelemetry Logs Exporter is enabled (similar to metrics)
67-
if (Environment.GetEnvironmentVariable("OTEL_LOGS_EXPORTER_ENABLED") is string value
68-
&& value == "true")
71+
var services = new ServiceCollection();
72+
services.AddLogging(builder =>
6973
{
70-
return LoggerFactory.Create(builder =>
74+
builder.SetMinimumLevel(LogLevel.Trace);
75+
76+
if (Environment.GetEnvironmentVariable("OTEL_LOGS_EXPORTER_ENABLED") is string value
77+
&& value == "true")
7178
{
72-
builder.SetMinimumLevel(LogLevel.Trace);
7379
#if NET6_0_OR_GREATER
74-
builder.AddOpenTelemetry(
75-
options =>
76-
{
77-
options.AddOtlpExporter();
78-
}
79-
);
80+
builder.AddOpenTelemetry(options =>
81+
{
82+
options.AddOtlpExporter();
83+
});
8084
#endif
81-
});
82-
}
83-
else
84-
{
85-
// Create logger factory without OTel - Datadog instrumentation will hook this
86-
return LoggerFactory.Create(builder =>
87-
{
88-
builder.SetMinimumLevel(LogLevel.Trace);
89-
});
90-
}
85+
}
86+
});
87+
88+
return services.BuildServiceProvider();
9189
}
9290
}
9391
#endif

tracer/test/test-applications/integrations/Samples.OpenTelemetrySdk/Program.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using OpenTelemetry.Metrics;
88
#endif
99
#if OTEL_1_9
10+
using Microsoft.Extensions.DependencyInjection;
1011
using OpenTelemetry.Logs;
1112
#endif
1213
using System.Collections.Generic;
@@ -50,8 +51,8 @@ public static async Task Main(string[] args)
5051
#endif
5152

5253
#if OTEL_1_9
53-
using var loggerFactory = CustomLoggerFactoryBuilderExtensions
54-
.AddOtlpExporterIfEnvironmentVariablePresent();
54+
using var loggerServices = CustomLoggerFactoryBuilderExtensions.CreateLoggerServices();
55+
var loggerFactory = loggerServices.GetRequiredService<ILoggerFactory>();
5556
#endif
5657

5758
_tracer = tracerProvider.GetTracer(serviceName); // The version is omitted so the ActivitySource.Version / otel.library.version is not set
@@ -147,8 +148,11 @@ public static async Task Main(string[] args)
147148
meterProvider?.Dispose();
148149
#endif
149150
#if OTEL_1_9
150-
151-
loggerFactory?.Dispose();
151+
// Flush OTLP log batches before the ServiceProvider's `using` disposes them.
152+
// LoggerProviderSdk.Dispose caps shutdown flush at 5s, which is often insufficient
153+
// for the first gRPC export (TCP+HTTP/2+TLS handshake). A generous ForceFlush here
154+
// drains pending batches on the critical path instead of racing a hard-coded timeout.
155+
loggerServices.GetService<LoggerProvider>()?.ForceFlush(timeoutMilliseconds: 10_000);
152156
#endif
153157
}
154158

0 commit comments

Comments
 (0)