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:
|
- Support ASP.NET Core OpenTelemetry Log exporter related environment variables:
|
||||||
- `OTEL_LOGS_EXPORTER`,
|
- `OTEL_LOGS_EXPORTER`,
|
||||||
- `OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED`,
|
- `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`.
|
- `OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE`.
|
||||||
- Support `OTEL_DOTNET_AUTO_GRAPHQL_SET_DOCUMENT` (default value: `false`)
|
- Support `OTEL_DOTNET_AUTO_GRAPHQL_SET_DOCUMENT` (default value: `false`)
|
||||||
environment variable which controls whether `graphql.document` attribute
|
environment variable which controls whether `graphql.document` attribute
|
||||||
|
|
|
@ -25,10 +25,12 @@ for more details.
|
||||||
| Environment variable | Description | Default value |
|
| 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_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_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_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
|
### Traces instrumentations
|
||||||
|
|
||||||
|
@ -62,8 +64,8 @@ for more details.
|
||||||
### Logs instrumentations
|
### Logs instrumentations
|
||||||
|
|
||||||
| ID | Instrumented library | Supported versions | Instrumentation type |
|
| 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] |
|
| 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
|
**[1]**: For ASP.NET Core applications, the `LoggingBuilder` instrumentation
|
||||||
can be enabled without using the .NET CLR Profiler by setting
|
can be enabled without using the .NET CLR Profiler by setting
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "GraphQL",
|
"name": "GraphQL",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [
|
"method_replacements": [
|
||||||
{
|
{
|
||||||
"caller": {},
|
"caller": {},
|
||||||
|
@ -51,7 +52,8 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "LoggingBuilder",
|
"name": "ILogger",
|
||||||
|
"type": "Log",
|
||||||
"method_replacements": [
|
"method_replacements": [
|
||||||
{
|
{
|
||||||
"caller": {},
|
"caller": {},
|
||||||
|
@ -80,6 +82,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "MongoDB",
|
"name": "MongoDB",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [
|
"method_replacements": [
|
||||||
{
|
{
|
||||||
"caller": {},
|
"caller": {},
|
||||||
|
@ -108,6 +111,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "MySqlData",
|
"name": "MySqlData",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [
|
"method_replacements": [
|
||||||
{
|
{
|
||||||
"caller": {},
|
"caller": {},
|
||||||
|
@ -135,6 +139,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "StackExchangeRedis",
|
"name": "StackExchangeRedis",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [
|
"method_replacements": [
|
||||||
{
|
{
|
||||||
"caller": {},
|
"caller": {},
|
||||||
|
|
|
@ -28,14 +28,14 @@ namespace OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class BootstrapperHostingStartup : IHostingStartup
|
internal class BootstrapperHostingStartup : IHostingStartup
|
||||||
{
|
{
|
||||||
private readonly LogSettings settings;
|
private readonly LogSettings _settings;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BootstrapperHostingStartup"/> class.
|
/// Initializes a new instance of the <see cref="BootstrapperHostingStartup"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BootstrapperHostingStartup()
|
public BootstrapperHostingStartup()
|
||||||
{
|
{
|
||||||
settings = LogSettings.FromDefaultSources();
|
_settings = LogSettings.FromDefaultSources();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -44,6 +44,12 @@ internal class BootstrapperHostingStartup : IHostingStartup
|
||||||
/// <param name="builder">The <see cref="IWebHostBuilder"/>.</param>
|
/// <param name="builder">The <see cref="IWebHostBuilder"/>.</param>
|
||||||
public void Configure(IWebHostBuilder builder)
|
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
|
try
|
||||||
{
|
{
|
||||||
builder.ConfigureLogging(logging => logging.AddOpenTelemetryLogs());
|
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);
|
rejit_handler = new RejitHandler(this->info_, callback);
|
||||||
|
|
||||||
// load all integrations from JSON files
|
// 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());
|
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.
|
// Sets a list of integrations to enable. If not set (default), all integrations are enabled.
|
||||||
// Supports multiple values separated with comma, for example:
|
// Supports multiple values separated with comma, for example:
|
||||||
// "ElasticsearchNet,AspNetWebApi2"
|
// "ElasticsearchNet,AspNetWebApi2"
|
||||||
const WSTRING enabled_integrations =
|
const WSTRING enabled_traces_integrations =
|
||||||
WStr("OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS");
|
WStr("OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS");
|
||||||
|
|
||||||
// Sets a list of integrations to disable. Status of other integrations will remain
|
// 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.
|
// then if instrumentation is not explicitly disabled OTEL_DOTNET_AUTO_TRACES_ENABLED_INSTRUMENTATIONS is checked.
|
||||||
// Supports multiple values separated with comma, for example:
|
// Supports multiple values separated with comma, for example:
|
||||||
// "ElasticsearchNet,AspNetWebApi2"
|
// "ElasticsearchNet,AspNetWebApi2"
|
||||||
const WSTRING disabled_integrations =
|
const WSTRING disabled_traces_integrations =
|
||||||
WStr("OTEL_DOTNET_AUTO_TRACES_DISABLED_INSTRUMENTATIONS");
|
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.
|
// Sets the directory for the profiler's log file.
|
||||||
// If not set, default is
|
// If not set, default is
|
||||||
// "%ProgramData%"\OpenTelemetry .NET AutoInstrumentation\logs\" on Windows or
|
// "%ProgramData%"\OpenTelemetry .NET AutoInstrumentation\logs\" on Windows or
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "integration_loader.h"
|
#include "integration_loader.h"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "environment_variables.h"
|
#include "environment_variables.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
@ -14,20 +13,25 @@ using json = nlohmann::json;
|
||||||
|
|
||||||
void LoadIntegrationsFromEnvironment(
|
void LoadIntegrationsFromEnvironment(
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames) {
|
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))
|
for (const WSTRING& filePath : GetEnvironmentValues(environment::integrations_path, ENV_VAR_PATH_SEPARATOR))
|
||||||
{
|
{
|
||||||
Logger::Debug("Loading integrations from file: ", filePath);
|
Logger::Debug("Loading integrations from file: ", filePath);
|
||||||
LoadIntegrationsFromFile(filePath, integrationMethods, enabledIntegrationNames, disabledIntegrationNames);
|
LoadIntegrationsFromFile(
|
||||||
|
filePath, integrationMethods, enabledTraceIntegrationNames, disabledTraceIntegrationNames, enabledLogIntegrationNames, disabledLogIntegrationNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadIntegrationsFromFile(
|
void LoadIntegrationsFromFile(
|
||||||
const WSTRING& file_path,
|
const WSTRING& file_path,
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames) {
|
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& disabledLogIntegrationNames) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::ifstream stream(ToString(file_path));
|
std::ifstream stream(ToString(file_path));
|
||||||
|
@ -36,8 +40,10 @@ void LoadIntegrationsFromFile(
|
||||||
{
|
{
|
||||||
LoadIntegrationsFromStream(stream,
|
LoadIntegrationsFromStream(stream,
|
||||||
integrationMethods,
|
integrationMethods,
|
||||||
enabledIntegrationNames,
|
enabledTraceIntegrationNames,
|
||||||
disabledIntegrationNames);
|
disabledTraceIntegrationNames,
|
||||||
|
enabledLogIntegrationNames,
|
||||||
|
disabledLogIntegrationNames);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -66,8 +72,10 @@ void LoadIntegrationsFromFile(
|
||||||
void LoadIntegrationsFromStream(
|
void LoadIntegrationsFromStream(
|
||||||
std::istream& stream,
|
std::istream& stream,
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames) {
|
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& disabledLogIntegrationNames) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
|
@ -78,7 +86,12 @@ void LoadIntegrationsFromStream(
|
||||||
|
|
||||||
for (const auto& el : j)
|
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>& enabledIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames)
|
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
|
// check if the integration is disabled
|
||||||
for (const WSTRING& disabledName : disabledIntegrationNames)
|
for (const WSTRING& disabledName : disabledIntegrationNames)
|
||||||
{
|
{
|
||||||
|
@ -150,8 +154,10 @@ namespace
|
||||||
|
|
||||||
void IntegrationFromJson(const json::value_type& src,
|
void IntegrationFromJson(const json::value_type& src,
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames)
|
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& disabledLogIntegrationNames)
|
||||||
{
|
{
|
||||||
if (!src.is_object())
|
if (!src.is_object())
|
||||||
{
|
{
|
||||||
|
@ -166,8 +172,29 @@ namespace
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,29 +19,37 @@ using json = nlohmann::json;
|
||||||
// in the OTEL_DOTNET_AUTO_INTEGRATIONS_FILE environment variable
|
// in the OTEL_DOTNET_AUTO_INTEGRATIONS_FILE environment variable
|
||||||
void LoadIntegrationsFromEnvironment(
|
void LoadIntegrationsFromEnvironment(
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||||
|
|
||||||
// LoadIntegrationsFromFile loads the integrations from a file
|
// LoadIntegrationsFromFile loads the integrations from a file
|
||||||
void LoadIntegrationsFromFile(
|
void LoadIntegrationsFromFile(
|
||||||
const WSTRING& file_path,
|
const WSTRING& file_path,
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||||
|
|
||||||
// LoadIntegrationsFromFile loads the integrations from a stream
|
// LoadIntegrationsFromFile loads the integrations from a stream
|
||||||
void LoadIntegrationsFromStream(
|
void LoadIntegrationsFromStream(
|
||||||
std::istream& stream,
|
std::istream& stream,
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
const std::vector<WSTRING>& disabledTraceIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& enabledLogIntegrationNames,
|
||||||
|
const std::vector<WSTRING>& disabledLogIntegrationNames);
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void IntegrationFromJson(const json::value_type& src,
|
void IntegrationFromJson(const json::value_type& src,
|
||||||
std::vector<IntegrationMethod>& integrationMethods,
|
std::vector<IntegrationMethod>& integrationMethods,
|
||||||
const std::vector<WSTRING>& enabledIntegrationNames,
|
const std::vector<WSTRING>& enabledTraceIntegrationNames,
|
||||||
const std::vector<WSTRING>& disabledIntegrationNames);
|
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,
|
void MethodReplacementFromJson(const json::value_type& src, const WSTRING& integrationName,
|
||||||
std::vector<IntegrationMethod>& integrationMethods);
|
std::vector<IntegrationMethod>& integrationMethods);
|
||||||
|
|
|
@ -174,6 +174,16 @@ internal static class ConfigurationKeys
|
||||||
/// should be included on generated <see cref="LogRecord"/>s.
|
/// should be included on generated <see cref="LogRecord"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string IncludeFormattedMessage = "OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE";
|
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>
|
/// <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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using OpenTelemetry.AutoInstrumentation.Util;
|
||||||
|
|
||||||
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
||||||
|
|
||||||
|
@ -35,6 +36,11 @@ internal class LogSettings : Settings
|
||||||
LogExporter = ParseLogExporter(source);
|
LogExporter = ParseLogExporter(source);
|
||||||
ConsoleExporterEnabled = source.GetBool(ConfigurationKeys.Logs.ConsoleExporterEnabled) ?? false;
|
ConsoleExporterEnabled = source.GetBool(ConfigurationKeys.Logs.ConsoleExporterEnabled) ?? false;
|
||||||
IncludeFormattedMessage = source.GetBool(ConfigurationKeys.Logs.IncludeFormattedMessage) ?? 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>
|
/// <summary>
|
||||||
|
@ -52,6 +58,11 @@ internal class LogSettings : Settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ConsoleExporterEnabled { get; }
|
public bool ConsoleExporterEnabled { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of enabled instrumentations.
|
||||||
|
/// </summary>
|
||||||
|
public IList<LogInstrumentation> EnabledInstrumentations { get; }
|
||||||
|
|
||||||
internal static LogSettings FromDefaultSources()
|
internal static LogSettings FromDefaultSources()
|
||||||
{
|
{
|
||||||
var configurationSource = new CompositeConfigurationSource
|
var configurationSource = new CompositeConfigurationSource
|
||||||
|
|
|
@ -24,5 +24,6 @@ internal class GraphQLExecuteAsyncAttribute : InstrumentMethodAttribute
|
||||||
MethodName = "ExecuteAsync";
|
MethodName = "ExecuteAsync";
|
||||||
ReturnTypeName = "System.Threading.Tasks.Task`1[GraphQL.ExecutionResult]";
|
ReturnTypeName = "System.Threading.Tasks.Task`1[GraphQL.ExecutionResult]";
|
||||||
ParameterTypeNames = new[] { "GraphQL.Execution.ExecutionContext" };
|
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.
|
/// Gets or sets the integration name. Allows to group several integration with a single integration name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string IntegrationName { get; set; }
|
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" },
|
ParameterTypeNames = new[] { "Microsoft.Extensions.DependencyInjection.IServiceCollection" },
|
||||||
MinimumVersion = "3.1.0",
|
MinimumVersion = "3.1.0",
|
||||||
MaximumVersion = "6.*.*",
|
MaximumVersion = "6.*.*",
|
||||||
IntegrationName = "LoggingBuilder")]
|
IntegrationName = "ILogger",
|
||||||
|
Type = InstrumentationType.Log)]
|
||||||
public class LoggingBuilderIntegration
|
public class LoggingBuilderIntegration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -36,7 +36,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MongoDB;
|
||||||
ParameterTypeNames = new[] { "MongoDB.Driver.MongoClientSettings" },
|
ParameterTypeNames = new[] { "MongoDB.Driver.MongoClientSettings" },
|
||||||
MinimumVersion = "2.13.3",
|
MinimumVersion = "2.13.3",
|
||||||
MaximumVersion = "2.65535.65535",
|
MaximumVersion = "2.65535.65535",
|
||||||
IntegrationName = "MongoDB")]
|
IntegrationName = "MongoDB",
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
public class MongoClientIntegration
|
public class MongoClientIntegration
|
||||||
{
|
{
|
||||||
#if NETCOREAPP3_1_OR_GREATER
|
#if NETCOREAPP3_1_OR_GREATER
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { ClrNames.Object, StackExchangeRedisConstants.TextWriterTypeName },
|
ParameterTypeNames = new[] { ClrNames.Object, StackExchangeRedisConstants.TextWriterTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
[InstrumentMethod(// releases 2.1.50 - 2.5.43
|
[InstrumentMethod(// releases 2.1.50 - 2.5.43
|
||||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||||
|
@ -39,7 +40,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName },
|
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
[InstrumentMethod(// releases 2.5.61 - 2.6.48
|
[InstrumentMethod(// releases 2.5.61 - 2.6.48
|
||||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||||
|
@ -48,7 +50,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName },
|
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
[InstrumentMethod(// releases 2.6.66+
|
[InstrumentMethod(// releases 2.6.66+
|
||||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||||
|
@ -57,7 +60,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName, StackExchangeRedisConstants.EndPointCollectionTypeName },
|
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName, StackExchangeRedisConstants.EndPointCollectionTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
public class StackExchangeRedisIntegration
|
public class StackExchangeRedisIntegration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { ClrNames.Object, StackExchangeRedisConstants.TextWriterTypeName },
|
ParameterTypeNames = new[] { ClrNames.Object, StackExchangeRedisConstants.TextWriterTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
[InstrumentMethod(// releases 2.1.50 - 2.5.43
|
[InstrumentMethod(// releases 2.1.50 - 2.5.43
|
||||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||||
|
@ -39,7 +40,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName },
|
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
[InstrumentMethod(// releases 2.5.61+
|
[InstrumentMethod(// releases 2.5.61+
|
||||||
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
AssemblyName = StackExchangeRedisConstants.AssemblyName,
|
||||||
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
TypeName = StackExchangeRedisConstants.ConnectionMultiplexerTypeName,
|
||||||
|
@ -48,7 +50,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.StackExchangeRedis;
|
||||||
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName },
|
ParameterTypeNames = new[] { StackExchangeRedisConstants.ConfigurationOptionsTypeName, StackExchangeRedisConstants.TextWriterTypeName, StackExchangeRedisConstants.NullableServerTypeTypeName },
|
||||||
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
MinimumVersion = StackExchangeRedisConstants.MinimumVersion,
|
||||||
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
MaximumVersion = StackExchangeRedisConstants.MaximumVersion,
|
||||||
IntegrationName = StackExchangeRedisConstants.IntegrationName)]
|
IntegrationName = StackExchangeRedisConstants.IntegrationName,
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
public class StackExchangeRedisIntegrationAsync
|
public class StackExchangeRedisIntegrationAsync
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -33,7 +33,8 @@ namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Validations;
|
||||||
ParameterTypeNames = new string[0],
|
ParameterTypeNames = new string[0],
|
||||||
MinimumVersion = "1.0.0",
|
MinimumVersion = "1.0.0",
|
||||||
MaximumVersion = "1.65535.65535",
|
MaximumVersion = "1.65535.65535",
|
||||||
IntegrationName = "StrongNamedValidation")]
|
IntegrationName = "StrongNamedValidation",
|
||||||
|
Type = InstrumentationType.Trace)]
|
||||||
public class StrongNamedValidation
|
public class StrongNamedValidation
|
||||||
{
|
{
|
||||||
private static readonly ActivitySource ValidationActivitySource = new ActivitySource("TestApplication.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(
|
private static void FailExpectations(
|
||||||
List<Expectation> missingExpectations,
|
List<Expectation> missingExpectations,
|
||||||
List<global::OpenTelemetry.Proto.Logs.V1.LogRecord> expectationsMet,
|
List<global::OpenTelemetry.Proto.Logs.V1.LogRecord> expectationsMet,
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -272,6 +271,18 @@ public class SmokeTests : TestHelper
|
||||||
|
|
||||||
collector.AssertExpectations();
|
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
|
#endif
|
||||||
|
|
||||||
private async Task VerifyTestApplicationInstrumented(bool enableStartupHook = true, bool enableClrProfiler = true)
|
private async Task VerifyTestApplicationInstrumented(bool enableStartupHook = true, bool enableClrProfiler = true)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "StrongNamedValidation",
|
"name": "StrongNamedValidation",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [
|
"method_replacements": [
|
||||||
{
|
{
|
||||||
"caller": {},
|
"caller": {},
|
||||||
|
|
|
@ -16,7 +16,7 @@ using namespace trace;
|
||||||
TEST(IntegrationLoaderTest, HandlesMissingFile)
|
TEST(IntegrationLoaderTest, HandlesMissingFile)
|
||||||
{
|
{
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
LoadIntegrationsFromFile(L"missing-file", integrations, {}, {});
|
LoadIntegrationsFromFile(L"missing-file", integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(0, integrations.size());
|
EXPECT_EQ(0, integrations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNoName)
|
||||||
{
|
{
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
std::stringstream str("[{}]");
|
std::stringstream str("[{}]");
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
// 0 because name is required
|
// 0 because name is required
|
||||||
EXPECT_EQ(0, integrations.size());
|
EXPECT_EQ(0, integrations.size());
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationBadJson)
|
||||||
{
|
{
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
std::stringstream str("[");
|
std::stringstream str("[");
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(0, integrations.size());
|
EXPECT_EQ(0, integrations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNotAnObject)
|
||||||
{
|
{
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
std::stringstream str("[1,2,3]");
|
std::stringstream str("[1,2,3]");
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(0, integrations.size());
|
EXPECT_EQ(0, integrations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNotAnArray)
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
{"name": "test-integration"}
|
{"name": "test-integration"}
|
||||||
)TEXT");
|
)TEXT");
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(0, integrations.size());
|
EXPECT_EQ(0, integrations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMethodReplacements)
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[{
|
[{
|
||||||
"name": "test-integration",
|
"name": "test-integration",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [{
|
"method_replacements": [{
|
||||||
"caller": { },
|
"caller": { },
|
||||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 0, "minimum_minor": 1, "maximum_major": 10, "maximum_minor": 0 },
|
"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");
|
)TEXT");
|
||||||
|
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(1, integrations.size());
|
EXPECT_EQ(1, integrations.size());
|
||||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||||
}
|
}
|
||||||
|
@ -80,6 +81,7 @@ TEST(IntegrationLoaderTest, DoesNotCrashWithOutOfRangeVersion)
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[{
|
[{
|
||||||
"name": "test-integration",
|
"name": "test-integration",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [{
|
"method_replacements": [{
|
||||||
"caller": { },
|
"caller": { },
|
||||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 0, "minimum_minor": 1, "maximum_major": 75555, "maximum_minor": 0 },
|
"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");
|
)TEXT");
|
||||||
|
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(1, integrations.size());
|
EXPECT_EQ(1, integrations.size());
|
||||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||||
|
|
||||||
|
@ -111,6 +113,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMissingCaller)
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[{
|
[{
|
||||||
"name": "test-integration",
|
"name": "test-integration",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [{
|
"method_replacements": [{
|
||||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 1, "minimum_minor": 2, "maximum_major": 10, "maximum_minor": 99 },
|
"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" }
|
"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");
|
)TEXT");
|
||||||
|
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(1, integrations.size());
|
EXPECT_EQ(1, integrations.size());
|
||||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||||
|
|
||||||
|
@ -148,6 +151,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithInvalidTarget)
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[{
|
[{
|
||||||
"name": "test-integration",
|
"name": "test-integration",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [{
|
"method_replacements": [{
|
||||||
"target": 1234,
|
"target": 1234,
|
||||||
"wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "action": "CallTargetModification" }
|
"wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "action": "CallTargetModification" }
|
||||||
|
@ -155,7 +159,7 @@ TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithInvalidTarget)
|
||||||
}]
|
}]
|
||||||
)TEXT");
|
)TEXT");
|
||||||
|
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
EXPECT_EQ(1, integrations.size());
|
EXPECT_EQ(1, integrations.size());
|
||||||
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str());
|
||||||
|
|
||||||
|
@ -172,12 +176,12 @@ TEST(IntegrationLoaderTest, LoadsFromEnvironment)
|
||||||
std::ofstream f;
|
std::ofstream f;
|
||||||
f.open(temp_name1);
|
f.open(temp_name1);
|
||||||
f << R"TEXT(
|
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";
|
)TEXT";
|
||||||
f.close();
|
f.close();
|
||||||
f.open(temp_name2);
|
f.open(temp_name2);
|
||||||
f << R"TEXT(
|
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";
|
)TEXT";
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
|
@ -188,7 +192,7 @@ TEST(IntegrationLoaderTest, LoadsFromEnvironment)
|
||||||
const std::vector<std::wstring> expected_names = {L"test-integration-1", L"test-integration-2"};
|
const std::vector<std::wstring> expected_names = {L"test-integration-1", L"test-integration-2"};
|
||||||
std::vector<std::wstring> actual_names;
|
std::vector<std::wstring> actual_names;
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
LoadIntegrationsFromEnvironment(integrations, {}, {});
|
LoadIntegrationsFromEnvironment(integrations, {}, {}, {}, {});
|
||||||
for (auto& integration : integrations)
|
for (auto& integration : integrations)
|
||||||
{
|
{
|
||||||
actual_names.push_back(integration.integration_name);
|
actual_names.push_back(integration.integration_name);
|
||||||
|
@ -205,6 +209,7 @@ TEST(IntegrationLoaderTest, DeserializesSignatureTypeArray)
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[{
|
[{
|
||||||
"name": "test-integration",
|
"name": "test-integration",
|
||||||
|
"type": "Trace",
|
||||||
"method_replacements": [{
|
"method_replacements": [{
|
||||||
"caller": { },
|
"caller": { },
|
||||||
"target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "signature_types": ["System.Void", "_", "FakeClient.Pipeline'1<T>"] },
|
"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");
|
)TEXT");
|
||||||
|
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {}, {});
|
||||||
const auto target = integrations[0].replacement.target_method;
|
const auto target = integrations[0].replacement.target_method;
|
||||||
EXPECT_STREQ(L"System.Void", target.signature_types[0].c_str());
|
EXPECT_STREQ(L"System.Void", target.signature_types[0].c_str());
|
||||||
EXPECT_STREQ(L"_", target.signature_types[1].c_str());
|
EXPECT_STREQ(L"_", target.signature_types[1].c_str());
|
||||||
EXPECT_STREQ(L"FakeClient.Pipeline'1<T>", target.signature_types[2].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::vector<IntegrationMethod> integrations;
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[
|
[
|
||||||
{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
{ "name": "test-trace-integration-1", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||||
{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
{ "name": "test-trace-integration-2", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||||
]
|
]
|
||||||
)TEXT");
|
)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;
|
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)
|
for (auto& integration : integrations)
|
||||||
{
|
{
|
||||||
actual_names.push_back(integration.integration_name);
|
actual_names.push_back(integration.integration_name);
|
||||||
|
@ -239,39 +244,88 @@ TEST(IntegrationLoaderTest, SupportsEnabledIntegrations) {
|
||||||
EXPECT_EQ(expected_names, actual_names);
|
EXPECT_EQ(expected_names, actual_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IntegrationLoaderTest, SupportsDisabledIntegrations) {
|
TEST(IntegrationLoaderTest, SupportsEnabledLogIntegrations)
|
||||||
|
{
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[
|
[
|
||||||
{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
{ "name": "test-log-integration-1", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||||
{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
{ "name": "test-log-integration-2", "type": "Log", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||||
]
|
]
|
||||||
)TEXT");
|
)TEXT");
|
||||||
|
|
||||||
const std::vector<std::wstring> expected_names = {L"test-integration-1"};
|
const std::vector<std::wstring> expected_names = {L"test-log-integration-2"};
|
||||||
std::vector<std::wstring> actual_names;
|
std::vector<std::wstring> actual_names;
|
||||||
LoadIntegrationsFromStream(str, integrations, {}, {L"test-integration-2"});
|
LoadIntegrationsFromStream(str, integrations, {}, {}, {L"test-log-integration-2"}, {});
|
||||||
for (auto& integration : integrations) {
|
for (auto& integration : integrations)
|
||||||
|
{
|
||||||
actual_names.push_back(integration.integration_name);
|
actual_names.push_back(integration.integration_name);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(expected_names, actual_names);
|
EXPECT_EQ(expected_names, actual_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IntegrationLoaderTest, SupportsEnabledAndDisabledIntegrations) {
|
TEST(IntegrationLoaderTest, SupportsDisabledTraceIntegrations)
|
||||||
|
{
|
||||||
std::vector<IntegrationMethod> integrations;
|
std::vector<IntegrationMethod> integrations;
|
||||||
std::stringstream str(R"TEXT(
|
std::stringstream str(R"TEXT(
|
||||||
[
|
[
|
||||||
{ "name": "test-integration-1", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
{ "name": "test-trace-integration-1", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
||||||
{ "name": "test-integration-2", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] },
|
{ "name": "test-trace-integration-2", "type": "Trace", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
||||||
{ "name": "test-integration-3", "method_replacements": [{ "caller": {}, "target": {}, "wrapper": {"action": "CallTargetModification"} }] }
|
|
||||||
]
|
]
|
||||||
)TEXT");
|
)TEXT");
|
||||||
|
|
||||||
const std::vector<std::wstring> expected_names = {L"test-integration-1"};
|
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;
|
std::vector<std::wstring> actual_names;
|
||||||
LoadIntegrationsFromStream(str, integrations,
|
LoadIntegrationsFromStream(str, integrations,
|
||||||
{L"test-integration-1", L"test-integration-2"},
|
{L"test-trace-integration-1", L"test-trace-integration-2"},
|
||||||
{L"test-integration-2", L"test-integration-3"});
|
{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)
|
for (auto& integration : integrations)
|
||||||
{
|
{
|
||||||
actual_names.push_back(integration.integration_name);
|
actual_names.push_back(integration.integration_name);
|
||||||
|
|
|
@ -98,6 +98,7 @@ public class SettingsTests : IDisposable
|
||||||
settings.LogExporter.Should().Be(LogExporter.Otlp);
|
settings.LogExporter.Should().Be(LogExporter.Otlp);
|
||||||
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
||||||
settings.ConsoleExporterEnabled.Should().BeFalse();
|
settings.ConsoleExporterEnabled.Should().BeFalse();
|
||||||
|
settings.EnabledInstrumentations.Should().NotBeEmpty();
|
||||||
settings.Plugins.Should().BeEmpty();
|
settings.Plugins.Should().BeEmpty();
|
||||||
settings.IncludeFormattedMessage.Should().BeFalse();
|
settings.IncludeFormattedMessage.Should().BeFalse();
|
||||||
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
||||||
|
@ -231,6 +232,27 @@ public class SettingsTests : IDisposable
|
||||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<MetricInstrumentation> { MetricInstrumentation.NetRuntime });
|
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]
|
[Theory]
|
||||||
[InlineData("true", true)]
|
[InlineData("true", true)]
|
||||||
[InlineData("false", false)]
|
[InlineData("false", false)]
|
||||||
|
@ -297,6 +319,8 @@ public class SettingsTests : IDisposable
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.Exporter, null);
|
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.Exporter, null);
|
||||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.IncludeFormattedMessage, 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.Exporter, null);
|
||||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, null);
|
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, null);
|
||||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.DisabledInstrumentations, null);
|
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.DisabledInstrumentations, null);
|
||||||
|
|
|
@ -22,6 +22,9 @@ internal class Integration
|
||||||
[JsonPropertyName("name")]
|
[JsonPropertyName("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("method_replacements")]
|
[JsonPropertyName("method_replacements")]
|
||||||
public IList<MethodReplacement> MethodReplacements { get; set; }
|
public IList<MethodReplacement> MethodReplacements { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ foreach (var typeInfo in autoInstrumentationLib.GetTypes())
|
||||||
new Integration
|
new Integration
|
||||||
{
|
{
|
||||||
Name = integration.IntegrationName,
|
Name = integration.IntegrationName,
|
||||||
|
Type = integration.IntegartionType,
|
||||||
MethodReplacements = new List<MethodReplacement> { integration.MethodReplacement }
|
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 integrationName = GetPropertyValue<string>("IntegrationName", attribute);
|
||||||
|
var integrationType = GetPropertyValue<object>("Type", attribute).ToString();
|
||||||
|
|
||||||
var methodReplacement = new MethodReplacement
|
var methodReplacement = new MethodReplacement
|
||||||
{
|
{
|
||||||
|
@ -133,7 +135,7 @@ bool InheritsFrom(Type type, string baseType)
|
||||||
methodReplacement.Target.MaximumPath = int.Parse(maxVersion[2]);
|
methodReplacement.Target.MaximumPath = int.Parse(maxVersion[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (integrationName, methodReplacement);
|
return (integrationType, integrationName, methodReplacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
T GetPropertyValue<T>(string propertyName, Attribute attribute)
|
T GetPropertyValue<T>(string propertyName, Attribute attribute)
|
||||||
|
|
Loading…
Reference in New Issue