Skip to content

Commit ac607d1

Browse files
tiagodaraujojoelfoliveira
authored andcommitted
feat: inc and dec gauge metrics
1 parent 7f017cf commit ac607d1

File tree

20 files changed

+280
-129
lines changed

20 files changed

+280
-129
lines changed

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ sample:
55

66
sample-clean:
77
@docker compose -f docker-compose.sample.yaml down
8+
9+
benchmark:
10+
dotnet run -c Release --project ./tests/benchmark/Farfetch.LoadShedding.BenchmarkTests/Farfetch.LoadShedding.BenchmarkTests.csproj
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Threading.Tasks;
32
using Farfetch.LoadShedding.Tasks;
43
using Microsoft.AspNetCore.Http;
@@ -9,8 +8,6 @@ internal class HttpHeaderPriorityResolver : IPriorityResolver
98
{
109
internal const string DefaultPriorityHeaderName = "X-Priority";
1110

12-
private const string Separator = "-";
13-
1411
private readonly string _headerName;
1512

1613
public HttpHeaderPriorityResolver()
@@ -30,21 +27,7 @@ public Task<Priority> ResolveAsync(HttpContext context)
3027
return Task.FromResult(Priority.Normal);
3128
}
3229

33-
var normalizedValue = this.NormalizeHeaderValue(values);
34-
35-
if (!Enum.TryParse(normalizedValue, true, out Priority priority))
36-
{
37-
priority = Priority.Normal;
38-
}
39-
40-
return Task.FromResult(priority);
41-
}
42-
43-
private string NormalizeHeaderValue(string headerValue)
44-
{
45-
return headerValue
46-
.Replace(Separator, string.Empty)
47-
.ToLower();
30+
return Task.FromResult(values.ToString().ParsePriority());
4831
}
4932
}
5033
}

src/Farfetch.LoadShedding.Prometheus/IAdaptativeLimiterOptionsExtensions.cs

+15-17
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ private static void SubscribeItemDequeuedEvent(
6666
events.ItemDequeued.Subscribe(args =>
6767
{
6868
var method = accessor.GetMethod();
69+
var priority = args.Priority.FormatPriority();
6970

70-
queueItemsGauge.Set(method, args.Priority.FormatPriority(), args.QueueCount);
71-
queueTimeHistogram.Observe(method, args.Priority.FormatPriority(), args.QueueTime.TotalSeconds);
71+
queueItemsGauge.Decrement(method, priority);
72+
queueTimeHistogram.Observe(method, priority, args.QueueTime.TotalSeconds);
7273
});
7374
}
7475

@@ -88,7 +89,7 @@ private static void SubscribeItemProcessedEvent(
8889
var method = accessor.GetMethod();
8990
var priority = args.Priority.FormatPriority();
9091

91-
concurrencyItemsGauge.Set(method, priority, args.ConcurrencyCount);
92+
concurrencyItemsGauge.Decrement(method, priority);
9293
taskProcessingTimeHistogram.Observe(method, priority, args.ProcessingTime.TotalSeconds);
9394
});
9495
}
@@ -123,10 +124,10 @@ private static void SubscribeItemProcessingEvent(
123124

124125
events.ItemProcessing.Subscribe(args =>
125126
{
126-
concurrencyItemsGauge.Set(
127-
accessor.GetMethod(),
128-
args.Priority.FormatPriority(),
129-
args.ConcurrencyCount);
127+
var method = accessor.GetMethod();
128+
var priority = args.Priority.FormatPriority();
129+
130+
concurrencyItemsGauge.Increment(method, priority);
130131
});
131132
}
132133

@@ -139,10 +140,10 @@ private static void SubscribeItemEnqueuedEvent(this Events.ILoadSheddingEvents e
139140

140141
events.ItemEnqueued.Subscribe(args =>
141142
{
142-
queueItemsGauge.Set(
143-
accessor.GetMethod(),
144-
args.Priority.FormatPriority(),
145-
args.QueueCount);
143+
var method = accessor.GetMethod();
144+
var priority = args.Priority.FormatPriority();
145+
146+
queueItemsGauge.Increment(method, priority);
146147
});
147148
}
148149

@@ -155,8 +156,10 @@ private static void SubscribeRejectedEvent(this Events.ILoadSheddingEvents event
155156

156157
events.Rejected.Subscribe(args =>
157158
{
159+
var method = accessor.GetMethod();
160+
158161
rejectedCounter.Increment(
159-
accessor.GetMethod(),
162+
method,
160163
args.Priority.FormatPriority(),
161164
args.Reason);
162165
});
@@ -171,10 +174,5 @@ private static string GetMethod(this IHttpContextAccessor accessor)
171174

172175
return accessor.HttpContext.Request.Method.ToUpper();
173176
}
174-
175-
private static string FormatPriority(this Priority priority)
176-
{
177-
return priority.ToString().ToLower();
178-
}
179177
}
180178
}

