diff --git a/docs/file-based-configuration.md b/docs/file-based-configuration.md index c5ee3fd538..ac3f7c5e80 100644 --- a/docs/file-based-configuration.md +++ b/docs/file-based-configuration.md @@ -47,6 +47,9 @@ fail_fast: false # Configure if the Flush On Unhandled Exception is enabled or not. # If omitted or null, false is used. flush_on_unhandled_exception: false +# Configure if the Logs Include Formatted Message is enabled or not. +# If omitted or null, false is used. +logs_include_formatted_message: false ``` ### Tracer Provider Configuration @@ -112,6 +115,79 @@ tracer_provider: console: ``` +### Logger Provider Configuration + +``` yaml +logger_provider: + processors: + # Batch processor for OTLP HTTP + - batch: + # Configure delay interval (in milliseconds) between two consecutive exports. + # Value must be non-negative. + # If omitted or null, 5000 is used. + schedule_delay: 5000 + # Configure maximum allowed time (in milliseconds) to export data. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 30000 is used. + export_timeout: 30000 + # Configure maximum queue size. Value must be positive. + # If omitted or null, 2048 is used. + max_queue_size: 2048 + # Configure maximum batch size. Value must be positive. + # If omitted or null, 512 is used. + max_export_batch_size: 512 + # Configure exporter. + exporter: + # Configure the OTLP with HTTP transport exporter to enable it. + otlp_http: + # Configure endpoint, including the logs specific path. + # If omitted or null, http://localhost:4318/v1/logs is used. + endpoint: http://localhost:4318/v1/logs + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + # If omitted or null, no headers are added. + headers_list: api-key=1234 + # Configure compression. + # Values include: gzip, none. Implementations may support other compression algorithms. + # If omitted or null, none is used. + compression: gzip + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + + # Batch processor for OTLP gRPC + - batch: + exporter: + otlp_grpc: + # Configure endpoint. + # If omitted or null, http://localhost:4317 is used. + endpoint: http://localhost:4317 + # Configure headers. Entries have higher priority than entries from .headers_list. + # If an entry's .value is null, the entry is ignored. + headers: + - name: api-key + value: "1234" + # Configure headers. Entries have lower priority than entries from .headers. + # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + # If omitted or null, no headers are added. + headers_list: api-key=1234 + # Configure max time (in milliseconds) to wait for each export. + # Value must be non-negative. A value of 0 indicates no limit (infinity). + # If omitted or null, 10000 is used. + timeout: 10000 + + # Simple processor for Console + - simple: + exporter: + console: +``` + ### Resource Configuration You can configure resource attributes directly in YAML or via the diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationLogHelper.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationLogHelper.cs index 93523d66ae..a2087e9ddf 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationLogHelper.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationLogHelper.cs @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 using System.Runtime.CompilerServices; +using OpenTelemetry; +using OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; +using OpenTelemetry.AutoInstrumentation.Configurations.Otlp; using OpenTelemetry.AutoInstrumentation.Loading; +using OpenTelemetry.AutoInstrumentation.Logging; using OpenTelemetry.AutoInstrumentation.Plugins; using OpenTelemetry.Logs; @@ -10,6 +14,8 @@ namespace OpenTelemetry.AutoInstrumentation.Configurations; internal static class EnvironmentConfigurationLogHelper { + private static readonly IOtelLogger Logger = OtelLogging.GetLogger(); + public static LoggerProviderBuilder UseEnvironmentVariables( this LoggerProviderBuilder builder, LazyInstrumentationLoader lazyInstrumentationLoader, @@ -22,6 +28,119 @@ public static LoggerProviderBuilder UseEnvironmentVariables( private static void SetExporter(LoggerProviderBuilder builder, LogSettings settings, PluginManager pluginManager) { + if (settings.LogExporters.Count == 0) + { + if (settings.Processors != null) + { + foreach (var processor in settings.Processors) + { + if (processor.Batch != null && processor.Simple != null) + { + Logger.Debug("Both batch and simple processors are configured. It is not supported. Skipping."); + continue; + } + + if (processor.Batch == null && processor.Simple == null) + { + Logger.Debug("No valid processor configured, skipping."); + continue; + } + + if (processor.Batch != null) + { + var exporter = processor.Batch.Exporter; + if (exporter == null) + { + Logger.Debug("No exporter configured for batch processor. Skipping."); + continue; + } + + var exportersCount = 0; + + if (exporter.OtlpHttp != null) + { + exportersCount++; + } + + if (exporter.OtlpGrpc != null) + { + exportersCount++; + } + + switch (exportersCount) + { + case 0: + Logger.Debug("No valid exporter configured for batch processor. Skipping."); + continue; + case > 1: + Logger.Debug("Multiple exporters are configured for batch processor. Only one exporter is supported. Skipping."); + continue; + } + + if (exporter.OtlpHttp != null) + { + builder = Wrappers.AddOtlpHttpExporter(builder, pluginManager, processor.Batch, exporter.OtlpHttp); + } + else if (exporter.OtlpGrpc != null) + { + builder = Wrappers.AddOtlpGrpcExporter(builder, pluginManager, processor.Batch, exporter.OtlpGrpc); + } + } + else if (processor.Simple != null) + { + var exporter = processor.Simple.Exporter; + if (exporter == null) + { + Logger.Debug("No exporter configured for simple processor. Skipping."); + continue; + } + + var exportersCount = 0; + + if (exporter.OtlpHttp != null) + { + exportersCount++; + } + + if (exporter.OtlpGrpc != null) + { + exportersCount++; + } + + if (exporter.Console != null) + { + exportersCount++; + } + + switch (exportersCount) + { + case 0: + Logger.Debug("No valid exporter configured for simple processor. Skipping."); + continue; + case > 1: + Logger.Debug("Multiple exporters are configured for simple processor. Only one exporter is supported. Skipping."); + continue; + } + + if (exporter.OtlpHttp != null) + { + builder = Wrappers.AddOtlpHttpExporter(builder, pluginManager, exporter.OtlpHttp); + } + else if (exporter.OtlpGrpc != null) + { + builder = Wrappers.AddOtlpGrpcExporter(builder, pluginManager, exporter.OtlpGrpc); + } + else if (exporter.Console != null) + { + builder = Wrappers.AddConsoleExporter(builder, pluginManager); + } + } + } + } + + return; + } + foreach (var logExporter in settings.LogExporters) { builder = logExporter switch @@ -50,5 +169,53 @@ public static LoggerProviderBuilder AddOtlpExporter(LoggerProviderBuilder builde pluginManager?.ConfigureLogsOptions(options); }); } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static LoggerProviderBuilder AddOtlpHttpExporter(LoggerProviderBuilder builder, PluginManager pluginManager, LogBatchProcessorConfig batch, OtlpHttpExporterConfig otlpHttp) + { + var otlpSettings = new OtlpSettings(OtlpSignalType.Logs, otlpHttp); + return builder.AddOtlpExporter(options => + { + batch?.CopyTo(options.BatchExportProcessorOptions); + otlpSettings.CopyTo(options); + pluginManager?.ConfigureLogsOptions(options); + }); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static LoggerProviderBuilder AddOtlpGrpcExporter(LoggerProviderBuilder builder, PluginManager pluginManager, LogBatchProcessorConfig batch, OtlpGrpcExporterConfig otlpGrpc) + { + var otlpSettings = new OtlpSettings(otlpGrpc); + return builder.AddOtlpExporter(options => + { + batch?.CopyTo(options.BatchExportProcessorOptions); + otlpSettings.CopyTo(options); + pluginManager?.ConfigureLogsOptions(options); + }); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static LoggerProviderBuilder AddOtlpHttpExporter(LoggerProviderBuilder builder, PluginManager pluginManager, OtlpHttpExporterConfig otlpHttp) + { + var otlpSettings = new OtlpSettings(OtlpSignalType.Logs, otlpHttp); + return builder.AddOtlpExporter(options => + { + options.ExportProcessorType = ExportProcessorType.Simple; + otlpSettings.CopyTo(options); + pluginManager?.ConfigureLogsOptions(options); + }); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static LoggerProviderBuilder AddOtlpGrpcExporter(LoggerProviderBuilder builder, PluginManager pluginManager, OtlpGrpcExporterConfig otlpGrpc) + { + var otlpSettings = new OtlpSettings(otlpGrpc); + return builder.AddOtlpExporter(options => + { + options.ExportProcessorType = ExportProcessorType.Simple; + otlpSettings.CopyTo(options); + pluginManager?.ConfigureLogsOptions(options); + }); + } } } diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchLogExporterConfig.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchLogExporterConfig.cs new file mode 100644 index 0000000000..8e6485c1f3 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchLogExporterConfig.cs @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class BatchLogExporterConfig +{ + /// + /// Gets or sets the OTLP HTTP exporter configuration. + /// + [YamlMember(Alias = "otlp_http")] + public OtlpHttpExporterConfig? OtlpHttp { get; set; } + + /// + /// Gets or sets the OTLP gRPC exporter configuration. + /// + [YamlMember(Alias = "otlp_grpc")] + public OtlpGrpcExporterConfig? OtlpGrpc { get; set; } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfig.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfig.cs index de31d367fb..edf2575ea7 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfig.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfig.cs @@ -1,56 +1,15 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -using System.Diagnostics; using Vendors.YamlDotNet.Serialization; namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; -internal class BatchProcessorConfig +internal class BatchProcessorConfig : BatchProcessorConfigBase { - /// - /// Gets or sets the delay interval (in milliseconds) between two consecutive exports. - /// Value must be non-negative. - /// If omitted or null, 5000 is used. - /// - [YamlMember(Alias = "schedule_delay")] - public int ScheduleDelay { get; set; } = 5000; - - /// - /// Gets or sets the maximum allowed time (in milliseconds) to export data. - /// Value must be non-negative. A value of 0 indicates no limit (infinity). - /// If omitted or null, 30000 is used. - /// - [YamlMember(Alias = "export_timeout")] - public int ExportTimeout { get; set; } = 30000; - - /// - /// Gets or sets the maximum queue size. - /// Value must be positive. - /// If omitted or null, 2048 is used. - /// - [YamlMember(Alias = "max_queue_size")] - public int MaxQueueSize { get; set; } = 2048; - - /// - /// Gets or sets the maximum batch size. - /// Value must be positive. - /// If omitted or null, 512 is used. - /// - [YamlMember(Alias = "max_export_batch_size")] - public int MaxExportBatchSize { get; set; } = 512; - /// /// Gets or sets the exporters. /// [YamlMember(Alias = "exporter")] public BatchTracerExporterConfig? Exporter { get; set; } - - public void CopyTo(BatchExportProcessorOptions options) - { - options.ScheduledDelayMilliseconds = ScheduleDelay; - options.ExporterTimeoutMilliseconds = ExportTimeout; - options.MaxQueueSize = MaxQueueSize; - options.MaxExportBatchSize = MaxExportBatchSize; - } } diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfigBase.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfigBase.cs new file mode 100644 index 0000000000..c979b86b26 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/BatchProcessorConfigBase.cs @@ -0,0 +1,51 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry; +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class BatchProcessorConfigBase +{ + /// + /// Gets or sets the delay interval (in milliseconds) between two consecutive exports. + /// Value must be non-negative. + /// If omitted or null, 5000 is used. + /// + [YamlMember(Alias = "schedule_delay")] + public int ScheduleDelay { get; set; } = 5000; + + /// + /// Gets or sets the maximum allowed time (in milliseconds) to export data. + /// Value must be non-negative. A value of 0 indicates no limit (infinity). + /// If omitted or null, 30000 is used. + /// + [YamlMember(Alias = "export_timeout")] + public int ExportTimeout { get; set; } = 30000; + + /// + /// Gets or sets the maximum queue size. + /// Value must be positive. + /// If omitted or null, 2048 is used. + /// + [YamlMember(Alias = "max_queue_size")] + public int MaxQueueSize { get; set; } = 2048; + + /// + /// Gets or sets the maximum batch size. + /// Value must be positive. + /// If omitted or null, 512 is used. + /// + [YamlMember(Alias = "max_export_batch_size")] + public int MaxExportBatchSize { get; set; } = 512; + + public void CopyTo(BatchExportProcessorOptions options) + where T : class + { + options.ScheduledDelayMilliseconds = ScheduleDelay; + options.ExporterTimeoutMilliseconds = ExportTimeout; + options.MaxQueueSize = MaxQueueSize; + options.MaxExportBatchSize = MaxExportBatchSize; + } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogBatchProcessorConfig.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogBatchProcessorConfig.cs new file mode 100644 index 0000000000..349de8a1e1 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogBatchProcessorConfig.cs @@ -0,0 +1,15 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class LogBatchProcessorConfig : BatchProcessorConfigBase +{ + /// + /// Gets or sets the exporters. + /// + [YamlMember(Alias = "exporter")] + public BatchLogExporterConfig? Exporter { get; set; } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogProcessorConfig.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogProcessorConfig.cs new file mode 100644 index 0000000000..111832d0d4 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogProcessorConfig.cs @@ -0,0 +1,15 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class LogProcessorConfig +{ + [YamlMember(Alias = "batch")] + public LogBatchProcessorConfig? Batch { get; set; } + + [YamlMember(Alias = "simple")] + public LogSimpleProcessorConfig? Simple { get; set; } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogSimpleProcessorConfig.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogSimpleProcessorConfig.cs new file mode 100644 index 0000000000..6f449d1526 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LogSimpleProcessorConfig.cs @@ -0,0 +1,12 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class LogSimpleProcessorConfig +{ + [YamlMember(Alias = "exporter")] + public SimpleLogExporterConfig? Exporter { get; set; } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LoggerProviderConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LoggerProviderConfiguration.cs new file mode 100644 index 0000000000..7a4e51c050 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/LoggerProviderConfiguration.cs @@ -0,0 +1,12 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class LoggerProviderConfiguration +{ + [YamlMember(Alias = "processors")] + public List Processors { get; set; } = new(); +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/SimpleLogExporterConfig.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/SimpleLogExporterConfig.cs new file mode 100644 index 0000000000..9708719d02 --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/SimpleLogExporterConfig.cs @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class SimpleLogExporterConfig +{ + /// + /// Gets or sets the OTLP HTTP exporter configuration. + /// + [YamlMember(Alias = "otlp_http")] + public OtlpHttpExporterConfig? OtlpHttp { get; set; } + + /// + /// Gets or sets the OTLP gRPC exporter configuration. + /// + [YamlMember(Alias = "otlp_grpc")] + public OtlpGrpcExporterConfig? OtlpGrpc { get; set; } + + /// + /// Gets or sets the console exporter configuration. + /// + [YamlMember(Alias = "console")] + public object? Console { get; set; } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs index 11502f813a..48099cacdc 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs @@ -31,6 +31,14 @@ internal class YamlConfiguration [YamlMember(Alias = "tracer_provider")] public TracerProviderConfiguration? TracerProvider { get; set; } + /// + /// Gets or sets the logger provider configuration. + /// Configure logger provider. + /// If omitted, a noop logger provider is used. + /// + [YamlMember(Alias = "logger_provider")] + public LoggerProviderConfiguration? LoggerProvider { get; set; } + /// /// Gets or sets the text map context propagator configuration. /// If omitted, a noop propagator is used. @@ -59,6 +67,13 @@ internal class YamlConfiguration [YamlMember(Alias = "flush_on_unhandled_exception")] public bool FlushOnUnhandledException { get; set; } = false; + /// + /// Gets or sets a value indicating whether the Logs Include Formatted Message is enabled. + /// If omitted or null, false is used. + /// + [YamlMember(Alias = "logs_include_formatted_message")] + public bool LogsIncludeFormattedMessage { get; set; } = false; + /// /// Gets or sets the no-code tracing configuration. /// diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/LogSettings.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/LogSettings.cs index 0b15291aa5..a623237189 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/LogSettings.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/LogSettings.cs @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System; +using OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; using OpenTelemetry.AutoInstrumentation.Configurations.Otlp; using OpenTelemetry.AutoInstrumentation.Logging; @@ -21,7 +23,7 @@ internal class LogSettings : Settings /// /// Gets the list of enabled logs exporters. /// - public IReadOnlyList LogExporters { get; private set; } = new List(); + public IReadOnlyList LogExporters { get; private set; } = []; /// /// Gets a value indicating whether the IncludeFormattedMessage is enabled. @@ -36,13 +38,18 @@ internal class LogSettings : Settings /// /// Gets the list of enabled instrumentations. /// - public IReadOnlyList EnabledInstrumentations { get; private set; } = new List(); + public IReadOnlyList EnabledInstrumentations { get; private set; } = []; /// /// Gets logs OTLP Settings. /// public OtlpSettings? OtlpSettings { get; private set; } + /// + /// Gets the processors configured via file-based configuration. + /// + public IReadOnlyList? Processors { get; private set; } + protected override void OnLoadEnvVar(Configuration configuration) { LogsEnabled = configuration.GetBool(ConfigurationKeys.Logs.LogsEnabled) ?? true; @@ -64,7 +71,16 @@ protected override void OnLoadEnvVar(Configuration configuration) enabledConfigurationTemplate: ConfigurationKeys.Logs.EnabledLogsInstrumentationTemplate); } - private static IReadOnlyList ParseLogExporter(Configuration configuration) + protected override void OnLoadFile(YamlConfiguration configuration) + { + var processors = configuration.LoggerProvider?.Processors; + + LogsEnabled = processors != null && processors.Count > 0; + Processors = processors; + IncludeFormattedMessage = configuration.LogsIncludeFormattedMessage; + } + + private static List ParseLogExporter(Configuration configuration) { var logExporterEnvVar = configuration.GetString(ConfigurationKeys.Logs.Exporter); var exporters = new List(); diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/TracerSettings.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/TracerSettings.cs index bb3d6b01bf..f07452f5d4 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/TracerSettings.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/TracerSettings.cs @@ -106,11 +106,8 @@ protected override void OnLoadEnvVar(Configuration configuration) protected override void OnLoadFile(YamlConfiguration configuration) { var processors = configuration.TracerProvider?.Processors; - if (processors != null && processors.Count > 0) - { - TracesEnabled = true; - } + TracesEnabled = processors != null && processors.Count > 0; Processors = processors; } diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedLogsSettingsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedLogsSettingsTests.cs new file mode 100644 index 0000000000..b6fcefa3b8 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedLogsSettingsTests.cs @@ -0,0 +1,148 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.AutoInstrumentation.Configurations; +using OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; +using Xunit; + +namespace OpenTelemetry.AutoInstrumentation.Tests.Configurations.FileBased; + +public class FilebasedLogsSettingsTests +{ + [Fact] + public void LoadFile_SetsProcessorsCorrectly() + { + var batchProcessorConfig1 = new LogBatchProcessorConfig + { + ScheduleDelay = 1000, + ExportTimeout = 30000, + MaxQueueSize = 2048, + MaxExportBatchSize = 512, + Exporter = new BatchLogExporterConfig + { + OtlpGrpc = new OtlpGrpcExporterConfig + { + Endpoint = "http://localhost:4317/" + } + } + }; + + var batchProcessorConfig2 = new LogBatchProcessorConfig + { + Exporter = new BatchLogExporterConfig + { + OtlpHttp = new OtlpHttpExporterConfig + { + Endpoint = "http://localhost:4318/v1/logs" + } + } + }; + + var simpleProcessorConfig = new LogProcessorConfig + { + Simple = new LogSimpleProcessorConfig + { + Exporter = new SimpleLogExporterConfig + { + Console = new object() + } + } + }; + + var conf = new YamlConfiguration + { + LoggerProvider = new LoggerProviderConfiguration + { + Processors = + [ + new LogProcessorConfig + { + Batch = batchProcessorConfig1 + }, + new LogProcessorConfig + { + Batch = batchProcessorConfig2 + }, + simpleProcessorConfig + ] + } + }; + + var settings = new LogSettings(); + + settings.LoadFile(conf); + + Assert.True(settings.LogsEnabled); + Assert.NotNull(settings.Processors); + Assert.Equal(3, settings.Processors.Count); + Assert.Empty(settings.LogExporters); + } + + [Fact] + public void LoadFile_DisablesLogs_WhenNoProcessorConfigured() + { + var conf = new YamlConfiguration + { + LoggerProvider = new LoggerProviderConfiguration + { + Processors = [] + } + }; + + var settings = new LogSettings(); + + settings.LoadFile(conf); + + Assert.False(settings.LogsEnabled); + Assert.NotNull(settings.Processors); + Assert.Empty(settings.Processors); + Assert.Empty(settings.LogExporters); + } + + [Fact] + public void LoadFile_HandlesNullExporterGracefully() + { + var batchProcessorConfig = new LogBatchProcessorConfig + { + Exporter = null + }; + + var conf = new YamlConfiguration + { + LoggerProvider = new LoggerProviderConfiguration + { + Processors = + [ + new LogProcessorConfig + { + Batch = batchProcessorConfig + } + ] + } + }; + + var settings = new LogSettings(); + + settings.LoadFile(conf); + + Assert.True(settings.LogsEnabled); + Assert.NotNull(settings.Processors); + Assert.Single(settings.Processors); + Assert.Empty(settings.LogExporters); + } + + [Fact] + public void LoadFile_LogsIncludeFormatedMessage() + { + var conf = new YamlConfiguration + { + LogsIncludeFormattedMessage = true, + }; + + var settings = new LogSettings(); + + settings.LoadFile(conf); + + Assert.True(settings.IncludeFormattedMessage); + } +} diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestLogsFile.yaml b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestLogsFile.yaml new file mode 100644 index 0000000000..6032b808e5 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestLogsFile.yaml @@ -0,0 +1,32 @@ +logs_include_formatted_message: true + +logger_provider: + processors: + - batch: + schedule_delay: 5000 + export_timeout: 30000 + max_queue_size: 2048 + max_export_batch_size: 512 + exporter: + otlp_http: + endpoint: http://localhost:4318/v1/logs + headers: + - name: api-key + value: "1234" + headers_list: api-key=1234 + compression: gzip + timeout: 10000 + + - batch: + exporter: + otlp_grpc: + endpoint: http://localhost:4317 + headers: + - name: api-key + value: "1234" + headers_list: api-key=1234 + timeout: 10000 + + - simple: + exporter: + console: diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestLogsFileEnvVars.yaml b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestLogsFileEnvVars.yaml new file mode 100644 index 0000000000..3fc9f8535f --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestLogsFileEnvVars.yaml @@ -0,0 +1,12 @@ +logger_provider: + processors: + - batch: + schedule_delay: ${OTEL_BSP_SCHEDULE_DELAY} + export_timeout: ${OTEL_BSP_EXPORT_TIMEOUT} + max_queue_size: ${OTEL_BSP_MAX_QUEUE_SIZE} + max_export_batch_size: ${OTEL_BSP_MAX_EXPORT_BATCH_SIZE} + exporter: + otlp_http: + endpoint: ${OTEL_EXPORTER_OTLP_LOGS_ENDPOINT} + timeout: ${OTEL_EXPORTER_OTLP_LOGS_TIMEOUT} + headers_list: ${OTEL_EXPORTER_OTLP_LOGS_HEADERS} diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserLogsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserLogsTests.cs new file mode 100644 index 0000000000..b9ecf18d37 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserLogsTests.cs @@ -0,0 +1,91 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Xunit; +using YamlParser = OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration.Parser.Parser; + +namespace OpenTelemetry.AutoInstrumentation.Tests.Configurations.FileBased.Parser; + +[Collection("Non-Parallel Collection")] +public class ParserLogsTests +{ + [Fact] + public void Parse_FullConfigYaml_ShouldPopulateModelCorrectly() + { + var config = YamlParser.ParseYaml("Configurations/FileBased/Files/TestLogsFile.yaml"); + Assert.NotNull(config); + + Assert.True(config.LogsIncludeFormattedMessage); + Assert.NotNull(config.LoggerProvider); + Assert.NotNull(config.LoggerProvider.Processors); + Assert.Equal(3, config.LoggerProvider.Processors.Count); + + var batchProcessor = config.LoggerProvider.Processors[0].Batch; + Assert.NotNull(batchProcessor); + Assert.Equal(5000, batchProcessor.ScheduleDelay); + Assert.Equal(30000, batchProcessor.ExportTimeout); + Assert.Equal(2048, batchProcessor.MaxQueueSize); + Assert.Equal(512, batchProcessor.MaxExportBatchSize); + + Assert.NotNull(batchProcessor.Exporter); + var httpExporter = batchProcessor.Exporter.OtlpHttp; + Assert.NotNull(httpExporter); + Assert.Equal("http://localhost:4318/v1/logs", httpExporter.Endpoint); + Assert.Equal(10000, httpExporter.Timeout); + + Assert.NotNull(httpExporter.Headers); + Assert.Single(httpExporter.Headers); + Assert.Equal("api-key", httpExporter.Headers[0].Name); + Assert.Equal("1234", httpExporter.Headers[0].Value); + Assert.Equal("api-key=1234", httpExporter.HeadersList); + + var grpcProcessor = config.LoggerProvider.Processors[1].Batch; + Assert.NotNull(grpcProcessor); + Assert.NotNull(grpcProcessor.Exporter); + var grpcExporter = grpcProcessor.Exporter.OtlpGrpc; + Assert.NotNull(grpcExporter); + Assert.Equal("http://localhost:4317", grpcExporter.Endpoint); + Assert.NotNull(grpcExporter.Headers); + Assert.Single(grpcExporter.Headers); + Assert.Equal("api-key", grpcExporter.Headers[0].Name); + Assert.Equal("1234", grpcExporter.Headers[0].Value); + Assert.Equal("api-key=1234", grpcExporter.HeadersList); + + var simpleProcessor = config.LoggerProvider.Processors[2].Simple; + Assert.NotNull(simpleProcessor); + Assert.NotNull(simpleProcessor.Exporter); + Assert.NotNull(simpleProcessor.Exporter.Console); + } + + [Fact] + public void Parse_EnvVarYaml_ShouldPopulateModelCompletely() + { + Environment.SetEnvironmentVariable("OTEL_BSP_SCHEDULE_DELAY", "7000"); + Environment.SetEnvironmentVariable("OTEL_BSP_EXPORT_TIMEOUT", "35000"); + Environment.SetEnvironmentVariable("OTEL_BSP_MAX_QUEUE_SIZE", "4096"); + Environment.SetEnvironmentVariable("OTEL_BSP_MAX_EXPORT_BATCH_SIZE", "1024"); + Environment.SetEnvironmentVariable("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT", "http://collector:4318/v1/logs"); + Environment.SetEnvironmentVariable("OTEL_EXPORTER_OTLP_LOGS_TIMEOUT", "15000"); + Environment.SetEnvironmentVariable("OTEL_EXPORTER_OTLP_LOGS_HEADERS", "header1=value1,header2=value2"); + + var config = YamlParser.ParseYaml("Configurations/FileBased/Files/TestLogsFileEnvVars.yaml"); + Assert.NotNull(config); + + Assert.NotNull(config.LoggerProvider); + Assert.NotNull(config.LoggerProvider.Processors); + var batchProcessor = config.LoggerProvider.Processors[0].Batch; + Assert.NotNull(batchProcessor); + Assert.Equal(7000, batchProcessor.ScheduleDelay); + Assert.Equal(35000, batchProcessor.ExportTimeout); + Assert.Equal(4096, batchProcessor.MaxQueueSize); + Assert.Equal(1024, batchProcessor.MaxExportBatchSize); + + Assert.NotNull(batchProcessor.Exporter); + var httpExporter = batchProcessor.Exporter.OtlpHttp; + Assert.NotNull(httpExporter); + Assert.Equal("http://collector:4318/v1/logs", httpExporter.Endpoint); + Assert.Equal(15000, httpExporter.Timeout); + Assert.Null(httpExporter.Headers); + Assert.Equal("header1=value1,header2=value2", httpExporter.HeadersList); + } +} diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj b/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj index 1bd11da871..b1cf8d882f 100644 --- a/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj @@ -15,6 +15,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -30,6 +33,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest