serilog / serilog-settings-configuration

A Serilog configuration provider that reads from Microsoft.Extensions.Configuration
Apache License 2.0
444 stars 129 forks source link

Configure ResourceAttributes via appsettings.json #398

Closed steverb38 closed 2 months ago

steverb38 commented 11 months ago

Hi,

Any suggestions on how to specifiy ResourceAttributes when configuring the sink via appsettings.json? Specifying Endpoint and Protocol in appsettings.json works fine, but I can't get the syntax for specifying the Dictionary<string, object> for ResourceAttributes:

This is my attempt in appsettings.json - the service.name attribute doesn't end up as "myapp-test", but some default value "unknown_service:...":

   "WriteTo": [
      {
        "Name": "OpenTelemetry",
        "Args": {
          "endpoint": "http://MyOtelCollectorServer:4318/v1/logs",
          "protocol": "HttpProtobuf",
          "resourceAttributes": {
            "service.name" : "myapp-test"
           }
        }
          }
    ],

Is this even possible?

Steve

nblumhardt commented 11 months ago

Thanks for raising this. I don't believe that it is, at the present time. I'll move this ticket to serilog-settings-configuration, which is where the relevant code lives.

steverb38 commented 11 months ago

@nblumhardt - thanks for the reply. Good to know this wasn't me misunderstanding something! 😄

0xced commented 11 months ago

As @nblumhardt said, it's not currently possible. I did some early investigation and it seems would be pretty easy (too easy?) to make this configuration work.

"WriteTo:OpenTelemetry": {
  "Name": "OpenTelemetry",
  "Args": {
    "configure": {
      "Endpoint": "http://MyOtelCollectorServer:4318/v1/logs",
      "Protocol": "HttpProtobuf",
      "ResourceAttributes": {
        "service.name" : "myapp-test"
      },
      "BatchingOptions": {
        "BatchSizeLimit": 500
      }
    }
  }
}

Currently, it throws System.ArgumentException

Configuration resolution for Action parameter type at the path Serilog:WriteTo:OpenTelemetry:Args:configure is not implemented.

Sneak peek / starting point for a pull request:

diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs
index 1049b85..d54a0aa 100644
--- a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs
+++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs
@@ -283,6 +283,11 @@ class ConfigurationReader : IConfigurationReader
         CallConfigurationMethods(methodCalls, FindEventEnricherConfigurationMethods(_configurationAssemblies, _resolutionContext.ReaderOptions.AllowInternalTypes, _resolutionContext.ReaderOptions.AllowInternalMethods), loggerEnrichmentConfiguration);
     }

+    void IConfigurationReader.ApplyBinding(object instance)
+    {
+        _section.Bind(instance, options => options.ErrorOnUnknownConfiguration = true);
+    }
+
     void ApplyEnrichment(LoggerConfiguration loggerConfiguration)
     {
         var enrichDirective = _section.GetSection("Enrich");
diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/IConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/IConfigurationReader.cs
index f3dd36f..82c9d2f 100644
--- a/src/Serilog.Settings.Configuration/Settings/Configuration/IConfigurationReader.cs
+++ b/src/Serilog.Settings.Configuration/Settings/Configuration/IConfigurationReader.cs
@@ -6,4 +6,5 @@ interface IConfigurationReader : ILoggerSettings
 {
     void ApplySinks(LoggerSinkConfiguration loggerSinkConfiguration);
     void ApplyEnrichment(LoggerEnrichmentConfiguration loggerEnrichmentConfiguration);
+    void ApplyBinding(object instance);
 }
diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ObjectArgumentValue.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ObjectArgumentValue.cs
index 151ce5b..41ad346 100644
--- a/src/Serilog.Settings.Configuration/Settings/Configuration/ObjectArgumentValue.cs
+++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ObjectArgumentValue.cs
@@ -39,7 +39,7 @@ class ObjectArgumentValue : IConfigurationArgumentValue
                 _ when configType == typeof(LoggerConfiguration) => new Action<LoggerConfiguration>(configReader.Configure),
                 _ when configType == typeof(LoggerSinkConfiguration) => new Action<LoggerSinkConfiguration>(configReader.ApplySinks),
                 _ when configType == typeof(LoggerEnrichmentConfiguration) => new Action<LoggerEnrichmentConfiguration>(configReader.ApplyEnrichment),
-                _ => throw new ArgumentException($"Configuration resolution for Action<{configType.Name}> parameter type at the path {_section.Path} is not implemented.")
+                _ => new Action<object>(configReader.ApplyBinding)
             };
         }

This change, as small as it looks, would require extensive test coverage.

HHobeck commented 6 months ago

I having exactly the same problem. Are they any workarounds available? I'm using version 1.2.0 of Serilog.Sinks.OpenTelemetry

Why does the OpenTelemetry implementation of Serilog not using the build-in IHostingEnvironment.ApplicationName by default for the service.name?

nblumhardt commented 3 months ago

Hi all :wave:

Version 8.0.1-dev-00583 of Serilog.Settings.Configuration has just been published to NuGet with this change, and v2.0.0 of Serilog.Sinks.OpenTelemetry accepts resourceAttributes and headers via configuration.

Is anyone following this thread in a position to kick the tyres and send some feedback? Thanks!

CC @MikkelPorse and @frank-ang

codymullins commented 2 months ago

@nblumhardt looks good locally, pushing it to prod now 👍🏻

nblumhardt commented 2 months ago

This is out in 8.0.1 RTM now :-)

steverb38 commented 2 months ago

Fantastic! Thanks for all your work on Serilog 👍