网站异步发布到Loggly

时间:2014-03-12 00:04:44

标签: c# json asp.net-mvc-4 logging blockingcollection

我正在尝试研究如何为Loggly的应用程序日志记录创建异步日志记录解决方案。 看着Loggly's ducumentation,并认为这是一个典型的制作人 - 消费者问题,我想出了这个:

用于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;}
}

Logger类,将传递给需要记录的任何内容(如ExceptionFilter)。这使用BlockingCollection对要发送给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的正确子类,还是需要以不同方式发送消息?
  • 吞咽异常肯定是代码味道,但我不确定如果记录器无法发送消息会发生什么。有什么想法吗?

提前致谢,SO。

1 个答案:

答案 0 :(得分: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
            });
}