-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathHotKeys.ResultProcessor.cs
More file actions
217 lines (204 loc) · 11.1 KB
/
HotKeys.ResultProcessor.cs
File metadata and controls
217 lines (204 loc) · 11.1 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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
namespace StackExchange.Redis;
public sealed partial class HotKeysResult
{
internal static readonly ResultProcessor<HotKeysResult?> Processor = new HotKeysResultProcessor();
private sealed class HotKeysResultProcessor : ResultProcessor<HotKeysResult?>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result)
{
if (result.IsNull)
{
SetResult(message, null);
return true;
}
// an array with a single element that *is* an array/map that is the results
if (result is { Resp2TypeArray: ResultType.Array, ItemsCount: 1 })
{
ref readonly RawResult inner = ref result[0];
if (inner is { Resp2TypeArray: ResultType.Array, IsNull: false })
{
var hotKeys = new HotKeysResult(in inner);
SetResult(message, hotKeys);
return true;
}
}
return false;
}
}
private HotKeysResult(in RawResult result)
{
var metrics = HotKeysMetrics.None; // we infer this from the keys present
var iter = result.GetItems().GetEnumerator();
while (iter.MoveNext())
{
ref readonly RawResult key = ref iter.Current;
if (!iter.MoveNext()) break; // lies about the length!
ref readonly RawResult value = ref iter.Current;
var hash = key.Payload.Hash64();
long i64;
switch (hash)
{
case tracking_active.Hash when tracking_active.Is(hash, key):
TrackingActive = value.GetBoolean();
break;
case sample_ratio.Hash when sample_ratio.Is(hash, key) && value.TryGetInt64(out i64):
SampleRatio = i64;
break;
case selected_slots.Hash when selected_slots.Is(hash, key) & value.Resp2TypeArray is ResultType.Array:
var len = value.ItemsCount;
if (len == 0)
{
_selectedSlots = [];
continue;
}
var items = value.GetItems().GetEnumerator();
var slots = len == 1 ? null : new SlotRange[len];
for (int i = 0; i < len && items.MoveNext(); i++)
{
ref readonly RawResult pair = ref items.Current;
if (pair.Resp2TypeArray is ResultType.Array)
{
long from = -1, to = -1;
switch (pair.ItemsCount)
{
case 1 when pair[0].TryGetInt64(out from):
to = from; // single slot
break;
case 2 when pair[0].TryGetInt64(out from) && pair[1].TryGetInt64(out to):
break;
}
if (from < SlotRange.MinSlot)
{
// skip invalid ranges
}
else if (len == 1 & from == SlotRange.MinSlot & to == SlotRange.MaxSlot)
{
// this is the "normal" case when no slot filter was applied
slots = SlotRange.SharedAllSlots; // avoid the alloc
}
else
{
slots ??= new SlotRange[len];
slots[i] = new((int)from, (int)to);
}
}
}
_selectedSlots = slots;
break;
case all_commands_all_slots_us.Hash when all_commands_all_slots_us.Is(hash, key) && value.TryGetInt64(out i64):
AllCommandsAllSlotsMicroseconds = i64;
break;
case all_commands_selected_slots_us.Hash when all_commands_selected_slots_us.Is(hash, key) && value.TryGetInt64(out i64):
AllCommandSelectedSlotsMicroseconds = i64;
break;
case sampled_command_selected_slots_us.Hash when sampled_command_selected_slots_us.Is(hash, key) && value.TryGetInt64(out i64):
case sampled_commands_selected_slots_us.Hash when sampled_commands_selected_slots_us.Is(hash, key) && value.TryGetInt64(out i64):
SampledCommandsSelectedSlotsMicroseconds = i64;
break;
case net_bytes_all_commands_all_slots.Hash when net_bytes_all_commands_all_slots.Is(hash, key) && value.TryGetInt64(out i64):
AllCommandsAllSlotsNetworkBytes = i64;
break;
case net_bytes_all_commands_selected_slots.Hash when net_bytes_all_commands_selected_slots.Is(hash, key) && value.TryGetInt64(out i64):
NetworkBytesAllCommandsSelectedSlotsRaw = i64;
break;
case net_bytes_sampled_commands_selected_slots.Hash when net_bytes_sampled_commands_selected_slots.Is(hash, key) && value.TryGetInt64(out i64):
NetworkBytesSampledCommandsSelectedSlotsRaw = i64;
break;
case collection_start_time_unix_ms.Hash when collection_start_time_unix_ms.Is(hash, key) && value.TryGetInt64(out i64):
CollectionStartTimeUnixMilliseconds = i64;
break;
case collection_duration_ms.Hash when collection_duration_ms.Is(hash, key) && value.TryGetInt64(out i64):
CollectionDurationMicroseconds = i64 * 1000; // ms vs us is in question: support both, and abstract it from the caller
break;
case collection_duration_us.Hash when collection_duration_us.Is(hash, key) && value.TryGetInt64(out i64):
CollectionDurationMicroseconds = i64;
break;
case total_cpu_time_sys_ms.Hash when total_cpu_time_sys_ms.Is(hash, key) && value.TryGetInt64(out i64):
metrics |= HotKeysMetrics.Cpu;
TotalCpuTimeSystemMicroseconds = i64 * 1000; // ms vs us is in question: support both, and abstract it from the caller
break;
case total_cpu_time_sys_us.Hash when total_cpu_time_sys_us.Is(hash, key) && value.TryGetInt64(out i64):
metrics |= HotKeysMetrics.Cpu;
TotalCpuTimeSystemMicroseconds = i64;
break;
case total_cpu_time_user_ms.Hash when total_cpu_time_user_ms.Is(hash, key) && value.TryGetInt64(out i64):
metrics |= HotKeysMetrics.Cpu;
TotalCpuTimeUserMicroseconds = i64 * 1000; // ms vs us is in question: support both, and abstract it from the caller
break;
case total_cpu_time_user_us.Hash when total_cpu_time_user_us.Is(hash, key) && value.TryGetInt64(out i64):
metrics |= HotKeysMetrics.Cpu;
TotalCpuTimeUserMicroseconds = i64;
break;
case total_net_bytes.Hash when total_net_bytes.Is(hash, key) && value.TryGetInt64(out i64):
metrics |= HotKeysMetrics.Network;
TotalNetworkBytesRaw = i64;
break;
case by_cpu_time_us.Hash when by_cpu_time_us.Is(hash, key) & value.Resp2TypeArray is ResultType.Array:
metrics |= HotKeysMetrics.Cpu;
len = value.ItemsCount / 2;
if (len == 0)
{
_cpuByKey = [];
continue;
}
var cpuTime = new MetricKeyCpu[len];
items = value.GetItems().GetEnumerator();
for (int i = 0; i < len && items.MoveNext(); i++)
{
var metricKey = items.Current.AsRedisKey();
if (items.MoveNext() && items.Current.TryGetInt64(out var metricValue))
{
cpuTime[i] = new(metricKey, metricValue);
}
}
_cpuByKey = cpuTime;
break;
case by_net_bytes.Hash when by_net_bytes.Is(hash, key) & value.Resp2TypeArray is ResultType.Array:
metrics |= HotKeysMetrics.Network;
len = value.ItemsCount / 2;
if (len == 0)
{
_networkBytesByKey = [];
continue;
}
var netBytes = new MetricKeyBytes[len];
items = value.GetItems().GetEnumerator();
for (int i = 0; i < len && items.MoveNext(); i++)
{
var metricKey = items.Current.AsRedisKey();
if (items.MoveNext() && items.Current.TryGetInt64(out var metricValue))
{
netBytes[i] = new(metricKey, metricValue);
}
}
_networkBytesByKey = netBytes;
break;
} // switch
} // while
Metrics = metrics;
}
#pragma warning disable SA1134, SA1300
// ReSharper disable InconsistentNaming
[FastHash] internal static partial class tracking_active { }
[FastHash] internal static partial class sample_ratio { }
[FastHash] internal static partial class selected_slots { }
[FastHash] internal static partial class all_commands_all_slots_us { }
[FastHash] internal static partial class all_commands_selected_slots_us { }
[FastHash] internal static partial class sampled_command_selected_slots_us { }
[FastHash] internal static partial class sampled_commands_selected_slots_us { }
[FastHash] internal static partial class net_bytes_all_commands_all_slots { }
[FastHash] internal static partial class net_bytes_all_commands_selected_slots { }
[FastHash] internal static partial class net_bytes_sampled_commands_selected_slots { }
[FastHash] internal static partial class collection_start_time_unix_ms { }
[FastHash] internal static partial class collection_duration_ms { }
[FastHash] internal static partial class collection_duration_us { }
[FastHash] internal static partial class total_cpu_time_user_ms { }
[FastHash] internal static partial class total_cpu_time_user_us { }
[FastHash] internal static partial class total_cpu_time_sys_ms { }
[FastHash] internal static partial class total_cpu_time_sys_us { }
[FastHash] internal static partial class total_net_bytes { }
[FastHash] internal static partial class by_cpu_time_us { }
[FastHash] internal static partial class by_net_bytes { }
// ReSharper restore InconsistentNaming
#pragma warning restore SA1134, SA1300
}