Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenTracing doesn't send logs with Serilog

I'm trying to use OpenTracing.Contrib.NetCore with Serilog. I need to send to Jaeger my custom logs. Now, it works only when I use default logger factory Microsoft.Extensions.Logging.ILoggerFactory

My Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddSingleton<ITracer>(sp =>
    {
        var loggerFactory = sp.GetRequiredService<ILoggerFactory>();
        string serviceName = sp.GetRequiredService<IHostingEnvironment>().ApplicationName;

        var samplerConfiguration = new Configuration.SamplerConfiguration(loggerFactory)
            .WithType(ConstSampler.Type)
            .WithParam(1);

        var senderConfiguration = new Configuration.SenderConfiguration(loggerFactory)
            .WithAgentHost("localhost")
            .WithAgentPort(6831);

        var reporterConfiguration = new Configuration.ReporterConfiguration(loggerFactory)
            .WithLogSpans(true)
            .WithSender(senderConfiguration);

        var tracer = (Tracer)new Configuration(serviceName, loggerFactory)
            .WithSampler(samplerConfiguration)
            .WithReporter(reporterConfiguration)
            .GetTracer();

        //GlobalTracer.Register(tracer);
        return tracer;
    });
    services.AddOpenTracing();
}

and somewhere in controller:

[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    private readonly ILogger<ValuesController> _logger;

    public ValuesController(ILogger<ValuesController> logger)
    {
        _logger = logger;
    }

    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        _logger.LogWarning("Get values by id: {valueId}", id);
        return "value";
    }
}

in a result I will able to see that log in Jaeger UI enter image description here

But when I use Serilog, there are no any custom logs. I've added UseSerilog() to WebHostBuilder, and all custom logs I can see in console but not in Jaeger. There is open issue in github. Could you please suggest how I can use Serilog with OpenTracing?

like image 975
Mr.Potkin Avatar asked May 15 '19 20:05

Mr.Potkin


People also ask

How do you use Serilog logging?

Create a Console Application project in Visual Studio. Install Serilog and its dependencies. Create and configure the Serilog global logger. Integrate the logger into the C# Console Application.

Does Serilog support .NET core?

Serilog is a third-party, open-source library that integrates nicely with ASP.NET Core and allows developers to easily log-structured event data to the console, to files, and various kinds of log targets.

Where does Serilog write to by default?

By default, serilog will only log to the console.

What is structured logging in Serilog?

Structured logging is a modern approach where logging events are treated as structured data rather than text, for example: { “payload”: { “order”: { “id”: 10 }, “message”: “OrderId: 10 placed successfully” }


1 Answers

This is a limitation in the Serilog logger factory implementation; in particular, Serilog currently ignores added providers and assumes that Serilog Sinks will replace them instead.

So, the solutions is implementaion a simple WriteTo.OpenTracing() method to connect Serilog directly to OpenTracing

public class OpenTracingSink : ILogEventSink
{
    private readonly ITracer _tracer;
    private readonly IFormatProvider _formatProvider;

    public OpenTracingSink(ITracer tracer, IFormatProvider formatProvider)
    {
        _tracer = tracer;
        _formatProvider = formatProvider;
    }

    public void Emit(LogEvent logEvent)
    {
        ISpan span = _tracer.ActiveSpan;

        if (span == null)
        {
            // Creating a new span for a log message seems brutal so we ignore messages if we can't attach it to an active span.
            return;
        }

        var fields = new Dictionary<string, object>
        {
            { "component", logEvent.Properties["SourceContext"] },
            { "level", logEvent.Level.ToString() }
        };

        fields[LogFields.Event] = "log";

        try
        {
            fields[LogFields.Message] = logEvent.RenderMessage(_formatProvider);
            fields["message.template"] = logEvent.MessageTemplate.Text;

            if (logEvent.Exception != null)
            {
                fields[LogFields.ErrorKind] = logEvent.Exception.GetType().FullName;
                fields[LogFields.ErrorObject] = logEvent.Exception;
            }

            if (logEvent.Properties != null)
            {
                foreach (var property in logEvent.Properties)
                {
                    fields[property.Key] = property.Value;
                }
            }
        }
        catch (Exception logException)
        {
            fields["mbv.common.logging.error"] = logException.ToString();
        }

        span.Log(fields);
    }
}

public static class OpenTracingSinkExtensions
{
    public static LoggerConfiguration OpenTracing(
              this LoggerSinkConfiguration loggerConfiguration,
              IFormatProvider formatProvider = null)
    {
        return loggerConfiguration.Sink(new OpenTracingSink(GlobalTracer.Instance, formatProvider));
    }
}
like image 87
Mr.Potkin Avatar answered Oct 11 '22 20:10

Mr.Potkin