-
Notifications
You must be signed in to change notification settings - Fork 773
/
OtlpExporterOptions.cs
213 lines (185 loc) · 8.32 KB
/
OtlpExporterOptions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
using System.Diagnostics;
using System.Reflection;
#if NETFRAMEWORK
using System.Net.Http;
#endif
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace OpenTelemetry.Exporter;
/// <summary>
/// OpenTelemetry Protocol (OTLP) exporter options.
/// OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TIMEOUT, OTEL_EXPORTER_OTLP_PROTOCOL
/// environment variables are parsed during object construction.
/// </summary>
public class OtlpExporterOptions
{
internal const string EndpointEnvVarName = "OTEL_EXPORTER_OTLP_ENDPOINT";
internal const string HeadersEnvVarName = "OTEL_EXPORTER_OTLP_HEADERS";
internal const string TimeoutEnvVarName = "OTEL_EXPORTER_OTLP_TIMEOUT";
internal const string ProtocolEnvVarName = "OTEL_EXPORTER_OTLP_PROTOCOL";
internal static readonly KeyValuePair<string, string>[] StandardHeaders = new KeyValuePair<string, string>[]
{
new KeyValuePair<string, string>("User-Agent", GetUserAgentString()),
};
internal readonly Func<HttpClient> DefaultHttpClientFactory;
private const string DefaultGrpcEndpoint = "http://localhost:4317";
private const string DefaultHttpEndpoint = "http://localhost:4318";
private const OtlpExportProtocol DefaultOtlpExportProtocol = OtlpExportProtocol.Grpc;
private const string UserAgentProduct = "OTel-OTLP-Exporter-Dotnet";
private Uri endpoint;
/// <summary>
/// Initializes a new instance of the <see cref="OtlpExporterOptions"/> class.
/// </summary>
public OtlpExporterOptions()
: this(new ConfigurationBuilder().AddEnvironmentVariables().Build(), new())
{
}
internal OtlpExporterOptions(
IConfiguration configuration,
BatchExportActivityProcessorOptions defaultBatchOptions)
{
Debug.Assert(configuration != null, "configuration was null");
Debug.Assert(defaultBatchOptions != null, "defaultBatchOptions was null");
if (configuration.TryGetUriValue(EndpointEnvVarName, out var endpoint))
{
this.endpoint = endpoint;
}
if (configuration.TryGetStringValue(HeadersEnvVarName, out var headers))
{
this.Headers = headers;
}
if (configuration.TryGetIntValue(TimeoutEnvVarName, out var timeout))
{
this.TimeoutMilliseconds = timeout;
}
if (configuration.TryGetValue<OtlpExportProtocol>(
ProtocolEnvVarName,
OtlpExportProtocolParser.TryParse,
out var protocol))
{
this.Protocol = protocol;
}
this.HttpClientFactory = this.DefaultHttpClientFactory = () =>
{
return new HttpClient
{
Timeout = TimeSpan.FromMilliseconds(this.TimeoutMilliseconds),
};
};
this.BatchExportProcessorOptions = defaultBatchOptions;
}
/// <summary>
/// Gets or sets the target to which the exporter is going to send telemetry.
/// Must be a valid Uri with scheme (http or https) and host, and
/// may contain a port and path. The default value is
/// * http://localhost:4317 for <see cref="OtlpExportProtocol.Grpc"/>
/// * http://localhost:4318 for <see cref="OtlpExportProtocol.HttpProtobuf"/>.
/// </summary>
public Uri Endpoint
{
get
{
if (this.endpoint == null)
{
this.endpoint = this.Protocol == OtlpExportProtocol.Grpc
? new Uri(DefaultGrpcEndpoint)
: new Uri(DefaultHttpEndpoint);
}
return this.endpoint;
}
set
{
this.endpoint = value;
this.ProgrammaticallyModifiedEndpoint = true;
}
}
/// <summary>
/// Gets or sets optional headers for the connection. Refer to the <a href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables">
/// specification</a> for information on the expected format for Headers.
/// </summary>
public string Headers { get; set; }
/// <summary>
/// Gets or sets the max waiting time (in milliseconds) for the backend to process each batch. The default value is 10000.
/// </summary>
public int TimeoutMilliseconds { get; set; } = 10000;
/// <summary>
/// Gets or sets the the OTLP transport protocol. Supported values: Grpc and HttpProtobuf.
/// </summary>
public OtlpExportProtocol Protocol { get; set; } = DefaultOtlpExportProtocol;
/// <summary>
/// Gets or sets the export processor type to be used with the OpenTelemetry Protocol Exporter. The default value is <see cref="ExportProcessorType.Batch"/>.
/// </summary>
/// <remarks>Note: This only applies when exporting traces.</remarks>
public ExportProcessorType ExportProcessorType { get; set; } = ExportProcessorType.Batch;
/// <summary>
/// Gets or sets the BatchExportProcessor options. Ignored unless ExportProcessorType is Batch.
/// </summary>
/// <remarks>Note: This only applies when exporting traces.</remarks>
public BatchExportProcessorOptions<Activity> BatchExportProcessorOptions { get; set; }
/// <summary>
/// Gets or sets the factory function called to create the <see
/// cref="HttpClient"/> instance that will be used at runtime to
/// transmit telemetry over HTTP. The returned instance will be reused
/// for all export invocations.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>This is only invoked for the <see
/// cref="OtlpExportProtocol.HttpProtobuf"/> protocol.</item>
/// <item>The default behavior when using the <see
/// cref="OtlpTraceExporterHelperExtensions.AddOtlpExporter(TracerProviderBuilder,
/// Action{OtlpExporterOptions})"/> extension is if an <a
/// href="https://docs.microsoft.com/dotnet/api/system.net.http.ihttpclientfactory">IHttpClientFactory</a>
/// instance can be resolved through the application <see
/// cref="IServiceProvider"/> then an <see cref="HttpClient"/> will be
/// created through the factory with the name "OtlpTraceExporter"
/// otherwise an <see cref="HttpClient"/> will be instantiated
/// directly.</item>
/// <item>The default behavior when using the <see
/// cref="OtlpMetricExporterExtensions.AddOtlpExporter(MeterProviderBuilder,
/// Action{OtlpExporterOptions})"/> extension is if an <a
/// href="https://docs.microsoft.com/dotnet/api/system.net.http.ihttpclientfactory">IHttpClientFactory</a>
/// instance can be resolved through the application <see
/// cref="IServiceProvider"/> then an <see cref="HttpClient"/> will be
/// created through the factory with the name "OtlpMetricExporter"
/// otherwise an <see cref="HttpClient"/> will be instantiated
/// directly.</item>
/// </list>
/// </remarks>
public Func<HttpClient> HttpClientFactory { get; set; }
/// <summary>
/// Gets a value indicating whether <see cref="Endpoint" /> was modified via its setter.
/// </summary>
internal bool ProgrammaticallyModifiedEndpoint { get; private set; }
internal static void RegisterOtlpExporterOptionsFactory(IServiceCollection services)
{
services.RegisterOptionsFactory(CreateOtlpExporterOptions);
}
internal static OtlpExporterOptions CreateOtlpExporterOptions(
IServiceProvider serviceProvider,
IConfiguration configuration,
string name)
=> new(
configuration,
serviceProvider.GetRequiredService<IOptionsMonitor<BatchExportActivityProcessorOptions>>().Get(name));
private static string GetUserAgentString()
{
try
{
var assemblyVersion = typeof(OtlpExporterOptions).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
var informationalVersion = assemblyVersion.InformationalVersion;
return string.IsNullOrEmpty(informationalVersion) ? UserAgentProduct : $"{UserAgentProduct}/{informationalVersion}";
}
catch (Exception)
{
return UserAgentProduct;
}
}
}