100 lines
3.4 KiB
C#
100 lines
3.4 KiB
C#
using System;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Json;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Serilog.Core;
|
|
using Serilog.Events;
|
|
|
|
namespace TaxBaik.Web.Logging;
|
|
|
|
public class TelegramSink : ILogEventSink
|
|
{
|
|
private readonly string _botToken;
|
|
private readonly string _chatId;
|
|
private readonly HttpClient _httpClient;
|
|
|
|
public TelegramSink(string botToken, string chatId)
|
|
{
|
|
_botToken = botToken;
|
|
_chatId = chatId;
|
|
_httpClient = new HttpClient();
|
|
}
|
|
|
|
public void Emit(LogEvent logEvent)
|
|
{
|
|
if (logEvent.Level < LogEventLevel.Error)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Filter out harmless client disconnect and task cancellation exceptions
|
|
if (logEvent.Exception != null)
|
|
{
|
|
var exTypeName = logEvent.Exception.GetType().FullName ?? "";
|
|
var exMessage = logEvent.Exception.Message ?? "";
|
|
if (exTypeName.Contains("JSDisconnectedException") ||
|
|
exTypeName.Contains("TaskCanceledException") ||
|
|
exMessage.Contains("JavaScript interop calls cannot be issued") ||
|
|
exMessage.Contains("circuit has disconnected"))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Emit is a synchronous method, so we dispatch the network call asynchronously
|
|
Task.Run(async () =>
|
|
{
|
|
try
|
|
{
|
|
var timestamp = logEvent.Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff zzz");
|
|
var level = logEvent.Level.ToString().ToUpper();
|
|
var message = logEvent.RenderMessage();
|
|
var exceptionDetails = logEvent.Exception?.ToString();
|
|
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine($"<b>🚨 [{level}] 에러 발생</b>");
|
|
sb.AppendLine($"<b>시간:</b> {timestamp}");
|
|
sb.AppendLine($"<b>메시지:</b> {EscapeHtml(message)}");
|
|
|
|
if (!string.IsNullOrEmpty(exceptionDetails))
|
|
{
|
|
var escapedException = EscapeHtml(exceptionDetails);
|
|
if (escapedException.Length > 3000)
|
|
{
|
|
escapedException = escapedException.Substring(0, 3000) + "\n[이하 생략]";
|
|
}
|
|
sb.AppendLine($"<b>Exception 상세:</b>\n<pre>{escapedException}</pre>");
|
|
}
|
|
|
|
var url = $"https://api.telegram.org/bot{_botToken}/sendMessage";
|
|
var payload = new
|
|
{
|
|
chat_id = _chatId,
|
|
text = sb.ToString(),
|
|
parse_mode = "HTML"
|
|
};
|
|
|
|
var response = await _httpClient.PostAsJsonAsync(url, payload);
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
var errorResponse = await response.Content.ReadAsStringAsync();
|
|
Console.WriteLine($"[TelegramSink] Failed to send log to Telegram: {response.StatusCode} - {errorResponse}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[TelegramSink] Error in TelegramSink: {ex.Message}");
|
|
}
|
|
});
|
|
}
|
|
|
|
private static string EscapeHtml(string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text)) return text;
|
|
return text.Replace("&", "&")
|
|
.Replace("<", "<")
|
|
.Replace(">", ">");
|
|
}
|
|
}
|