我正在尝试研究如何为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
?LogMessage
的正确子类,还是需要以不同方式发送消息?提前致谢,SO。
答案 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
});
}