forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRedisErrorLoggerFeature.cs
More file actions
87 lines (70 loc) · 3.23 KB
/
Copy pathRedisErrorLoggerFeature.cs
File metadata and controls
87 lines (70 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright (c) Service Stack LLC. All Rights Reserved.
// License: https://raw.github.com/ServiceStack/ServiceStack/master/license.txt
using System;
using ServiceStack.Logging;
using ServiceStack.Redis;
using ServiceStack.Web;
namespace ServiceStack
{
public class RedisErrorLoggerFeature : IPlugin
{
public static ILog Log = LogManager.GetLogger(typeof(RedisErrorLoggerFeature));
public IRedisClientsManager redisManager;
public RedisErrorLoggerFeature(IRedisClientsManager redisManager)
{
if (redisManager == null)
throw new ArgumentNullException("redisManager");
this.redisManager = redisManager;
}
public void Register(IAppHost appHost)
{
appHost.ServiceExceptionHandlers.Add(HandleServiceException);
appHost.UncaughtExceptionHandlers.Add(HandleUncaughtException);
}
/// <summary>
/// Service error logs are kept in 'urn:ServiceErrors:{ServiceName}'
/// </summary>
public const string UrnServiceErrorType = "ServiceErrors";
/// <summary>
/// Combined service error logs are maintained in 'urn:ServiceErrors:All'
/// </summary>
public const string CombinedServiceLogId = "All";
public void HandleUncaughtException(IRequest httpReq, IResponse httpRes, string operationName, Exception ex)
{
LogErrorInRedis(operationName, ex);
}
public object HandleServiceException(IRequest httpReq, object request, Exception ex)
{
LogErrorInRedis(httpReq.OperationName, ex);
return null;
}
private void LogErrorInRedis(string operationName, Exception ex)
{
try
{
//Get a thread-safe redis client from the client manager pool
using (var client = redisManager.GetClient())
{
//Get a client with a native interface for storing 'ResponseStatus' objects
var redis = client.As<ResponseStatus>();
//Store the errors in predictable Redis-named lists i.e.
//'urn:ServiceErrors:{ServiceName}' and 'urn:ServiceErrors:All'
var redisSeriviceErrorList = redis.Lists[UrnId.Create(UrnServiceErrorType, operationName)];
var redisCombinedErrorList = redis.Lists[UrnId.Create(UrnServiceErrorType, CombinedServiceLogId)];
//Append the error at the start of the service-specific and combined error logs.
var responseStatus = ex.ToResponseStatus();
redisSeriviceErrorList.Prepend(responseStatus);
redisCombinedErrorList.Prepend(responseStatus);
//Clip old error logs from the managed logs
const int rollingErrorCount = 1000;
redisSeriviceErrorList.Trim(0, rollingErrorCount);
redisCombinedErrorList.Trim(0, rollingErrorCount);
}
}
catch (Exception suppressRedisException)
{
Log.Error("Could not append exception to redis service error logs", suppressRedisException);
}
}
}
}