src/Farfetch.LoadShedding.Prometheus/Metrics/HttpRequestsConcurrencyItemsGauge.cs

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Prometheus;
2-
32
using PrometheusBase = Prometheus;
43

54
namespace Farfetch.LoadShedding.Prometheus.Metrics
@@ -22,16 +21,27 @@ internal HttpRequestsConcurrencyItemsGauge(
2221
protected override string DefaultName => "http_requests_concurrency_items_total";
2322

2423
/// <summary>
25-
/// Sets the value of the gauge.
24+
/// Increments the value of the gauge.
25+
/// </summary>
26+
/// <param name="method">The method.</param>
27+
/// <param name="priority">The priority.</param>
28+
public void Increment(string method, string priority)
29+
{
30+
this.Metric?
31+
.WithLabels(method, priority)
32+
.Inc();
33+
}
34+
35+
/// <summary>
36+
/// Decrements the value of the gauge.
2637
/// </summary>
2738
/// <param name="method">The method.</param>
2839
/// <param name="priority">The priority.</param>
29-
/// <param name="value">The value.</param>
30-
public void Set(string method, string priority, double value)
40+
public void Decrement(string method, string priority)
3141
{
3242
this.Metric?
3343
.WithLabels(method, priority)
34-
.Set(value);
44+
.Dec();
3545
}
3646

3747
/// <inheritdoc/>
@@ -40,7 +50,7 @@ protected override Gauge Create(CollectorRegistry registry, MetricOptions option
4050
return PrometheusBase
4151
.Metrics
4252
.WithCustomRegistry(registry)
43-
.CreateGauge(options.Name, Description, new PrometheusBase.GaugeConfiguration
53+
.CreateGauge(options.Name, Description, new GaugeConfiguration
4454
{
4555
LabelNames = new[] { MetricsConstants.MethodLabel, MetricsConstants.PriorityLabel },
4656
});

src/Farfetch.LoadShedding.Prometheus/Metrics/HttpRequestsQueueItemsGauge.cs

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Prometheus;
2-
32
using PrometheusBase = Prometheus;
43

54
namespace Farfetch.LoadShedding.Prometheus.Metrics
@@ -22,16 +21,27 @@ internal HttpRequestsQueueItemsGauge(
2221
protected override string DefaultName => "http_requests_queue_items_total";
2322

2423
/// <summary>
25-
/// Sets the value of the gauge.
24+
/// Increments the value of the gauge.
25+
/// </summary>
26+
/// <param name="method">The method.</param>
27+
/// <param name="priority">The priority.</param>
28+
public void Increment(string method, string priority)
29+
{
30+
this.Metric?
31+
.WithLabels(method, priority)
32+
.Inc();
33+
}
34+
35+
/// <summary>
36+
/// Decrements the value of the gauge.
2637
/// </summary>
2738
/// <param name="method">The method.</param>
2839
/// <param name="priority">The priority.</param>
29-
/// <param name="value">The value.</param>
30-
public void Set(string method, string priority, double value)
40+
public void Decrement(string method, string priority)
3141
{
3242
this.Metric?
3343
.WithLabels(method, priority)
34-
.Set(value);
44+
.Dec();
3545
}
3646

3747
/// <inheritdoc/>

src/Farfetch.LoadShedding/Tasks/ConcurrentCounter.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ public int Decrement()
6464
{
6565
lock (this._locker)
6666
{
67-
if (this._count > 0)
68-
{
69-
this._count--;
70-
}
67+
this._count--;
7168

7269
return this._count;
7370
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
3+
namespace Farfetch.LoadShedding.Tasks
4+
{
5+
/// <summary>
6+
/// Extension methods of <see cref="Priority"/>
7+
/// </summary>
8+
public static class PriorityExtensions
9+
{
10+
/// <summary>
11+
/// Parses a string value into a <see cref="Priority"/> enum.
12+
/// The parser is case-insensetive and accepts hyphen. e.g. Normal, Non-Critival or CRITICAL.
13+
/// </summary>
14+
/// <param name="value">Priority string value to be parsed.</param>
15+
/// <returns>The Priority parsed value. Returns Priority.Normal if the value is invalid.</returns>
16+
public static Priority ParsePriority(this string value)
17+
{
18+
if (value is null)
19+
{
20+
return Priority.Normal;
21+
}
22+
23+
var normalizedValue = value
24+
.Replace("-", string.Empty)
25+
.ToLowerInvariant();
26+
27+
if (Enum.TryParse(normalizedValue, true, out Priority priority))
28+
{
29+
return priority;
30+
}
31+
32+
return Priority.Normal;
33+
}
34+
35+
/// <summary>
36+
/// Format a <see cref="Priority"/> enum to a string.
37+
/// </summary>
38+
/// <param name="priority">Priority value to be formatted.</param>
39+
/// <returns>The Priority format string.</returns>
40+
public static string FormatPriority(this Priority priority)
41+
{
42+
return priority.ToString().ToLowerInvariant();
43+
}
44+
}
45+
}

src/Farfetch.LoadShedding/Tasks/TaskQueue.cs

+16-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System;
2-
using System.Collections.Generic;
31
using System.Linq;
42
using System.Runtime.CompilerServices;
53

@@ -11,12 +9,7 @@ internal class TaskQueue
119
{
1210
private readonly ConcurrentCounter _counter = new();
1311

14-
private readonly IDictionary<Priority, TaskItemList> _queues = new SortedDictionary<Priority, TaskItemList>()
15-
{
16-
[Priority.Critical] = new TaskItemList(),
17-
[Priority.Normal] = new TaskItemList(),
18-
[Priority.NonCritical] = new TaskItemList(),
19-
};
12+
private readonly TaskItemList[] _queues = new TaskItemList[3] { new(), new(), new() };
2013

2114
public TaskQueue(int limit)
2215
{
@@ -44,9 +37,8 @@ public void Enqueue(TaskItem item)
4437
public TaskItem Dequeue()
4538
{
4639
var nextQueueItem = this._queues
47-
.FirstOrDefault(x => x.Value.HasItems)
48-
.Value?
49-
.Dequeue();
40+
.FirstOrDefault(x => x.HasItems)
41+
?.Dequeue();
5042

5143
if (nextQueueItem != null)
5244
{
@@ -58,7 +50,7 @@ public TaskItem Dequeue()
5850

5951
public void Remove(TaskItem item)
6052
{
61-
if (this._queues[item.Priority].Remove(item))
53+
if (this._queues[(int)item.Priority].Remove(item))
6254
{
6355
this.DecrementCounter();
6456
}
@@ -68,25 +60,22 @@ internal void Clear()
6860
{
6961
foreach (var queue in this._queues)
7062
{
71-
queue.Value.Clear();
63+
queue.Clear();
7264
}
7365
}
7466

7567
private int EnqueueItem(TaskItem item)
7668
{
77-
this._queues[item.Priority].Add(item);
78-
79-
var count = this._counter.Increment();
69+
this._queues[(int)item.Priority].Add(item);
8070

81-
return count;
71+
return this.IncrementCounter();
8272
}
8373

8474
private void RejectLastItem()
8575
{
8676
var lastItem = this._queues
87-
.LastOrDefault(x => x.Value.HasItems)
88-
.Value?
89-
.DequeueLast();
77+
.LastOrDefault(x => x.HasItems)
78+
?.DequeueLast();
9079

9180
if (lastItem == null)
9281
{
@@ -98,9 +87,14 @@ private void RejectLastItem()
9887
lastItem.Reject();
9988
}
10089

101-
private void DecrementCounter()
90+
private int IncrementCounter()
91+
{
92+
return this._counter.Increment();
93+
}
94+
95+
private int DecrementCounter()
10296
{
103-
this._counter.Decrement();
97+
return this._counter.Decrement();
10498
}
10599
}
106100
}

tests/Directory.Build.props

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../src'))" />
33

44
<ItemGroup>
5-
<Compile Include="$(MSBuildProjectDirectory)/../Traits.cs" Link="Properties/Traits.cs"/>
6-
<AdditionalFiles Include="..\..\..\stylecop.json" Link="stylecop.json" />
5+
<AdditionalFiles Include="..\..\..\stylecop.json" Link="stylecop.json" />
76
</ItemGroup>
87
</Project>

tests/benchmark/Farfetch.LoadShedding.BenchmarkTests/Farfetch.LoadShedding.BenchmarkTests.csproj

-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,4 @@
1818
<ProjectReference Include="..\..\..\src\Farfetch.LoadShedding\Farfetch.LoadShedding.csproj" />
1919
</ItemGroup>
2020

21-
<ItemGroup>
22-
<Compile Remove="$(MSBuildProjectDirectory)/../Traits.cs" />
23-
</ItemGroup>
24-
2521
</Project>

0 commit comments

Comments
 (0)