RuleEngineTracker to control rule engine execution (#2407)
This commit is contained in:
parent
765a89c46d
commit
44a24c4922
|
|
@ -16,6 +16,10 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
|
|||
the entry assembly name instead, only falling back to the process name
|
||||
in case of an error. If the application uses .NET Framework and is hosted
|
||||
on IIS, the service name is determined using `SiteName/ApplicationVirtualPath`.
|
||||
- Added a rule engine to validate potential conflicts and unsupported scenarios,
|
||||
ensuring back off instead of crashing, improving overall stability.
|
||||
- The environment variable `OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED` could be
|
||||
used to enable or disable the rule engine.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.SelfContain
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.EntityFrameworkCore.Pomelo.MySql", "test\test-applications\integrations\TestApplication.EntityFrameworkCore.Pomelo.MySql\TestApplication.EntityFrameworkCore.Pomelo.MySql.csproj", "{1D7E11AA-27B6-4863-B5EC-1F0ECC6979B2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.AutoInstrumentation.StartupHook.Tests", "test\OpenTelemetry.AutoInstrumentation.StartupHook.Tests\OpenTelemetry.AutoInstrumentation.StartupHook.Tests.csproj", "{0077F121-DC2B-425E-A2F4-DEAC2A566E14}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -849,6 +851,18 @@ Global
|
|||
{1D7E11AA-27B6-4863-B5EC-1F0ECC6979B2}.Release|x64.Build.0 = Release|x64
|
||||
{1D7E11AA-27B6-4863-B5EC-1F0ECC6979B2}.Release|x86.ActiveCfg = Release|x86
|
||||
{1D7E11AA-27B6-4863-B5EC-1F0ECC6979B2}.Release|x86.Build.0 = Release|x86
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -914,6 +928,7 @@ Global
|
|||
{2EF2F7CE-E56F-4B81-A5A5-277693529D43} = {91A299AD-6C09-4B7F-BD8B-A705D9BFC672}
|
||||
{25ED93D0-A70C-4A07-84D9-EF94115259C9} = {2EF2F7CE-E56F-4B81-A5A5-277693529D43}
|
||||
{1D7E11AA-27B6-4863-B5EC-1F0ECC6979B2} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
|
||||
{0077F121-DC2B-425E-A2F4-DEAC2A566E14} = {5C915382-C886-457D-8641-9E766D8E5A17}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
|
||||
|
|
|
|||
|
|
@ -325,6 +325,22 @@ Important environment variables include:
|
|||
| `OTEL_DOTNET_AUTO_METRICS_ADDITIONAL_SOURCES` | Comma-separated list of additional `System.Diagnostics.Metrics.Meter` names to be added to the meter at the startup. Use it to capture manually instrumented spans. | | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
| `OTEL_DOTNET_AUTO_PLUGINS` | Colon-separated list of OTel SDK instrumentation plugin types, specified with the [assembly-qualified name](https://docs.microsoft.com/en-us/dotnet/api/system.type.assemblyqualifiedname?view=net-6.0#system-type-assemblyqualifiedname). _Note: This list must be colon-separated because the type names may include commas._ See more info on how to write plugins at [plugins.md](plugins.md). | | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
|
||||
## RuleEngine
|
||||
|
||||
RuleEngine is a feature that validates OpenTelemetry API, SDK,
|
||||
Instrumentation, and Exporter assemblies for unsupported scenarios,
|
||||
ensuring that OpenTelemetry automatic instrumentation is more
|
||||
stable by backing of instead of crashing. It works on .NET 6 and higher.
|
||||
|
||||
Enable RuleEngine only during the first run of the application,
|
||||
or when the deployment changes or the Automatic Instrumentation
|
||||
library is upgraded. Once validated, there's no need to revalidate
|
||||
the rules when the application restarts.
|
||||
|
||||
| Environment variable | Description | Default value | Status |
|
||||
|--------------------------------------- |---------------------|----------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED` | Enables RuleEngine. | `true` | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
|
||||
|
||||
## .NET CLR Profiler
|
||||
|
||||
The CLR uses the following
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("OpenTelemetry.AutoInstrumentation.StartupHook.Tests")]
|
||||
|
|
@ -29,10 +29,26 @@ internal class RuleEngine
|
|||
new InstrumentationAssemblyRule()
|
||||
};
|
||||
|
||||
internal RuleEngine()
|
||||
{
|
||||
}
|
||||
|
||||
// This constructor is used for test purpose.
|
||||
internal RuleEngine(List<Rule> rules)
|
||||
{
|
||||
_rules = rules;
|
||||
}
|
||||
|
||||
internal bool Validate()
|
||||
{
|
||||
var result = true;
|
||||
|
||||
if (bool.TryParse(Environment.GetEnvironmentVariable("OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED"), out var shouldTrack) && !shouldTrack)
|
||||
{
|
||||
Logger.Information($"OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED is set to false, skipping rule engine validation.");
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var rule in _rules)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\OpenTelemetry.AutoInstrumentation.StartupHook\OpenTelemetry.AutoInstrumentation.StartupHook.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// <copyright file="RuleEngineTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using OpenTelemetry.AutoInstrumentation.RulesEngine;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.StartupHook.Tests;
|
||||
|
||||
public class RuleEngineTests : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED", null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RuleEngineValidation_WhenShouldTrackIsTrue()
|
||||
{
|
||||
// Arrange
|
||||
SetShouldTrackEnvironmentVariable(true);
|
||||
var testRule = new TestRule();
|
||||
var ruleEngine = new RuleEngine(new List<Rule> { testRule });
|
||||
|
||||
// Act
|
||||
var result = ruleEngine.Validate();
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.True(testRule.IsEvaluated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RuleEngineValidation_WhenShouldTrackIsFalse()
|
||||
{
|
||||
// Arrange
|
||||
SetShouldTrackEnvironmentVariable(false);
|
||||
var testRule = new TestRule();
|
||||
var ruleEngine = new RuleEngine(new List<Rule> { testRule });
|
||||
|
||||
// Act
|
||||
var result = ruleEngine.Validate();
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.False(testRule.IsEvaluated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RuleEngineValidation_WhenShouldTrackIsNull()
|
||||
{
|
||||
// Arrange
|
||||
SetShouldTrackEnvironmentVariable(null);
|
||||
var testRule = new TestRule();
|
||||
var ruleEngine = new RuleEngine(new List<Rule> { testRule });
|
||||
|
||||
// Act
|
||||
var result = ruleEngine.Validate();
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.True(testRule.IsEvaluated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RuleEngineValidation_WhenShouldTrackIsNotSet()
|
||||
{
|
||||
// Arrange
|
||||
var testRule = new TestRule();
|
||||
var ruleEngine = new RuleEngine(new List<Rule> { testRule });
|
||||
|
||||
// Act
|
||||
var result = ruleEngine.Validate();
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.True(testRule.IsEvaluated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RuleEngineValidation_WhenShouldTrackHasInvalidValue()
|
||||
{
|
||||
// Arrange
|
||||
Environment.SetEnvironmentVariable("OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED", "Invalid");
|
||||
var testRule = new TestRule();
|
||||
var ruleEngine = new RuleEngine(new List<Rule> { testRule });
|
||||
|
||||
// Act
|
||||
var result = ruleEngine.Validate();
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.True(testRule.IsEvaluated);
|
||||
}
|
||||
|
||||
private void SetShouldTrackEnvironmentVariable(bool? value)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OTEL_DOTNET_AUTO_RULE_ENGINE_ENABLED", value?.ToString());
|
||||
}
|
||||
|
||||
private class TestRule : Rule
|
||||
{
|
||||
internal bool IsEvaluated { get; private set; }
|
||||
|
||||
internal override bool Evaluate()
|
||||
{
|
||||
IsEvaluated = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue