Support OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED for StartupHook (#2524)
* Documentation * StartupHook - FailFast * Remove unused const * Typo fix * Smoke test for FastFail * Add test for FailFast disabled * better documentation * typo fix
This commit is contained in:
		
							parent
							
								
									12381ceac9
								
							
						
					
					
						commit
						a290429994
					
				|  | @ -9,6 +9,10 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h | |||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| - The environment variable `OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED` could be | ||||
|   used to enable or disable the failing process when | ||||
|   automatic instrumentation cannot be executed. | ||||
| 
 | ||||
| ### Changed | ||||
| 
 | ||||
| ### Deprecated | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ with environment variables taking precedence over `App.config` or `Web.config` f | |||
| 
 | ||||
|     - `OTEL_DOTNET_AUTO_HOME` | ||||
|     - `OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES` | ||||
|     - `OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED` | ||||
|     - `OTEL_DOTNET_AUTO_[TRACES|METRICS|LOGS]_INSTRUMENTATIONS_ENABLED` | ||||
|     - `OTEL_DOTNET_AUTO_[TRACES|METRICS|LOGS]_{INSTRUMENTATION_ID}_INSTRUMENTATION_ENABLED` | ||||
|     - `OTEL_DOTNET_AUTO_LOG_DIRECTORY` | ||||
|  | @ -53,11 +54,16 @@ However, if given setting supports it, then: | |||
| ## Global settings | ||||
| 
 | ||||
| | Environment variable                 | Description                                                                                                                                                                                                                        | Default value | Status                                                                                                                            | | ||||
| |--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------| | ||||
| |--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `OTEL_DOTNET_AUTO_HOME`              | Installation location.                                                                                                                                                                                                             |               | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
| | `OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES` | Names of the executable files that the profiler cannot instrument. Supports multiple comma-separated values, for example: `ReservedProcess.exe,powershell.exe`. If unset, the profiler attaches to all processes by default. |               | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
| | `OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES` | Names of the executable files that the profiler cannot instrument. Supports multiple comma-separated values, for example: `ReservedProcess.exe,powershell.exe`. If unset, the profiler attaches to all processes by default. \[1\] |               | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
| | `OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED` | Enables possibility to fail process when automatic instrumentation cannot be executed. It is designed for debugging purposes. It should not be used in production environment. \[1\]                                               | `false`       | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
| | `OTEL_LOG_LEVEL`                     | SDK log level. (supported values: `none`,`error`,`warn`,`info`,`debug`)                                                                                                                                                            | `info`        | [Stable](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md)       | | ||||
| 
 | ||||
| \[1\] If `OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED` is set to `true` then processes | ||||
| excluded from instrumentation by `OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES` will fail | ||||
| instead of silently continue. | ||||
| 
 | ||||
| ## Resources | ||||
| 
 | ||||
| A resource is the immutable representation of the entity producing the telemetry. | ||||
|  | @ -100,7 +106,7 @@ environment variable to `false`, where `{SIGNAL}` is the type of signal, | |||
| for example `TRACES`, and `{0}` is the case-sensitive name of the instrumentation. | ||||
| 
 | ||||
| | Environment variable                                   | Description                                                                                                                                                                                                    | Default value                                                                          | Status                                                                                                                            | | ||||
| |--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------| | ||||
| |--------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `OTEL_DOTNET_AUTO_INSTRUMENTATION_ENABLED`             | Enables all instrumentations.                                                                                                                                                                                  | `true`                                                                                 | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
| | `OTEL_DOTNET_AUTO_TRACES_INSTRUMENTATION_ENABLED`      | Enables all trace instrumentations. Overrides `OTEL_DOTNET_AUTO_INSTRUMENTATION_ENABLED`.                                                                                                                      | Inherited from the current value of `OTEL_DOTNET_AUTO_INSTRUMENTATION_ENABLED`         | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
| | `OTEL_DOTNET_AUTO_TRACES_{0}_INSTRUMENTATION_ENABLED`  | Configuration pattern for enabling a specific trace instrumentation, where `{0}` is the uppercase id of the instrumentation you want to enable. Overrides `OTEL_DOTNET_AUTO_TRACES_INSTRUMENTATION_ENABLED`.   | Inherited from the current value of `OTEL_DOTNET_AUTO_TRACES_INSTRUMENTATION_ENABLED`  | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) | | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ | |||
| // </copyright> | ||||
| 
 | ||||
| using System.Reflection; | ||||
| using System.Runtime.Versioning; | ||||
| using OpenTelemetry.AutoInstrumentation.Logging; | ||||
| using OpenTelemetry.AutoInstrumentation.RulesEngine; | ||||
| 
 | ||||
