Geçtiğimiz aylara kadar java ile haşır neşir olurken bir anda ibre .net
tarafına kaydı. Birbirleri ile çok ortak noktaları olsa da
implementasyonlar ve api lar farklı olabiliyor. Java yazarken circular
queue (aka ring buffer) ihtiyacım olduğu zaman guava içindeki
com.google.common.collect.EvictingQueue sınıfını kullanıyordum.
.Net Frameworkü üzerinde circular queue implementasyonu bulamadım.
Stackoverflow üzerinde yaptığım arama sonucunda
https://stackoverflow.com/a/9371346
adresindeki çözüme ulaştım.
Problemimiz web api uygulamamıza gelen son 100 isteğin cevap
zamanlarının ortalaması belli bir değeri aşarsa başka bir uygulamaya
uyarı göndermek. İlgili kısımları burada paylaşıyorum.
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
| public class FixedSizedQueue<T> : ConcurrentQueue<T>
{
private object lockObject = new object();
private int limit;
public FixedSizedQueue(int limit)
{
this.limit = limit;
}
public new void Enqueue(T obj)
{
base.Enqueue(obj);
lock (lockObject)
{
T overflow;
while (base.Count > limit && base.TryDequeue(out overflow)) ;
}
}
public T[] ReadAll()
{
return base.ToArray();
}
}
public class StopWatchAttribute : ActionFilterAttribute
{
private static string KEY = "Response.Time";
private static long LastWarning = DateTime.Now.Ticks;
private static long PERIOD = TimeSpan.TicksPerSecond * 15;
private static int SIZE = 100;
private FixedSizedQueue<long> queue = new FixedSizedQueue<long>(SIZE);
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
actionContext.Request.Properties[KEY] = Stopwatch.StartNew();
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
Stopwatch stopwatch = (Stopwatch)actionExecutedContext.Request.Properties[KEY];
var elapsed = stopwatch.ElapsedMilliseconds;
queue.Enqueue(elapsed);
var averageResponseTime = queue.ReadAll().Sum() / SIZE;
var responseTimeIncresing = averageResponseTime > 100;
var notInPeriod = DateTime.Now.Ticks - LastWarning > PERIOD;
if (responseTimeIncresing && notInPeriod)
{
LastWarning = DateTime.Now.Ticks;
Debug.WriteLine($"{elapsed} ms elapsed.");
// TODO whatever you want with this, log or feed another service
}
}
}
public class ValuesController : ApiController
{
[StopWatch]
public string Get()
{
return "ok";
}
}
|