Skip to content

Commit

Permalink
RuleEngineTracker to control rule engine execution (#2407)
Browse files Browse the repository at this point in the history
  • Loading branch information
rajkumar-rangaraj authored Apr 6, 2023
1 parent 765a89c commit 44a24c4
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
15 changes: 15 additions & 0 deletions OpenTelemetry.AutoInstrumentation.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down
16 changes: 16 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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")]
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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;
}
}
}

0 comments on commit 44a24c4

Please sign in to comment.