Enable/disable log instrumentations (#1475)
* Introduce instrumentation types * extend generator * support for disabling logs bytecode integrations * update documentation * change LoggingBuilder instrumentation name to ILogger * Support managing log instrumentation in managed code * update changelog * PR feedback - config * add LogsNoneInstrumentations test Co-authored-by: Chris Ventura <45495992+nrcventura@users.noreply.github.com>
This commit is contained in:
parent
b451a89637
commit
b4a4120bbd
|
@ -14,6 +14,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
- Support ASP.NET Core OpenTelemetry Log exporter related environment variables:
|
||||
- `OTEL_LOGS_EXPORTER`,
|
||||
- `OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED`,
|
||||
- `OTEL_DOTNET_AUTO_LOGS_ENABLED_INSTRUMENTATIONS`,
|
||||
- `OTEL_DOTNET_AUTO_LOGS_DISABLED_INSTRUMENTATIONS`,
|
||||
- `OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE`.
|
||||
- Support `OTEL_DOTNET_AUTO_GRAPHQL_SET_DOCUMENT` (default value: `false`)
|
||||
environment variable which controls whether `graphql.document` attribute
|
||||
|
|
|
@ -25,10 +25,12 @@ for more details.
|
|||
| Environment variable | Description | Default value |
|
||||
|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|
|
||||
| `OTEL_DOTNET_AUTO_INTEGRATIONS_FILE` | List of bytecode instrumentations JSON configuration filepaths, delimited by the platform-specific path separator (`;` on Windows, `:` on Linux and macOS). For example: `%ProfilerDirectory%/integrations.json`. It is required for bytecode instrumentations. | |
|
||||
| `OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS` | Comma-separated list of traces source instrumentations you want to enable. Set `none` to disable all trace instrumentations. | all available instrumentations |
|
||||
| `OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS` | Comma-separated list of traces source instrumentations you want to enable. Set to `none` to disable all trace instrumentations. | all available instrumentations |
|
||||
| `OTEL_DOTNET_AUTO_TRACES_DISABLED_INSTRUMENTATIONS` | Comma-separated list of traces source and bytecode instrumentations you want to disable. | |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_ENABLED_INSTRUMENTATIONS` | Comma-separated list of metrics source instrumentations you want to enable. Set `none` to disable all metric instrumentations. | all available instrumentations |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_ENABLED_INSTRUMENTATIONS` | Comma-separated list of metrics source instrumentations you want to enable. Set to `none` to disable all metric instrumentations. | all available instrumentations |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_DISABLED_INSTRUMENTATIONS` | Comma-separated list of metrics source instrumentations you want to disable. | |
|
||||
| `OTEL_DOTNET_AUTO_LOGS_ENABLED_INSTRUMENTATIONS` | Comma-separated list of logs source instrumentations you want to enable. Set to `none` to disable all metric instrumentations. | all available instrumentations |
|
||||
| `OTEL_DOTNET_AUTO_LOGS_DISABLED_INSTRUMENTATIONS` | Comma-separated list of logs source instrumentations you want to disable. | |
|
||||
|
||||
### Traces instrumentations
|
||||
|
||||
|
@ -61,9 +63,9 @@ for more details.
|
|||
|
||||
### Logs instrumentations
|
||||
|
||||
| ID | Instrumented library | Supported versions | Instrumentation type |
|
||||
|----|---------------------------------------------------------------------------------------------------------------------------------|--------------------|------------------------|
|
||||
| | [Microsoft.Extensions.Logging](https://www.nuget.org/packages/Microsoft.Extensions.Logging) **Not supported on .NET Framework** | ≥6.0.0 | bytecode or source [1] |
|
||||
| ID | Instrumented library | Supported versions | Instrumentation type |
|
||||
|---------|---------------------------------------------------------------------------------------------------------------------------------|--------------------|------------------------|
|
||||
| ILogger | [Microsoft.Extensions.Logging](https://www.nuget.org/packages/Microsoft.Extensions.Logging) **Not supported on .NET Framework** | ≥6.0.0 | bytecode or source [1] |
|
||||
|
||||
**[1]**: For ASP.NET Core applications, the `LoggingBuilder` instrumentation
|
||||
can be enabled without using the .NET CLR Profiler by setting
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[
|
||||
{
|
||||
"name": "GraphQL",
|
||||
"type": "Trace",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
|
@ -51,7 +52,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "LoggingBuilder",
|
||||
"name": "ILogger",
|
||||
"type": "Log",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
|
@ -80,6 +82,7 @@
|
|||
},
|
||||
{
|
||||
"name": "MongoDB",
|
||||
"type": "Trace",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
|
@ -108,6 +111,7 @@
|
|||
},
|
||||
{
|
||||
"name": "MySqlData",
|
||||
"type": "Trace",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
|
@ -135,6 +139,7 @@
|
|||
},
|
||||
{
|
||||
"name": "StackExchangeRedis",
|
||||
"type": "Trace",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
|
|
|
@ -28,14 +28,14 @@ namespace OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper;
|
|||
/// </summary>
|
||||
internal class BootstrapperHostingStartup : IHostingStartup
|
||||
{
|
||||
private readonly LogSettings settings;
|
||||
private readonly LogSettings _settings;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BootstrapperHostingStartup"/> class.
|
||||
/// </summary>
|
||||
public BootstrapperHostingStartup()
|
||||
{
|
||||
settings = LogSettings.FromDefaultSources();
|
||||
_settings = LogSettings.FromDefaultSources();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -44,6 +44,12 @@ internal class BootstrapperHostingStartup : IHostingStartup
|
|||
/// <param name="builder">The <see cref="IWebHostBuilder"/>.</param>
|
||||
public void Configure(IWebHostBuilder builder)
|
||||
{
|
||||
if (!_settings.EnabledInstrumentations.Contains(LogInstrumentation.ILogger))
|
||||
{
|
||||
BootstrapperEventSource.Log.Trace($"BootstrapperHostingStartup loaded, but {nameof(LogInstrumentation.ILogger)} instrumentation is disabled. Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
builder.ConfigureLogging(logging => logging.AddOpenTelemetryLogs());
|
||||
|
|
|
@ -179,7 +179,12 @@ HRESULT STDMETHODCALLTYPE CorProfiler::Initialize(IUnknown* cor_profiler_info_un
|
|||
rejit_handler = new RejitHandler(this->info_, callback);
|
||||
|
||||
// load all integrations from JSON files
|
||||
LoadIntegrationsFromEnvironment(integration_methods_, GetEnvironmentValues(environment::enabled_integrations), GetEnvironmentValues(environment::disabled_integrations));
|
||||
LoadIntegrationsFromEnvironment(
|
||||
integration_methods_,
|
||||
GetEnvironmentValues(environment::enabled_traces_integrations),
|
||||
GetEnvironmentValues(environment::disabled_traces_integrations),
|
||||
GetEnvironmentValues(environment::enabled_logs_integrations),
|
||||
GetEnvironmentValues(environment::disabled_logs_integrations));
|
||||
|
||||
Logger::Debug("Number of Integrations loaded: ", integration_methods_.size());
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ const WSTRING exclude_process_names = WStr("OTEL_DOTNET_AUTO_EXCLUDE_PROCESSES")
|
|||
// Sets a list of integrations to enable. If not set (default), all integrations are enabled.
|
||||
// Supports multiple values separated with comma, for example:
|
||||
// "ElasticsearchNet,AspNetWebApi2"
|
||||
const WSTRING enabled_integrations =
|
||||
const WSTRING enabled_traces_integrations =
|
||||
WStr("OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS");
|
||||
|
||||
// Sets a list of integrations to disable. Status of other integrations will remain
|
||||
|
@ -45,9 +45,24 @@ const WSTRING enabled_integrations =
|
|||
// then if instrumentation is not explicitly disabled OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS is checked.
|
||||
// Supports multiple values separated with comma, for example:
|
||||
// "ElasticsearchNet,AspNetWebApi2"
|
||||
const WSTRING disabled_integrations =
|
||||
const WSTRING disabled_traces_integrations =
|
||||
WStr("OTEL_DOTNET_AUTO_TRACES_DISABLED_INSTRUMENTATIONS");
|
||||
|
||||
// Sets a list of integrations to enable. If not set (default), all integrations
|
||||
// are enabled. Supports multiple values separated with comma, for example:
|
||||
// "ElasticsearchNet,AspNetWebApi2"
|
||||
const WSTRING enabled_logs_integrations =
|
||||
WStr("OTEL_DOTNET_AUTO_LOGS_ENABLED_INSTRUMENTATIONS");
|
||||
|
||||
// Sets a list of integrations to disable. Status of other integrations will
|
||||
// remain unchanged. Calculation order:
|
||||
// OTEL_DOTNET_AUTO_LOGS_DISABLED_INSTRUMENTATIONS then if instrumentation is
|
||||
// not explicitly disabled OTEL_DOTNET_AUTO_LOGS_ENABLED_INSTRUMENTATIONS is
|
||||
// checked. Supports multiple values separated with comma, for example:
|
||||
// "ElasticsearchNet,AspNetWebApi2"
|
||||
const WSTRING disabled_logs_integrations =
|
||||
WStr("OTEL_DOTNET_AUTO_LOGS_DISABLED_INSTRUMENTATIONS");
|
||||
|
||||
// Sets the directory for the profiler's log file.
|
||||
// If not set, default is
|
||||
// "%ProgramData%"\OpenTelemetry .NET AutoInstrumentation\logs\" on Windows or
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "integration_loader.h"
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "environment_variables.h"
|
||||
#include "logger.h"
|
||||
|
@ -14,20 +13,25 @@ using json = nlohmann::json;
|
|||
|
||||
void LoadIntegrationsFromEnvironment(
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames) {
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames) {
|
||||
for (const WSTRING& filePath : GetEnvironmentValues(environment::integrations_path, ENV_VAR_PATH_SEPARATOR))
|
||||
{
|
||||
Logger::Debug("Loading integrations from file: ", filePath);
|
||||
LoadIntegrationsFromFile(filePath, integrationMethods, enabledIntegrationNames, disabledIntegrationNames);
|
||||
LoadIntegrationsFromFile(
|
||||
filePath, integrationMethods, enabledTraceIntegrationNames, disabledTraceIntegrationNames, enabledLogIntegrationNames, disabledLogIntegrationNames);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadIntegrationsFromFile(
|
||||
const WSTRING& file_path,
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames) {
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames) {
|
||||
try
|
||||
{
|
||||
std::ifstream stream(ToString(file_path));
|
||||
|
@ -36,8 +40,10 @@ void LoadIntegrationsFromFile(
|
|||
{
|
||||
LoadIntegrationsFromStream(stream,
|
||||
integrationMethods,
|
||||
enabledIntegrationNames,
|
||||
disabledIntegrationNames);
|
||||
enabledTraceIntegrationNames,
|
||||
disabledTraceIntegrationNames,
|
||||
enabledLogIntegrationNames,
|
||||
disabledLogIntegrationNames);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -66,8 +72,10 @@ void LoadIntegrationsFromFile(
|
|||
void LoadIntegrationsFromStream(
|
||||
std::istream& stream,
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames) {
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames) {
|
||||
try
|
||||
{
|
||||
json j;
|
||||
|
@ -78,7 +86,12 @@ void LoadIntegrationsFromStream(
|
|||
|
||||
for (const auto& el : j)
|
||||
{
|
||||
IntegrationFromJson(el, integrationMethods, enabledIntegrationNames, disabledIntegrationNames);
|
||||
IntegrationFromJson(el,
|
||||
integrationMethods,
|
||||
enabledTraceIntegrationNames,
|
||||
disabledTraceIntegrationNames,
|
||||
enabledLogIntegrationNames,
|
||||
disabledLogIntegrationNames);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -114,15 +127,6 @@ namespace
|
|||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames)
|
||||
{
|
||||
// LoggingBuilder has to be always enabled.
|
||||
// Technically it is not an instrumentation but
|
||||
// it is using the same functionality.
|
||||
// See https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1310.
|
||||
if (name == WStr("LoggingBuilder"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if the integration is disabled
|
||||
for (const WSTRING& disabledName : disabledIntegrationNames)
|
||||
{
|
||||
|
@ -150,8 +154,10 @@ namespace
|
|||
|
||||
void IntegrationFromJson(const json::value_type& src,
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames)
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames)
|
||||
{
|
||||
if (!src.is_object())
|
||||
{
|
||||
|
@ -166,8 +172,29 @@ namespace
|
|||
return;
|
||||
}
|
||||
|
||||
if (!InstrumentationEnabled(name, enabledIntegrationNames, disabledIntegrationNames))
|
||||
const WSTRING type = ToWSTRING(src.value("type", ""));
|
||||
if (name.empty())
|
||||
{
|
||||
Logger::Warn("Integration type is missing for integration: ", src.dump());
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == WStr("Trace"))
|
||||
{
|
||||
if (!InstrumentationEnabled(name, enabledTraceIntegrationNames, disabledTraceIntegrationNames))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (type == WStr("Log"))
|
||||
{
|
||||
if (!InstrumentationEnabled(name, enabledLogIntegrationNames, disabledLogIntegrationNames)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Warn("Unsupported type for integration: ", src.dump());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,29 +19,37 @@ using json = nlohmann::json;
|
|||
// in the OTEL_DOTNET_AUTO_INTEGRATIONS_FILE environment variable
|
||||
void LoadIntegrationsFromEnvironment(
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||
|
||||
// LoadIntegrationsFromFile loads the integrations from a file
|
||||
void LoadIntegrationsFromFile(
|
||||
const WSTRING& file_path,
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||
|
||||
// LoadIntegrationsFromFile loads the integrations from a stream
|
||||
void LoadIntegrationsFromStream(
|
||||
std::istream& stream,
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||
|
||||
namespace
|
||||
{
|
||||
void IntegrationFromJson(const json::value_type& src,
|
||||
std::vector<IntegrationMethod>& integrationMethods,
|
||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
||||
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||
|
||||
void MethodReplacementFromJson(const json::value_type& src, const WSTRING& integrationName,
|
||||
std::vector<IntegrationMethod>& integrationMethods);
|
||||
|
|
|
@ -174,6 +174,16 @@ internal static class ConfigurationKeys
|
|||
/// should be included on generated <see cref="LogRecord"/>s.
|
||||
/// </summary>
|
||||
public const string IncludeFormattedMessage = "OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE";
|
||||
|
||||
/// <summary>
|
||||
/// Configuration key for comma separated list of enabled logs instrumentations.
|
||||
/// </summary>
|
||||
public const string Instrumentations = "OTEL_DOTNET_AUTO_LOGS_ENABLED_INSTRUMENTATIONS";
|
||||
|
||||
/// <summary>
|
||||
/// Configuration key for comma separated list of disabled logs instrumentations.
|
||||
/// </summary>
|
||||
public const string DisabledInstrumentations = "OTEL_DOTNET_AUTO_LOGS_DISABLED_INSTRUMENTATIONS";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// <copyright file="LogInstrumentation.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.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing supported meter instrumentations.
|
||||
/// </summary>
|
||||
internal enum LogInstrumentation
|
||||
{
|
||||
/// <summary>
|
||||
/// ILogger instrumentation.
|
||||
/// </summary>
|
||||
ILogger
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTelemetry.AutoInstrumentation.Util;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
|
||||
|
@ -35,6 +36,11 @@ internal class LogSettings : Settings
|
|||
LogExporter = ParseLogExporter(source);
|
||||
ConsoleExporterEnabled = source.GetBool(ConfigurationKeys.Logs.ConsoleExporterEnabled) ?? false;
|
||||
IncludeFormattedMessage = source.GetBool(ConfigurationKeys.Logs.IncludeFormattedMessage) ?? false;
|
||||
|
||||
EnabledInstrumentations = source.ParseEnabledEnumList<LogInstrumentation>(
|
||||
enabledConfiguration: ConfigurationKeys.Logs.Instrumentations,
|
||||
disabledConfiguration: ConfigurationKeys.Logs.DisabledInstrumentations,
|
||||
error: "The \"{0}\" is not recognized as supported logs instrumentation and cannot be enabled or disabled.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -52,6 +58,11 @@ internal class LogSettings : Settings
|
|||
/// </summary>
|
||||
public bool ConsoleExporterEnabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of enabled instrumentations.
|
||||
/// </summary>
|
||||
public IList<LogInstrumentation> EnabledInstrumentations { get; }
|
||||
|
||||
internal static LogSettings FromDefaultSources()
|
||||
{
|
||||
var configurationSource = new CompositeConfigurationSource
|
||||
|
|
|
@ -24,5 +24,6 @@ internal class GraphQLExecuteAsyncAttribute : InstrumentMethodAttribute
|
|||
MethodName = "ExecuteAsync";
|
||||
ReturnTypeName = "System.Threading.Tasks.Task`1[GraphQL.ExecutionResult]";
|
||||
ParameterTypeNames = new[] { "GraphQL.Execution.ExecutionContext" };
|
||||
Type = InstrumentationType.Trace;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,4 +101,9 @@ internal class InstrumentMethodAttribute : Attribute
|
|||
/// Gets or sets the integration name. Allows to group several integration with a single integration name.
|
||||
/// </summary>
|
||||
public string IntegrationName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the integration type.
|
||||
/// </summary>
|
||||
public InstrumentationType Type { get; set; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// <copyright file="InstrumentationType.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.Instrumentations;
|
||||
|
||||
internal enum InstrumentationType
|
||||
{
|
||||
Trace,
|
||||
// Metric,
|
||||
Log
|
||||
}
|
|
@ -30,7 +30,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Logger;
|
|||
ParameterTypeNames = new[] { "Microsoft.Extensions.DependencyInjection.IServiceCollection" },
|
||||
MinimumVersion = "3.1.0",
|
||||
MaximumVersion = "6.*.*",
|
||||
IntegrationName = "LoggingBuilder")]
|
||||
IntegrationName = "ILogger",
|
||||
Type = InstrumentationType.Log)]
|
||||
public class LoggingBuilderIntegration
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -36,7 +36,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MongoDB;
|
|||
ParameterTypeNames = new[] { "MongoDB.Driver.MongoClientSettings" },
|
||||
MinimumVersion = "2.13.3",
|
||||
MaximumVersion = "2.65535.65535",
|
||||
IntegrationName = "MongoDB")]
|
||||
IntegrationName = "MongoDB",
|
||||
Type = InstrumentationType.Trace)]
|
||||
public class MongoClientIntegration
|
||||
{
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { ClrNames.Object, StackExchangeRedisConstants.TextWriterTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
[InstrumentMethod(// releases 2.1.50 - 2.5.43
|
||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||
|
@ -39,7 +40,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
[InstrumentMethod(// releases 2.5.61 - 2.6.48
|
||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||
|
@ -48,7 +50,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
[InstrumentMethod(// releases 2.6.66+
|
||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||
|
@ -57,7 +60,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName, StackExchangeRedisConstants.EndPointCollectionTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
public class StackExchangeRedisIntegration
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { ClrNames.Object, StackExchangeRedisConstants.TextWriterTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
[InstrumentMethod(// releases 2.1.50 - 2.5.43
|
||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||
|
@ -39,7 +40,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
[InstrumentMethod(// releases 2.5.61+
|
||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||
|
@ -48,7 +50,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
|||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName },
|
||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
||||
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||
Type = InstrumentationType.Trace)]
|
||||
public class StackExchangeRedisIntegrationAsync
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Validations;
|
|||
ParameterTypeNames = new string[0],
|
||||
MinimumVersion = "1.0.0",
|
||||
MaximumVersion = "1.65535.65535",
|
||||
IntegrationName = "StrongNamedValidation")]
|
||||
IntegrationName = "StrongNamedValidation",
|
||||
Type = InstrumentationType.Trace)]
|
||||
public class StrongNamedValidation
|
||||
{
|
||||
private static readonly ActivitySource ValidationActivitySource = new ActivitySource("TestApplication.StrongNamedValidation");
|
||||
|
|
|
@ -139,6 +139,15 @@ public class MockLogsCollector : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public void AssertEmpty(TimeSpan? timeout = null)
|
||||
{
|
||||
timeout ??= DefaultWaitTimeout;
|
||||
if (_logs.TryTake(out var logRecord, timeout.Value))
|
||||
{
|
||||
Assert.Fail($"Expected nothing, but got: {logRecord}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void FailExpectations(
|
||||
List<Expectation> missingExpectations,
|
||||
List<global::OpenTelemetry.Proto.Logs.V1.LogRecord> expectationsMet,
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
|
@ -272,6 +271,18 @@ public class SmokeTests : TestHelper
|
|||
|
||||
collector.AssertExpectations();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", "EndToEnd")]
|
||||
public async Task LogsNoneInstrumentations()
|
||||
{
|
||||
using var collector = await MockLogsCollector.Start(Output);
|
||||
|
||||
SetEnvironmentVariable("OTEL_DOTNET_AUTO_LOGS_ENABLED_INSTRUMENTATIONS", "none");
|
||||
RunTestApplication(logsAgentPort: collector.Port, enableClrProfiler: true);
|
||||
|
||||
collector.AssertEmpty(5.Seconds());
|
||||
}
|
||||
#endif
|
||||
|
||||
private async Task VerifyTestApplicationInstrumented(bool enableStartupHook = true, bool enableClrProfiler = true)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[
|
||||
{
|
||||
"name": "StrongNamedValidation",
|
||||
"type": "Trace",
|
||||
"method_replacements": [
|
||||
{
|
||||
"caller": {},
|
||||
|
|
|
@ -16,7 +16,7 @@ using namespace trace;
|
|||
TEST(IntegrationLoaderTest, HandlesMissingFile)
|
||||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
LoadIntegrationsFromFile(L"missing-file", integrations, {}, {});
|
||||
LoadIntegrationsFromFile(L"missing-file", integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(0, integrations.size());
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNoName)
|
|||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str("[{}]");
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
// 0 because name is required
|
||||
EXPECT_EQ(0, integrations.size());
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationBadJson)
|
|||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str("[");
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(0, integrations.size());
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNotAnObject)
|
|||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str("[1,2,3]");
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(0, integrations.size());
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNotAnArray)
|
|||
std::stringstream str(R"TEXT(
|
||||
{"name": "test-integration"}
|
||||
)TEXT");
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(0, integrations.size());
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMethodReplacements)
|
|||
std::stringstream str(R"TEXT(
|
||||
[{
|
||||
"name": "test-integration",
|
||||
"type": "Trace",
|
||||
"method_replacements": [{
|
||||
"caller": { },
|
||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 0, "minimum_minor": 1, "maximum_major": 10, "maximum_minor": 0 },
|
||||
|
@ -69,7 +70,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMethodReplacements)
|
|||
}]
|
||||
)TEXT");
|
||||
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(1, integrations.size());
|
||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||
}
|
||||
|
@ -80,6 +81,7 @@ TEST(IntegrationLoaderTest, DoesNotCrashWithOutOfRangeVersion)
|
|||
std::stringstream str(R"TEXT(
|
||||
[{
|
||||
"name": "test-integration",
|
||||
"type": "Trace",
|
||||
"method_replacements": [{
|
||||
"caller": { },
|
||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 0, "minimum_minor": 1, "maximum_major": 75555, "maximum_minor": 0 },
|
||||
|
@ -88,7 +90,7 @@ TEST(IntegrationLoaderTest, DoesNotCrashWithOutOfRangeVersion)
|
|||
}]
|
||||
)TEXT");
|
||||
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(1, integrations.size());
|
||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||
|
||||
|
@ -111,6 +113,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMissingCaller)
|
|||
std::stringstream str(R"TEXT(
|
||||
[{
|
||||
"name": "test-integration",
|
||||
"type": "Trace",
|
||||
"method_replacements": [{
|
||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 1, "minimum_minor": 2, "maximum_major": 10, "maximum_minor": 99 },
|
||||
"wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "signature": [0, 1, 1, 28], "action": "CallTargetModification" }
|
||||
|
@ -118,7 +121,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMissingCaller)
|
|||
}]
|
||||
)TEXT");
|
||||
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(1, integrations.size());
|
||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||
|
||||
|
@ -148,6 +151,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithInvalidTarget)
|
|||
std::stringstream str(R"TEXT(
|
||||
[{
|
||||
"name": "test-integration",
|
||||
"type": "Trace",
|
||||
"method_replacements": [{
|
||||
"target": 1234,
|
||||
"wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "action": "CallTargetModification" }
|
||||
|
@ -155,7 +159,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithInvalidTarget)
|
|||
}]
|
||||
)TEXT");
|
||||
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
EXPECT_EQ(1, integrations.size());
|
||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||
|
||||
|
@ -172,12 +176,12 @@ TEST(IntegrationLoaderTest, LoadsFromEnvironment)
|
|||
std::ofstream f;
|
||||
f.open(temp_name1);
|
||||
f << R"TEXT(
|
||||
[{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }]
|
||||
[{ "name": "test-integration-1", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }]
|
||||
)TEXT";
|
||||
f.close();
|
||||
f.open(temp_name2);
|
||||
f << R"TEXT(
|
||||
[{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }]
|
||||
[{ "name": "test-integration-2", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }]
|
||||
)TEXT";
|
||||
f.close();
|
||||
|
||||
|
@ -188,7 +192,7 @@ TEST(IntegrationLoaderTest, LoadsFromEnvironment)
|
|||
const std::vector<std::wstring> expected_names = {L"test-integration-1", L"test-integration-2"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
LoadIntegrationsFromEnvironment(integrations, {}, {});
|
||||
LoadIntegrationsFromEnvironment(integrations, {}, {}, {}, {});
|
||||
for (auto& integration : integrations)
|
||||
{
|
||||
actual_names.push_back(integration.integration_name);
|
||||
|
@ -205,6 +209,7 @@ TEST(IntegrationLoaderTest, DeserializesSignatureTypeArray)
|
|||
std::stringstream str(R"TEXT(
|
||||
[{
|
||||
"name": "test-integration",
|
||||
"type": "Trace",
|
||||
"method_replacements": [{
|
||||
"caller": { },
|
||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "signature_types": ["System.Void", "_", "FakeClient.Pipeline'1<T>"] },
|
||||
|
@ -213,25 +218,25 @@ TEST(IntegrationLoaderTest, DeserializesSignatureTypeArray)
|
|||
}]
|
||||
)TEXT");
|
||||
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||
const auto target = integrations[0].replacement.target_method;
|
||||
EXPECT_STREQ(L"System.Void", target.signature_types[0].c_str());
|
||||
EXPECT_STREQ(L"_", target.signature_types[1].c_str());
|
||||
EXPECT_STREQ(L"FakeClient.Pipeline'1<T>", target.signature_types[2].c_str());
|
||||
}
|
||||
|
||||
TEST(IntegrationLoaderTest, SupportsEnabledIntegrations) {
|
||||
TEST(IntegrationLoaderTest, SupportsEnabledTraceIntegrations) {
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str(R"TEXT(
|
||||
[
|
||||
{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
{ "name": "test-trace-integration-1", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-trace-integration-2", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-integration-2"};
|
||||
const std::vector<std::wstring> expected_names = {L"test-trace-integration-2"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
LoadIntegrationsFromStream(str, integrations, {L"test-integration-2"}, {});
|
||||
LoadIntegrationsFromStream(str, integrations, {L"test-trace-integration-2"}, {}, {}, {});
|
||||
for (auto& integration : integrations)
|
||||
{
|
||||
actual_names.push_back(integration.integration_name);
|
||||
|
@ -239,42 +244,91 @@ TEST(IntegrationLoaderTest, SupportsEnabledIntegrations) {
|
|||
EXPECT_EQ(expected_names, actual_names);
|
||||
}
|
||||
|
||||
TEST(IntegrationLoaderTest, SupportsDisabledIntegrations) {
|
||||
TEST(IntegrationLoaderTest, SupportsEnabledLogIntegrations)
|
||||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str(R"TEXT(
|
||||
[
|
||||
{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-integration-1"};
|
||||
[
|
||||
{ "name": "test-log-integration-1", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-log-integration-2", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-log-integration-2"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {L"test-integration-2"});
|
||||
for (auto& integration : integrations) {
|
||||
actual_names.push_back(integration.integration_name);
|
||||
}
|
||||
EXPECT_EQ(expected_names, actual_names);
|
||||
}
|
||||
|
||||
TEST(IntegrationLoaderTest, SupportsEnabledAndDisabledIntegrations) {
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str(R"TEXT(
|
||||
[
|
||||
{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-integration-3", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-integration-1"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
LoadIntegrationsFromStream(str, integrations,
|
||||
{L"test-integration-1", L"test-integration-2"},
|
||||
{L"test-integration-2", L"test-integration-3"});
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {L"test-log-integration-2"}, {});
|
||||
for (auto& integration : integrations)
|
||||
{
|
||||
actual_names.push_back(integration.integration_name);
|
||||
actual_names.push_back(integration.integration_name);
|
||||
}
|
||||
EXPECT_EQ(expected_names, actual_names);
|
||||
}
|
||||
|
||||
TEST(IntegrationLoaderTest, SupportsDisabledTraceIntegrations)
|
||||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str(R"TEXT(
|
||||
[
|
||||
{ "name": "test-trace-integration-1", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-trace-integration-2", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-trace-integration-1"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {L"test-trace-integration-2"}, {}, {});
|
||||
for (auto& integration : integrations)
|
||||
{
|
||||
actual_names.push_back(integration.integration_name);
|
||||
}
|
||||
EXPECT_EQ(expected_names, actual_names);
|
||||
}
|
||||
|
||||
TEST(IntegrationLoaderTest, SupportsDisabledLogIntegrations)
|
||||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str(R"TEXT(
|
||||
[
|
||||
{ "name": "test-log-integration-1", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-log-integration-2", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-log-integration-1"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {L"test-log-integration-2"});
|
||||
for (auto& integration : integrations)
|
||||
{
|
||||
actual_names.push_back(integration.integration_name);
|
||||
}
|
||||
EXPECT_EQ(expected_names, actual_names);
|
||||
}
|
||||
|
||||
TEST(IntegrationLoaderTest, SupportsEnabledAndDisabledIntegrations)
|
||||
{
|
||||
std::vector<IntegrationMethod> integrations;
|
||||
std::stringstream str(R"TEXT(
|
||||
[
|
||||
{ "name": "test-trace-integration-1", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-trace-integration-2", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-trace-integration-3", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-log-integration-1", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-log-integration-2", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||
{ "name": "test-log-integration-3", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||
]
|
||||
)TEXT");
|
||||
|
||||
const std::vector<std::wstring> expected_names = {L"test-trace-integration-1", L"test-log-integration-1"};
|
||||
std::vector<std::wstring> actual_names;
|
||||
LoadIntegrationsFromStream(str, integrations,
|
||||
{L"test-trace-integration-1", L"test-trace-integration-2"},
|
||||
{L"test-trace-integration-2", L"test-trace-integration-3"},
|
||||
{L"test-log-integration-1", L"test-log-integration-2"},
|
||||
{L"test-log-integration-2", L"test-log-integration-3"});
|
||||
|
||||
for (auto& integration : integrations)
|
||||
{
|
||||
actual_names.push_back(integration.integration_name);
|
||||
}
|
||||
EXPECT_EQ(expected_names, actual_names);
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ public class SettingsTests : IDisposable
|
|||
settings.LogExporter.Should().Be(LogExporter.Otlp);
|
||||
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
||||
settings.ConsoleExporterEnabled.Should().BeFalse();
|
||||
settings.EnabledInstrumentations.Should().NotBeEmpty();
|
||||
settings.Plugins.Should().BeEmpty();
|
||||
settings.IncludeFormattedMessage.Should().BeFalse();
|
||||
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
||||
|
@ -231,6 +232,27 @@ public class SettingsTests : IDisposable
|
|||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<MetricInstrumentation> { MetricInstrumentation.NetRuntime });
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(nameof(LogInstrumentation.ILogger), LogInstrumentation.ILogger)]
|
||||
internal void LogSettings_Instrumentations_SupportedValues(string logInstrumentation, LogInstrumentation expectedLogInstrumentation)
|
||||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, logInstrumentation);
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<LogInstrumentation> { expectedLogInstrumentation });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
internal void LogSettings_DisabledInstrumentations()
|
||||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.DisabledInstrumentations, nameof(LogInstrumentation.ILogger));
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("true", true)]
|
||||
[InlineData("false", false)]
|
||||
|
@ -297,6 +319,8 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.Exporter, null);
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.IncludeFormattedMessage, null);
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.Instrumentations, null);
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.DisabledInstrumentations, null);
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Exporter, null);
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, null);
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.DisabledInstrumentations, null);
|
||||
|
|
|
@ -22,6 +22,9 @@ internal class Integration
|
|||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("method_replacements")]
|
||||
public IList<MethodReplacement> MethodReplacements { get; set; }
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ foreach (var typeInfo in autoInstrumentationLib.GetTypes())
|
|||
new Integration
|
||||
{
|
||||
Name = integration.IntegrationName,
|
||||
Type = integration.IntegartionType,
|
||||
MethodReplacements = new List<MethodReplacement> { integration.MethodReplacement }
|
||||
});
|
||||
}
|
||||
|
@ -88,9 +89,10 @@ bool InheritsFrom(Type type, string baseType)
|
|||
}
|
||||
}
|
||||
|
||||
(string IntegrationName, MethodReplacement MethodReplacement) ConvertToIntegration(string wrapperTypeName, Attribute attribute)
|
||||
(string IntegartionType, string IntegrationName, MethodReplacement MethodReplacement) ConvertToIntegration(string wrapperTypeName, Attribute attribute)
|
||||
{
|
||||
var integrationName = GetPropertyValue<string>("IntegrationName", attribute);
|
||||
var integrationType = GetPropertyValue<object>("Type", attribute).ToString();
|
||||
|
||||
var methodReplacement = new MethodReplacement
|
||||
{
|
||||
|
@ -133,7 +135,7 @@ bool InheritsFrom(Type type, string baseType)
|
|||
methodReplacement.Target.MaximumPath = int.Parse(maxVersion[2]);
|
||||
}
|
||||
|
||||
return (integrationName, methodReplacement);
|
||||
return (integrationType, integrationName, methodReplacement);
|
||||
}
|
||||
|
||||
T GetPropertyValue<T>(string propertyName, Attribute attribute)
|
||||
|
|
Loading…
Reference in New Issue