5

I have a Class Library and a test integration sample application which uses Serilog. How do I add a logger into the Class Library? I prefer Microsoft.Extensions.Logging, but I cannot find a way to do that without a dependency injection.

Sample

using System.Reactive.Disposables;
using Ardalis.GuardClauses;
using Binance.WebSocket.Client.Extensions;
using Binance.WebSocket.Client.Subscriptions;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;

namespace Binance.WebSocket.Client.Sample;

public class Program
{
    private static readonly ManualResetEvent ExitEvent = new(false);

    private static async Task Main()
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Verbose()
            .Enrich.FromLogContext()
            .WriteTo.Console(LogEventLevel.Debug, theme: SystemConsoleTheme.Colored)
            .WriteTo.File(Path.Combine("logs", "verbose.log"), rollingInterval: RollingInterval.Day)
            .CreateLogger();

        var disposable = new CompositeDisposable();
        var uri = new Uri("wss://stream.binance.com:9443");

        using var communicator = new BinanceWebSocketCommunicator(uri);

        communicator.Name = "Binance-Spot";
        communicator.ReconnectTimeout = TimeSpan.FromMinutes(10);

        communicator.ReconnectionHappened
            .Subscribe(info => Log.Information($"Reconnection happened, type: {info.Type}"))
            .DisposeWith(disposable);

        communicator.DisconnectionHappened
            .Subscribe(info => Log.Information($"Disconnection happened, type: {info.Type}"))
            .DisposeWith(disposable);

        using var client = new BinanceWebSocketClient(communicator);

        client.Streams.PongStream
            .Subscribe(x => Log.Information($"Pong received ({x.Message})"))
            .DisposeWith(disposable);

        client.Streams.AggregateTradesStream
            .Subscribe(response =>
            {
                Guard.Against.Null(response, nameof(response));
                Guard.Against.Null(response.Data, nameof(response.Data),
                    "Something went wrong and the aggregated trade object is null");

                var trade = response.Data;
                Log.Information($"Aggregated trade [{trade.Symbol}] [{trade.Side}] " +
                                $"Price: {trade.Price} Size: {trade.Quantity}");
            })
            .DisposeWith(disposable);

        client.Streams.KlineStream
            .Subscribe(response =>
            {
                Guard.Against.Null(response, nameof(response));
                Guard.Against.Null(response.Data, nameof(response.Data),
                    "Something went wrong and the kline object is null");
                Guard.Against.Null(response.Data.Data, nameof(response.Data.Data),
                    "Something went wrong and the kline data object is null");

                var kline = response.Data;
                var klineData = response.Data.Data;

                Log.Information($"Kline [{kline.Symbol}] " +
                                $"Kline start time: {klineData.StartTime} " +
                                $"Kline close time: {klineData.CloseTime} " +
                                $"Interval: {klineData.Interval} " +
                                $"First trade ID: {klineData.FirstTradeId} " +
                                $"Last trade ID: {klineData.LastTradeId} " +
                                $"Open price: {klineData.OpenPrice} " +
                                $"Close price: {klineData.ClosePrice} " +
                                $"High price: {klineData.HighPrice} " +
                                $"Low price: {klineData.LowPrice} " +
                                $"Base asset volume: {klineData.BaseAssetVolume} " +
                                $"Number of trades: {klineData.NumberTrades} " +
                                $"Is this kline closed?: {klineData.IsClosed} " +
                                $"Quote asset volume: {klineData.QuoteAssetVolume} " +
                                $"Taker buy base: {klineData.TakerBuyBaseAssetVolume} " +
                                $"Taker buy quote: {klineData.TakerBuyQuoteAssetVolume} " +
                                $"Ignore: {klineData.Ignore} ");
            })
            .DisposeWith(disposable);

        client.AddSubscription(
            new AggregateTradeSubscription("bnbusdt"),
            new KlineSubscription("btcusdt", "1h"));

        await communicator.Start().ConfigureAwait(false);

        ExitEvent.WaitOne();
 
        disposable.Dispose();

        Log.CloseAndFlush();
    }
}
nop
  • 4,711
  • 6
  • 32
  • 93
  • 1
    The code you show is not library code. I don't really see how that code relates to the problem of logging in a library. – PMF Dec 03 '21 at 11:51

1 Answers1

6

You can use the LoggerFactory like the following

using var loggerFactory = LoggerFactory.Create(builder =>
{
    builder
        .AddFilter("Microsoft", LogLevel.Warning)
        .AddFilter("System", LogLevel.Warning)
        .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
        .AddConsole()
        .AddEventLog();
});

ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");

Reference: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0#non-host-console-app

Jack Jiang
  • 522
  • 3
  • 11
  • Thank you for your answer! How do I use `Serilog` along with the `LoggerFactory` tho? – nop Dec 03 '21 at 08:46
  • You can use the extension method that's provided by the Serilog library `.AddSerilog(serilog);` after referencing https://www.nuget.org/packages/Serilog.Extensions.Logging/ – Jack Jiang Dec 03 '21 at 08:56
  • Thanks! It worked, however now I gotta think of a way to pass that to the Class Library, just like the guy here did https://github.com/JKorf/CryptoExchange.Net/blob/4e5aeb68b55e99b73bc5e17046489af764926bfe/CryptoExchange.Net/Objects/Options.cs#L24 – nop Dec 03 '21 at 09:42