0

我正在尝试研究如何为应用程序日志记录到 Loggly 制作异步日志记录解决方案。查看Loggly 的文档,并将其视为经典的 Producer-Consumer 问题,我想出了这个:

用于 JSON 数据序列化的消息模型:

[DataContract]
public abstract class LogMessage
{
    [DataMember]
    public DateTime TimeStamp {get;set;}

    [DataMember]
    public Guid Id {get;set;}

    [DataMember]
    public int SentAttemptCount {get;set;}
}

[DataContract]
public class ExceptionMessage : LogMessage
{
    [DataMember]
    public ExceptionMessageDetails ExceptionDetails {get;set;}
}

[DataContract]
public class ExceptionMessageDetails
{
    [DataMember]
    public string Message {get;set;}

    [DataMember]
    public string Type {get;set;}

    [DataMember]
    public string StackTrace {get;set;}

    [DataMember]
    public ExceptionMessageDetails InnerException {get;set;}
}

记录器类,它将被传递给任何需要记录的东西(比如ExceptionFilter)。这使用 aBlockingCollection来排队发送到 Loggly 的消息。

public class LogglyLogger
{

    private readonly string logglyUrl = "https://logs-01.loggly.com/inputs/xxxx/";
    private readonly HttpClient client; 
    private readonly BlockingCollection<LogMessage> logQueue;
    private readonly int maxAttempts = 4;

    public LogglyLogger()
    {
        logQueue = new BlockingCollection<LogMessage>();
        client = new HttpClient();

        Task.Run(async () =>
        {
            foreach(var msg in logQueue.GetConsumingEnumerable())
            {
                try
                {           
                    await SendMessage(msg);
                }
                catch (Exception)
                {
                    if (msg.SentAttemptCount <= maxAttempts)
                    {
                        msg.SentAttemptCount += 1;
                        logQueue.Add(msg);
                    }
                }
            }
        });
    }


    public void SendLogMessage<T>(T msg) where T : LogMessage
    {
        logQueue.Add(msg);
    }

    private async Task SendMessage<T>(T msg) where T : LogMessage
    {
        await client.PostAsJsonAsync(logglyUrl, msg);
    }
}

以下是我的问题:

  • 这种设置模式有问题BlockingCollection吗?
  • JSON.Net 会找出正确的子类LogMessage,还是我需要以不同的方式发送消息?
  • 吞咽异常绝对是一种代码异味,但我不确定如果记录器无法发送消息会发生什么。有什么想法吗?

在此先感谢,所以。

4

1 回答 1

0

我最终通过更直接地控制发送的内容来解决这个问题。

LogMessageEvelope 类有些成熟,添加了一个非序列化MessageTags属性以将所需的标签传递给 Loggly。

/// <summary>
/// Send the log message to loggly
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
private void SendMessage(LogMessageEnvelope message)
{
    // build list of tags
    string tags = string.Join(",", message.MessageTags); 

    // serialize the message
    JsonSerializerSettings settings = new JsonSerializerSettings 
    { 
        NullValueHandling = NullValueHandling.Ignore,
    };
    string content = 
        JsonConvert.SerializeObject(message, Formatting.Indented, settings);

    // build the request
    HttpRequestMessage request = new HttpRequestMessage();
    request.RequestUri = new Uri(logglyUrl);
    request.Method = HttpMethod.Post;
    request.Content = new StringContent(content, Encoding.UTF8);
    request.Headers.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
    request.Headers.Add("X-LOGGLY-TAG", tags);

    // send the request
    HttpClient client = new HttpClient();
    client.SendAsync(request)
          .ContinueWith(sendTask =>
            {
                // handle the response
                HttpResponseMessage response = sendTask.Result;
                if (!response.IsSuccessStatusCode)
                    // handle a failed log message post
            });
}
于 2014-04-04T21:02:24.367 回答