@@ -32,6 +32,30 @@ public static void AddOtlpEnvironment(IResource resource, IConfiguration configu
32
32
// Add annotation to mark this resource as having OTLP exporter configured
33
33
resource . Annotations . Add ( new OtlpExporterAnnotation ( ) ) ;
34
34
35
+ RegisterOtlpEnvironment ( resource , configuration , environment ) ;
36
+ }
37
+
38
+ /// <summary>
39
+ /// Configures OpenTelemetry in projects using environment variables.
40
+ /// </summary>
41
+ /// <param name="resource">The resource to add annotations to.</param>
42
+ /// <param name="configuration">The configuration to use for the OTLP exporter endpoint URL.</param>
43
+ /// <param name="environment">The host environment to check if the application is running in development mode.</param>
44
+ /// <param name="protocol">The protocol to use for the OTLP exporter. If not set, it will try gRPC then Http.</param>
45
+ public static void AddOtlpEnvironment ( IResource resource , IConfiguration configuration , IHostEnvironment environment , OtlpProtocol protocol )
46
+ {
47
+ ArgumentNullException . ThrowIfNull ( resource ) ;
48
+ ArgumentNullException . ThrowIfNull ( configuration ) ;
49
+ ArgumentNullException . ThrowIfNull ( environment ) ;
50
+
51
+ // Add annotation to mark this resource as having OTLP exporter configured
52
+ resource . Annotations . Add ( new OtlpExporterAnnotation { RequiredProtocol = protocol } ) ;
53
+
54
+ RegisterOtlpEnvironment ( resource , configuration , environment ) ;
55
+ }
56
+
57
+ private static void RegisterOtlpEnvironment ( IResource resource , IConfiguration configuration , IHostEnvironment environment )
58
+ {
35
59
// Configure OpenTelemetry in projects using environment variables.
36
60
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md
37
61
@@ -43,26 +67,13 @@ public static void AddOtlpEnvironment(IResource resource, IConfiguration configu
43
67
return ;
44
68
}
45
69
46
- var dashboardOtlpGrpcUrl = configuration . GetString ( KnownConfigNames . DashboardOtlpGrpcEndpointUrl , KnownConfigNames . Legacy . DashboardOtlpGrpcEndpointUrl ) ;
47
- var dashboardOtlpHttpUrl = configuration . GetString ( KnownConfigNames . DashboardOtlpHttpEndpointUrl , KnownConfigNames . Legacy . DashboardOtlpHttpEndpointUrl ) ;
48
-
49
- // The dashboard can support OTLP/gRPC and OTLP/HTTP endpoints at the same time, but it can
50
- // only tell resources about one of the endpoints via environment variables.
51
- // If both OTLP/gRPC and OTLP/HTTP are available then prefer gRPC.
52
- if ( dashboardOtlpGrpcUrl != null )
53
- {
54
- SetOtelEndpointAndProtocol ( context . EnvironmentVariables , dashboardOtlpGrpcUrl , "grpc" ) ;
55
- }
56
- else if ( dashboardOtlpHttpUrl != null )
57
- {
58
- SetOtelEndpointAndProtocol ( context . EnvironmentVariables , dashboardOtlpHttpUrl , "http/protobuf" ) ;
59
- }
60
- else
70
+ if ( ! resource . TryGetLastAnnotation < OtlpExporterAnnotation > ( out var otlpExporterAnnotation ) )
61
71
{
62
- // No endpoints provided to host. Use default value for URL.
63
- SetOtelEndpointAndProtocol ( context . EnvironmentVariables , DashboardOtlpUrlDefaultValue , "grpc" ) ;
72
+ return ;
64
73
}
65
74
75
+ SetOtelEndpointAndProtocol ( context , configuration , otlpExporterAnnotation ) ;
76
+
66
77
// Set the service name and instance id to the resource name and UID. Values are injected by DCP.
67
78
var dcpDependencyCheckService = context . ExecutionContext . ServiceProvider . GetRequiredService < IDcpDependencyCheckService > ( ) ;
68
79
var dcpInfo = await dcpDependencyCheckService . GetDcpInfoAsync ( cancellationToken : context . CancellationToken ) . ConfigureAwait ( false ) ;
@@ -91,6 +102,42 @@ public static void AddOtlpEnvironment(IResource resource, IConfiguration configu
91
102
}
92
103
} ) ) ;
93
104
105
+ static void SetOtelEndpointAndProtocol ( EnvironmentCallbackContext context , IConfiguration configuration , OtlpExporterAnnotation otlpExporterAnnotation )
106
+ {
107
+ var dashboardOtlpGrpcUrl = configuration . GetString ( KnownConfigNames . DashboardOtlpGrpcEndpointUrl , KnownConfigNames . Legacy . DashboardOtlpGrpcEndpointUrl ) ;
108
+ var dashboardOtlpHttpUrl = configuration . GetString ( KnownConfigNames . DashboardOtlpHttpEndpointUrl , KnownConfigNames . Legacy . DashboardOtlpHttpEndpointUrl ) ;
109
+
110
+ // Check if a specific protocol is required by the annotation
111
+ if ( otlpExporterAnnotation . RequiredProtocol is OtlpProtocol . Grpc )
112
+ {
113
+ SetOtelEndpointAndProtocol ( context . EnvironmentVariables , dashboardOtlpGrpcUrl ?? DashboardOtlpUrlDefaultValue , "grpc" ) ;
114
+ }
115
+ else if ( otlpExporterAnnotation . RequiredProtocol is OtlpProtocol . HttpProtobuf )
116
+ {
117
+ SetOtelEndpointAndProtocol ( context . EnvironmentVariables , dashboardOtlpHttpUrl ?? throw new InvalidOperationException ( "OtlpExporter is configured to require http/protobuf, but no endpoint was configured for ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL" ) , "http/protobuf" ) ;
118
+ }
119
+ else
120
+ {
121
+ // No specific protocol required, use the existing preference logic
122
+ // The dashboard can support OTLP/gRPC and OTLP/HTTP endpoints at the same time, but it can
123
+ // only tell resources about one of the endpoints via environment variables.
124
+ // If both OTLP/gRPC and OTLP/HTTP are available then prefer gRPC.
125
+ if ( dashboardOtlpGrpcUrl is not null )
126
+ {
127
+ SetOtelEndpointAndProtocol ( context . EnvironmentVariables , dashboardOtlpGrpcUrl , "grpc" ) ;
128
+ }
129
+ else if ( dashboardOtlpHttpUrl is not null )
130
+ {
131
+ SetOtelEndpointAndProtocol ( context . EnvironmentVariables , dashboardOtlpHttpUrl , "http/protobuf" ) ;
132
+ }
133
+ else
134
+ {
135
+ // No endpoints provided to host. Use default value for URL.
136
+ SetOtelEndpointAndProtocol ( context . EnvironmentVariables , DashboardOtlpUrlDefaultValue , "grpc" ) ;
137
+ }
138
+ }
139
+ }
140
+
94
141
static void SetOtelEndpointAndProtocol ( Dictionary < string , object > environmentVariables , string url , string protocol )
95
142
{
96
143
environmentVariables [ "OTEL_EXPORTER_OTLP_ENDPOINT" ] = new HostUrl ( url ) ;
@@ -112,7 +159,26 @@ public static IResourceBuilder<T> WithOtlpExporter<T>(this IResourceBuilder<T> b
112
159
ArgumentNullException . ThrowIfNull ( builder ) ;
113
160
114
161
AddOtlpEnvironment ( builder . Resource , builder . ApplicationBuilder . Configuration , builder . ApplicationBuilder . Environment ) ;
115
-
162
+
163
+ return builder ;
164
+ }
165
+
166
+ /// <summary>
167
+ /// Injects the appropriate environment variables to allow the resource to enable sending telemetry to the dashboard.
168
+ /// 1. It sets the OTLP endpoint to the value of the ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL environment variable.
169
+ /// 2. It sets the service name and instance id to the resource name and UID. Values are injected by the orchestrator.
170
+ /// 3. It sets a small batch schedule delay in development. This reduces the delay that OTLP exporter waits to sends telemetry and makes the dashboard telemetry pages responsive.
171
+ /// </summary>
172
+ /// <typeparam name="T">The resource type.</typeparam>
173
+ /// <param name="builder">The resource builder.</param>
174
+ /// <param name="protocol">The protocol to use for the OTLP exporter. If not set, it will try gRPC then Http.</param>
175
+ /// <returns>The <see cref="IResourceBuilder{T}"/>.</returns>
176
+ public static IResourceBuilder < T > WithOtlpExporter < T > ( this IResourceBuilder < T > builder , OtlpProtocol protocol ) where T : IResourceWithEnvironment
177
+ {
178
+ ArgumentNullException . ThrowIfNull ( builder ) ;
179
+
180
+ AddOtlpEnvironment ( builder . Resource , builder . ApplicationBuilder . Configuration , builder . ApplicationBuilder . Environment , protocol ) ;
181
+
116
182
return builder ;
117
183
}
118
184
}
0 commit comments