Skip to content

Commit

Permalink
Merge pull request #9 from ernado-x/8-logging-configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ernado-x authored Apr 25, 2022
2 parents c435c4c + e1481ba commit c776237
Show file tree
Hide file tree
Showing 17 changed files with 312 additions and 81 deletions.
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ You can configure Telegram logging provider by code or by config file:

### Code
```csharp
var options = new TelegramLoggerOptions
var options = new TelegramLoggerOptions(LogLevel.Information)
{
AccessToken = "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
ChatId = "-0000000000000",
LogLevel = LogLevel.Information,
Source = "Human Readable Project Name"
};

Expand All @@ -54,7 +53,10 @@ builder
"Microsoft.Hosting.Lifetime": "Information"
},
"Telegram": {
"LogLevel": "Warning",
"LogLevel": {
"Default": "Error",
"WebApp.Controllers": "Warning"
},
"AccessToken": "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
"ChatId": "1234567890",
"Source": "Human Readable Project Name"
Expand All @@ -78,3 +80,25 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
})
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
````
### Use custom log writer
Now developers can use their own implementation for writing data to Telegram. Custom writer should implement _ILogWriter_ interface:
``` cs
var customLogWriter = new CustomLogWriter();
logBuilder.AddTelegram(options, customLogWriter);
```

### Use custom message formatter
For implement custom message formatting _ITelegramMessageFormatter_ can be used now.

``` cs
private ITelegramMessageFormatter CreateFormatter(string name)
{
return new CustomTelegramMessageFormatter(name);
}

