diff --git a/README.md b/README.md index e452836..ff28fe0 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ catch (Exception ex) | `ServiceVersion` | `string` | `"1.0.0"` | Service version | | `OtlpEndpoint` | `string` | `null` | OTLP collector endpoint (e.g., `http://localhost:4317`) | | `UseOtlpHttp` | `bool` | `false` | Use HTTP/protobuf instead of gRPC | +| `OtlpHeaders` | `IDictionary` | empty | Custom headers for OTLP requests (auth, API keys) | | `EnableConsoleExporter` | `bool` | `false` | Output telemetry to console (for debugging) | | `EnableTracing` | `bool` | `true` | Enable distributed tracing | | `EnableMetrics` | `bool` | `true` | Enable metrics collection | @@ -256,6 +257,23 @@ VsixTelemetry.Initialize(new TelemetryConfiguration }); ``` +### Example: Using Custom Headers (Honeycomb, etc.) + +```csharp +var config = new TelemetryConfiguration +{ + ServiceName = "MyExtension", + OtlpEndpoint = "https://api.honeycomb.io:443", + UseOtlpHttp = true +}; + +// Add authentication headers +config.OtlpHeaders["x-honeycomb-team"] = "your-api-key"; +config.OtlpHeaders["x-honeycomb-dataset"] = "your-dataset"; + +VsixTelemetry.Initialize(config); +``` + --- ## Dependency Injection diff --git a/src/CodingWithCalvin.Otel4Vsix/TelemetryConfiguration.cs b/src/CodingWithCalvin.Otel4Vsix/TelemetryConfiguration.cs index 0f485af..15d0033 100644 --- a/src/CodingWithCalvin.Otel4Vsix/TelemetryConfiguration.cs +++ b/src/CodingWithCalvin.Otel4Vsix/TelemetryConfiguration.cs @@ -40,6 +40,21 @@ public sealed class TelemetryConfiguration /// public bool UseOtlpHttp { get; set; } + /// + /// Gets custom headers to include in OTLP export requests. + /// + /// + /// Use this to add authentication headers (API keys, bearer tokens) or other custom headers + /// required by your telemetry backend. + /// + /// + /// config.OtlpHeaders["x-api-key"] = "your-api-key"; + /// config.OtlpHeaders["Authorization"] = "Bearer your-token"; + /// + /// + /// + public IDictionary OtlpHeaders { get; } = new Dictionary(); + /// /// Gets or sets a value indicating whether the console exporter is enabled. /// diff --git a/src/CodingWithCalvin.Otel4Vsix/VsixTelemetry.cs b/src/CodingWithCalvin.Otel4Vsix/VsixTelemetry.cs index 6b91d58..a231c5d 100644 --- a/src/CodingWithCalvin.Otel4Vsix/VsixTelemetry.cs +++ b/src/CodingWithCalvin.Otel4Vsix/VsixTelemetry.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; +using System.Linq; using System.Threading; using Microsoft.Extensions.Logging; using OpenTelemetry; @@ -367,11 +368,7 @@ private static TracerProvider BuildTracerProvider(ResourceBuilder resourceBuilde { builder.AddOtlpExporter(options => { - options.Endpoint = new Uri(_configuration.OtlpEndpoint); - options.Protocol = _configuration.UseOtlpHttp - ? OtlpExportProtocol.HttpProtobuf - : OtlpExportProtocol.Grpc; - options.TimeoutMilliseconds = _configuration.ExportTimeoutMilliseconds; + ConfigureOtlpExporter(options); }); } @@ -395,11 +392,7 @@ private static OpenTelemetry.Metrics.MeterProvider BuildMeterProvider(ResourceBu { builder.AddOtlpExporter(options => { - options.Endpoint = new Uri(_configuration.OtlpEndpoint); - options.Protocol = _configuration.UseOtlpHttp - ? OtlpExportProtocol.HttpProtobuf - : OtlpExportProtocol.Grpc; - options.TimeoutMilliseconds = _configuration.ExportTimeoutMilliseconds; + ConfigureOtlpExporter(options); }); } @@ -427,11 +420,7 @@ private static ILoggerFactory BuildLoggerFactory(ResourceBuilder resourceBuilder { options.AddOtlpExporter(exporterOptions => { - exporterOptions.Endpoint = new Uri(_configuration.OtlpEndpoint); - exporterOptions.Protocol = _configuration.UseOtlpHttp - ? OtlpExportProtocol.HttpProtobuf - : OtlpExportProtocol.Grpc; - exporterOptions.TimeoutMilliseconds = _configuration.ExportTimeoutMilliseconds; + ConfigureOtlpExporter(exporterOptions); }); } @@ -444,6 +433,23 @@ private static ILoggerFactory BuildLoggerFactory(ResourceBuilder resourceBuilder }); } + private static void ConfigureOtlpExporter(OtlpExporterOptions options) + { + options.Endpoint = new Uri(_configuration.OtlpEndpoint); + options.Protocol = _configuration.UseOtlpHttp + ? OtlpExportProtocol.HttpProtobuf + : OtlpExportProtocol.Grpc; + options.TimeoutMilliseconds = _configuration.ExportTimeoutMilliseconds; + + // Add custom headers if configured + if (_configuration.OtlpHeaders.Count > 0) + { + var headerString = string.Join(",", + _configuration.OtlpHeaders.Select(kvp => $"{kvp.Key}={kvp.Value}")); + options.Headers = headerString; + } + } + private static void ThrowIfNotInitialized() { if (!_isInitialized)