|  | @ -35,6 +34,8 @@ internal class StartupHook | |||
|     /// </summary> | ||||
|     public static void Initialize() | ||||
|     { | ||||
|         bool.TryParse(Environment.GetEnvironmentVariable("OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED"), out var failFast); | ||||
| 
 | ||||
|         try | ||||
|         { | ||||
|             LoaderAssemblyLocation = GetLoaderAssemblyLocation(); | ||||
|  | @ -42,20 +43,22 @@ internal class StartupHook | |||
|             var ruleEngine = new RuleEngine(); | ||||
|             if (!ruleEngine.ValidateRules()) | ||||
|             { | ||||
|                 Logger.Error("Rule Engine Failure: One or more rules failed validation. Automatic Instrumentation won't be loaded."); | ||||
|                 return; | ||||
|                 throw new Exception("Rule Engine Failure: One or more rules failed validation. Automatic Instrumentation won't be loaded."); | ||||
|             } | ||||
| 
 | ||||
|             Logger.Information("Initialization."); | ||||
| 
 | ||||
|             // Creating an instance of OpenTelemetry.AutoInstrumentation.Loader.Startup | ||||
|             // will initialize Instrumentation through its static constructor. | ||||
|             string loaderFilePath = Path.Combine(LoaderAssemblyLocation, "OpenTelemetry.AutoInstrumentation.Loader.dll"); | ||||
|             Assembly loaderAssembly = Assembly.LoadFrom(loaderFilePath); | ||||
|             var loaderFilePath = Path.Combine(LoaderAssemblyLocation, "OpenTelemetry.AutoInstrumentation.Loader.dll"); | ||||
|             var loaderAssembly = Assembly.LoadFrom(loaderFilePath); | ||||
|             var loaderInstance = loaderAssembly.CreateInstance("OpenTelemetry.AutoInstrumentation.Loader.Loader"); | ||||
|             if (loaderInstance is null) | ||||
|             { | ||||
|                 Logger.Error("StartupHook failed to create an instance of the Loader"); | ||||
|                 if (failFast) | ||||
|                 { | ||||
|                     throw new Exception("StartupHook failed to create an instance of the Loader"); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | @ -64,10 +67,13 @@ internal class StartupHook | |||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             Logger.Error($"Error in StartupHook initialization: LoaderFolderLocation: {LoaderAssemblyLocation}, Error: {ex}"); | ||||
|             Logger.Error(ex, $"Error in StartupHook initialization: LoaderFolderLocation: {LoaderAssemblyLocation}"); | ||||
|             if (failFast) | ||||
|             { | ||||
|                 throw; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static string GetLoaderAssemblyLocation() | ||||
|     { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| namespace OpenTelemetry.AutoInstrumentation.Configurations; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Represents the configration taken from one or more configuration sources. | ||||
| /// Represents the configuration taken from one or more configuration sources. | ||||
| /// </summary> | ||||
| internal class Configuration | ||||
| { | ||||
|  |  | |||
|  | @ -32,14 +32,6 @@ internal static class ConfigurationKeys | |||
|     /// </summary> | ||||
|     public const string ExporterOtlpProtocol = "OTEL_EXPORTER_OTLP_PROTOCOL"; | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// Configuration key for setting the directory for the profiler's log files. | ||||
|     /// If not set, default is | ||||
|     /// "%ProgramData%"\OpenTelemetry .NET AutoInstrumentation\logs\" on Windows or | ||||
|     /// "/var/log/opentelemetry/dotnet/" on Linux. | ||||
|     /// </summary> | ||||
|     public const string LogDirectory = "OTEL_DOTNET_AUTO_LOG_DIRECTORY"; | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// Configuration key for enabling the flushing of telemetry data when an unhandled exception occurs. | ||||
|     /// </summary> | ||||
|  |  | |||
|  | @ -15,12 +15,12 @@ | |||
| // </copyright> | ||||
| 
 | ||||
| using System.Reflection; | ||||
| using FluentAssertions; | ||||
| using IntegrationTests.Helpers; | ||||
| using Xunit.Abstractions; | ||||
| 
 | ||||
| #if NETFRAMEWORK | ||||
| using System.Net; | ||||
| using FluentAssertions; | ||||
| using FluentAssertions.Extensions; | ||||
| using IntegrationTests.Helpers.Compatibility; | ||||
| #endif | ||||
|  | @ -348,6 +348,38 @@ public class SmokeTests : TestHelper | |||
|         collector.AssertEmpty(); | ||||
|     } | ||||
| 
 | ||||
|     [Fact] | ||||
|     [Trait("Category", "EndToEnd")] | ||||
|     public void ApplicationFailFastDisabled() | ||||
|     { | ||||
|         SetEnvironmentVariable("OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES", $"dotnet,dotnet.exe,{EnvironmentHelper.FullTestApplicationName},{EnvironmentHelper.FullTestApplicationName}.exe"); | ||||
|         SetEnvironmentVariable("OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED", "false"); | ||||
| 
 | ||||
|         VerifyTestApplicationNotInstrumented(); | ||||
|     } | ||||
| 
 | ||||
| #if NET6_0_OR_GREATER | ||||
|     [Fact] | ||||
|     [Trait("Category", "EndToEnd")] | ||||
|     public void ApplicationFailFastEnabled() | ||||
|     { | ||||
|         SetEnvironmentVariable("OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES", $"dotnet,dotnet.exe,{EnvironmentHelper.FullTestApplicationName},{EnvironmentHelper.FullTestApplicationName}.exe"); | ||||
|         SetEnvironmentVariable("OTEL_DOTNET_AUTO_FAIL_FAST_ENABLED", "true"); | ||||
|         var process = StartTestApplication(); | ||||
| 
 | ||||
|         process.Should().NotBeNull(); | ||||
|         var processTimeout = !process!.WaitForExit((int)TestTimeout.ProcessExit.TotalMilliseconds); | ||||
|         if (processTimeout) | ||||
|         { | ||||
|             process.Kill(); | ||||
|         } | ||||
| 
 | ||||
|         processTimeout.Should().BeFalse(); | ||||
| 
 | ||||
|         process!.ExitCode.Should().NotBe(0); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     private void VerifyTestApplicationInstrumented() | ||||
|     { | ||||
|         using var collector = new MockSpansCollector(Output); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue