OpenTelemetrySdkMinimumVersionRule tests (#2420)

* Test changes.

* PR feedback
This commit is contained in:
Rajkumar Rangaraj 2023-04-11 10:03:00 -07:00 committed by GitHub
parent 782bf618cf
commit d2df8de6f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 323 additions and 14 deletions

View File

@ -22,7 +22,7 @@ namespace OpenTelemetry.AutoInstrumentation.RulesEngine;
internal class OpenTelemetrySdkMinimumVersionRule : Rule
{
private static readonly IOtelLogger Logger = OtelLogging.GetLogger("StartupHook");
private static IOtelLogger logger = OtelLogging.GetLogger("StartupHook");
public OpenTelemetrySdkMinimumVersionRule()
{
@ -30,41 +30,67 @@ internal class OpenTelemetrySdkMinimumVersionRule : Rule
Description = "Ensure that the OpenTelemetry SDK version is not older than the version used by the Auto-Instrumentation";
}
// This constructor is used for test purpose.
protected OpenTelemetrySdkMinimumVersionRule(IOtelLogger otelLogger)
: this()
{
logger = otelLogger;
}
internal override bool Evaluate()
{
string? oTelPackageVersion = null;
try
{
var openTelemetryType = Type.GetType("OpenTelemetry.Sdk, OpenTelemetry");
if (openTelemetryType != null)
var loadedOTelFileVersion = GetVersionFromApp();
if (loadedOTelFileVersion != null)
{
var loadedOTelAssembly = Assembly.GetAssembly(openTelemetryType);
var loadedOTelFileVersionInfo = FileVersionInfo.GetVersionInfo(loadedOTelAssembly?.Location);
var loadedOTelFileVersion = new Version(loadedOTelFileVersionInfo.FileVersion);
var autoInstrumentationOTelLocation = Path.Combine(StartupHook.LoaderAssemblyLocation ?? string.Empty, "OpenTelemetry.dll");
var autoInstrumentationOTelFileVersionInfo = FileVersionInfo.GetVersionInfo(autoInstrumentationOTelLocation);
var autoInstrumentationOTelFileVersion = new Version(autoInstrumentationOTelFileVersionInfo.FileVersion);
var autoInstrumentationOTelFileVersion = GetVersionFromAutoInstrumentation();
if (loadedOTelFileVersion < autoInstrumentationOTelFileVersion)
{
oTelPackageVersion = loadedOTelFileVersionInfo.FileVersion;
oTelPackageVersion = loadedOTelFileVersion.ToString();
}
}
}
catch (Exception ex)
{
// Exception in evaluation should not throw or crash the process.
Logger.Information($"Couldn't evaluate reference to OpenTelemetry Sdk in an app. Exception: {ex}");
logger.Information($"Rule Engine: Couldn't evaluate reference to OpenTelemetry Sdk in an app. Exception: {ex}");
return true;
}
if (oTelPackageVersion != null)
{
Logger.Error($"Application has direct or indirect reference to older version of OpenTelemetry package {oTelPackageVersion}.");
logger.Error($"Rule Engine: Application has direct or indirect reference to older version of OpenTelemetry package {oTelPackageVersion}.");
return false;
}
logger.Information("Rule Engine: OpenTelemetrySdkMinimumVersionRule evaluation success.");
return true;
}
protected virtual Version? GetVersionFromApp()
{
var openTelemetryType = Type.GetType("OpenTelemetry.Sdk, OpenTelemetry");
if (openTelemetryType != null)
{
var loadedOTelAssembly = Assembly.GetAssembly(openTelemetryType);
var loadedOTelFileVersionInfo = FileVersionInfo.GetVersionInfo(loadedOTelAssembly?.Location);
var loadedOTelFileVersion = new Version(loadedOTelFileVersionInfo.FileVersion);
return loadedOTelFileVersion;
}
return null;
}
protected virtual Version? GetVersionFromAutoInstrumentation()
{
var autoInstrumentationOTelLocation = Path.Combine(StartupHook.LoaderAssemblyLocation ?? string.Empty, "OpenTelemetry.dll");
var autoInstrumentationOTelFileVersionInfo = FileVersionInfo.GetVersionInfo(autoInstrumentationOTelLocation);
var autoInstrumentationOTelFileVersion = new Version(autoInstrumentationOTelFileVersionInfo.FileVersion);
return autoInstrumentationOTelFileVersion;
}
}

View File

@ -0,0 +1,71 @@
// <copyright file="OpenTelemetrySdkMinimumVersionRuleTests.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.Logging;
using OpenTelemetry.AutoInstrumentation.RulesEngine;
using Xunit;
namespace OpenTelemetry.AutoInstrumentation.StartupHook.Tests;
public class OpenTelemetrySdkMinimumVersionRuleTests
{
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
public static IEnumerable<object[]> RuleTestData =>
new List<object[]>
{
new object[] { new Version("1.0.0.0"), new Version("2.0.0.0"), "Rule Engine: Application has direct or indirect reference to older version of OpenTelemetry package 1.0.0.0.", false },
new object[] { new Version("2.0.0.0"), new Version("1.0.0.0"), "Rule Engine: OpenTelemetrySdkMinimumVersionRule evaluation success.", true },
new object[] { new Version("1.0.0.0"), new Version("1.0.0.0"), "Rule Engine: OpenTelemetrySdkMinimumVersionRule evaluation success.", true },
new object[] { null, new Version("1.0.0.0"), "Rule Engine: OpenTelemetrySdkMinimumVersionRule evaluation success.", true },
new object[] { new Version("1.0.0.0"), null, "Rule Engine: OpenTelemetrySdkMinimumVersionRule evaluation success.", true },
new object[] { null, null, "Rule Engine: OpenTelemetrySdkMinimumVersionRule evaluation success.", true },
};
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
[Theory]
[MemberData(nameof(RuleTestData))]
public void OpenTelemetrySdkMinimumVersionRuleValidation(Version appVersion, Version autoInstrumentationVersion, string logMessage, bool result)
{
var logger = new TestLogger();
var rule = new OpenTelemetrySdkMinimumVersionTestRule(appVersion, autoInstrumentationVersion, logger);
var ruleResult = rule.Evaluate();
Assert.Equal(logMessage, logger.LogRecords[0].Message);
Assert.Equal(result, ruleResult);
}
private class OpenTelemetrySdkMinimumVersionTestRule : OpenTelemetrySdkMinimumVersionRule
{
private readonly Version _appVersion;
private readonly Version _autoInstrumentationVersion;
public OpenTelemetrySdkMinimumVersionTestRule(Version appVersion, Version autoInstrumentationVersion, IOtelLogger otelLogger)
: base(otelLogger)
{
_appVersion = appVersion;
_autoInstrumentationVersion = autoInstrumentationVersion;
}
protected override Version? GetVersionFromApp()
{
return _appVersion;
}
protected override Version? GetVersionFromAutoInstrumentation()
{
return _autoInstrumentationVersion;
}
}
}

View File

@ -0,0 +1,212 @@
// <copyright file="TestLogger.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>
namespace OpenTelemetry.AutoInstrumentation.Logging;
/// <summary>
/// Test implementation.
/// </summary>
internal class TestLogger : IOtelLogger
{
public List<LogRecord> LogRecords { get; } = new List<LogRecord>();
public LogLevel Level => default;
public bool IsEnabled(LogLevel level)
{
return true;
}
public void Debug(string messageTemplate, bool writeToEventLog = true)
{
}
public void Debug<T>(string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Debug<T0, T1>(string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Debug<T0, T1, T2>(string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Debug(string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Debug(Exception exception, string messageTemplate, bool writeToEventLog = true)
{
}
public void Debug<T>(Exception exception, string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Debug<T0, T1>(Exception exception, string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Debug<T0, T1, T2>(Exception exception, string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Debug(Exception exception, string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Information(string messageTemplate, bool writeToEventLog = true)
{
var logRecord = new LogRecord(LogLevel.Information, messageTemplate);
LogRecords.Add(logRecord);
}
public void Information<T>(string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Information<T0, T1>(string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Information<T0, T1, T2>(string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Information(string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Information(Exception exception, string messageTemplate, bool writeToEventLog = true)
{
}
public void Information<T>(Exception exception, string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Information<T0, T1>(Exception exception, string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Information<T0, T1, T2>(Exception exception, string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Information(Exception exception, string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Warning(string messageTemplate, bool writeToEventLog = true)
{
}
public void Warning<T>(string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Warning<T0, T1>(string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Warning<T0, T1, T2>(string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Warning(string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Warning(Exception exception, string messageTemplate, bool writeToEventLog = true)
{
}
public void Warning<T>(Exception exception, string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Warning<T0, T1>(Exception exception, string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Warning<T0, T1, T2>(Exception exception, string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Warning(Exception exception, string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Error(string messageTemplate, bool writeToEventLog = true)
{
var logRecord = new LogRecord(LogLevel.Error, messageTemplate);
LogRecords.Add(logRecord);
}
public void Error<T>(string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Error<T0, T1>(string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Error<T0, T1, T2>(string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Error(string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
public void Error(Exception exception, string messageTemplate, bool writeToEventLog = true)
{
}
public void Error<T>(Exception exception, string messageTemplate, T property, bool writeToEventLog = true)
{
}
public void Error<T0, T1>(Exception exception, string messageTemplate, T0 property0, T1 property1, bool writeToEventLog = true)
{
}
public void Error<T0, T1, T2>(Exception exception, string messageTemplate, T0 property0, T1 property1, T2 property2, bool writeToEventLog = true)
{
}
public void Error(Exception exception, string messageTemplate, object[] args, bool writeToEventLog = true)
{
}
internal class LogRecord
{
public LogRecord(LogLevel logLevel, string message, Exception? exception = null)
{
LogLevel = logLevel;
Message = message;
Exception = exception;
}
public LogLevel LogLevel { get; }
public string Message { get; }
public Exception? Exception { get; }
}
}