logBuilder.AddTelegram(options, CreateFormatter);
```

For using custom message formatter delegate Func<string, ITelegramMessageFormatter> should be passed to extensions method AddTelegram. Delegate should be used because formatter needs to know which category is used for rendering the message.
3 changes: 1 addition & 2 deletions examples/ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ public class AnotherExampleClass

static void Main(string[] args)
{
var options = new TelegramLoggerOptions
var options = new TelegramLoggerOptions(LogLevel.Information)
{
AccessToken = "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
ChatId = "-0000000000000",
LogLevel = LogLevel.Information,
Source = "TEST APP",
UseEmoji = true
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ public IEnumerable<WeatherForecast> Get()
var rng = new Random();
var temperatureC = rng.Next(-20, 55);

_logger.LogInformation($"Temperature: {temperatureC}");
_logger.LogTrace($"Trace Temperature: {temperatureC}");
_logger.LogDebug($"Debug Temperature: {temperatureC}");
_logger.LogInformation($"Information Temperature: {temperatureC}");
_logger.LogWarning($"Warning Temperature: {temperatureC}");
_logger.LogError($"Error Temperature: {temperatureC}");
_logger.LogCritical($"Critical Temperature: {temperatureC}");

return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Expand Down
6 changes: 4 additions & 2 deletions examples/WebApp.NextVersion/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
"Microsoft.AspNetCore": "Warning"
},
"Telegram": {
"LogLevel": "Information",
"LogLevel": {
"Default": "Error"
},
"AccessToken": "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
"ChatId": "-0000000000000",
"UseEmoji": "true",
"Source": "WebApp.NextVersion"
}
},
},
"AllowedHosts": "*"
}
7 changes: 6 additions & 1 deletion examples/WebApp/Controllers/WeatherForecastController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ public IEnumerable<WeatherForecast> Get()
var rng = new Random();
var temperatureC = rng.Next(-20, 55);

_logger.LogInformation($"Temperature: {temperatureC}");
_logger.LogTrace($"Trace Temperature: {temperatureC}");
_logger.LogDebug($"Debug Temperature: {temperatureC}");
_logger.LogInformation($"Information Temperature: {temperatureC}");
_logger.LogWarning($"Warning Temperature: {temperatureC}");
_logger.LogError($"Error Temperature: {temperatureC}");
_logger.LogCritical($"Critical Temperature: {temperatureC}");

return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Expand Down
7 changes: 5 additions & 2 deletions examples/WebApp/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
"Microsoft.Hosting.Lifetime": "Information"
},
"Telegram": {
"LogLevel": "Information",
"LogLevel": {
"Default": "Error",
"WebApp.Controllers": "Warning"
},
"AccessToken": "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
"ChatId": "-0000000000000",
"UseEmoji": "true",
"Source": "WebApp.NextVersion"
"Source": "WebApp"
}
},
"AllowedHosts": "*"
Expand Down
13 changes: 13 additions & 0 deletions src/X.Extensions.Logging.Telegram/LogLevelChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.Extensions.Logging;

namespace X.Extensions.Logging.Telegram;

public interface ILogLevelChecker
{
bool IsEnabled(LogLevel logLevel);
}

public class DefaultLogLevelChecker : ILogLevelChecker
{
public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,34 @@
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace X.Extensions.Logging.Telegram;

internal class TelegramLoggerProcessor : IDisposable
[PublicAPI]
public interface ILogQueueProcessor : IDisposable
{
void EnqueueMessage(string message);
}

internal class LogQueueProcessor : ILogQueueProcessor
{
private const int MaxQueuedMessages = 1024;
private const int Timeout = 1500;

private readonly BlockingCollection<string> _queue = new(MaxQueuedMessages);
private readonly Thread _thread;
private readonly ITelegramWriter _writer;
private readonly ILogWriter _writer;

public TelegramLoggerProcessor(TelegramLoggerOptions options)
public LogQueueProcessor(ILogWriter logWriter)
{
_writer = new TelegramWriter(options.AccessToken, options.ChatId);
_writer = logWriter;

// Start Telegram message queue process
// Start message queue thread
_thread = new Thread(async () => { await ProcessLogQueue(); })
{
IsBackground = true,
Name = "Telegram logger queue process thread",
Name = $"{nameof(LogQueueProcessor)} thread",
};

_thread.Start();
Expand All @@ -39,6 +46,7 @@ public void EnqueueMessage(string message)
}
catch
{
// ignored
}
}

Expand Down Expand Up @@ -69,6 +77,7 @@ private async Task ProcessLogQueue()
}
catch
{
// ignored
}
}
}
Expand All @@ -83,6 +92,7 @@ public void Dispose()
}
catch
{
// ignored
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@
namespace X.Extensions.Logging.Telegram;

[PublicAPI]
public interface ITelegramWriter
public interface ILogWriter
{
Task Write(string message);
}

public class TelegramWriter : ITelegramWriter
public class TelegramLogWriter : ILogWriter
{
private readonly string _chatId;
private readonly ITelegramBotClient _client;

public TelegramWriter(string accessToken, string chatId)
public TelegramLogWriter(string accessToken, string chatId)
: this(new TelegramBotClient(accessToken), chatId)
{
}

public TelegramWriter(ITelegramBotClient client, string chatId)
public TelegramLogWriter(ITelegramBotClient client, string chatId)
{
_chatId = chatId;
_client = client;
Expand Down
27 changes: 7 additions & 20 deletions src/X.Extensions.Logging.Telegram/TelegramLogger.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,25 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;

namespace X.Extensions.Logging.Telegram;

public class TelegramLogger : ILogger
{
private readonly TelegramLoggerProcessor _queueProcessor;
private readonly string _category;
private readonly ILogLevelChecker _logLevelChecker;
private readonly ILogQueueProcessor _queueProcessor;
private readonly ITelegramMessageFormatter _formatter;

internal TelegramLogger(
string name,
TelegramLoggerOptions options,
TelegramLoggerProcessor loggerProcessor,
string category)
: this(options, loggerProcessor, category, new TelegramMessageFormatter(options, name))
{
}

internal TelegramLogger(
TelegramLoggerOptions options,
TelegramLoggerProcessor loggerProcessor,
string category,
ILogLevelChecker logLevelChecker,
ILogQueueProcessor loggerProcessor,
ITelegramMessageFormatter formatter)
{
Options = options ?? throw new ArgumentNullException(nameof(options));
_logLevelChecker = logLevelChecker;
_queueProcessor = loggerProcessor;
_category = category;
_formatter = formatter;

Options = options ?? throw new ArgumentNullException(nameof(options));
}

[PublicAPI]
Expand Down Expand Up @@ -58,9 +47,7 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
_queueProcessor.EnqueueMessage(message);
}

public bool IsEnabled(LogLevel logLevel) =>
logLevel > Options.LogLevel ||
logLevel == Options.LogLevel && (Options.Categories == null || Options.Categories.Contains(_category));
public bool IsEnabled(LogLevel logLevel) => _logLevelChecker.IsEnabled(logLevel);

public IDisposable BeginScope<TState>(TState state) => default;
}
Loading

0 comments on commit c776237

Please sign in to comment.