1
1
# pylint: skip-file
2
2
# flake8: noqa
3
3
4
+ import base64
4
5
import datetime
6
+ import functools
5
7
import itertools
6
8
import json
7
9
import pprint
8
10
import random
9
11
import string
12
+ import struct
10
13
11
14
import click
12
15
from arroyo .backends .kafka import KafkaPayload , KafkaProducer
13
16
from arroyo .types import Topic
14
17
15
18
from sentry .sentry_metrics .use_case_id_registry import UseCaseID
16
19
17
- make_counter_payload = lambda use_case , org_id , rand_str : {
18
- "name" : f"c:{ use_case } /{ use_case } @none" ,
19
- "tags" : {
20
- "environment" : "production" ,
21
- "session.status" : "init" ,
22
- f"metric_e2e_{ use_case } _counter_k_{ rand_str } " : f"metric_e2e_{ use_case } _counter_v_{ rand_str } " ,
23
- },
24
- "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
25
- "type" : "c" ,
26
- "value" : 1 ,
27
- "org_id" : org_id ,
28
- "retention_days" : 90 ,
29
- "project_id" : 3 ,
30
- }
31
-
32
- make_dist_payload = lambda use_case , org_id , rand_str , value_len : {
33
- "name" : f"d:{ use_case } /duration@second" ,
34
- "tags" : {
35
- "environment" : "production" ,
36
- "session.status" : "healthy" ,
37
- f"metric_e2e_{ use_case } _dist_k_{ rand_str } " : f"metric_e2e_{ use_case } _dist_v_{ rand_str } " ,
38
- },
39
- "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
40
- "type" : "d" ,
41
- "value" : {"format" : "array" , "data" : [random .random () for _ in range (value_len )]},
42
- "org_id" : org_id ,
43
- "retention_days" : 90 ,
44
- "project_id" : 3 ,
45
- }
46
-
47
- make_set_payload = lambda use_case , org_id , rand_str , value_len : {
48
- "name" : f"s:{ use_case } /error@none" ,
49
- "tags" : {
50
- "environment" : "production" ,
51
- "session.status" : "errored" ,
52
- f"metric_e2e_{ use_case } _set_k_{ rand_str } " : f"metric_e2e_{ use_case } _set_v_{ rand_str } " ,
53
- },
54
- "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
55
- "type" : "s" ,
56
- "value" : {"format" : "array" , "data" : [random .randint (0 , 2048 ) for _ in range (value_len )]},
57
- "org_id" : org_id ,
58
- "retention_days" : 90 ,
59
- "project_id" : 3 ,
60
- }
61
-
62
- make_gauge_payload = lambda use_case , org_id , rand_str : {
63
- "name" : f"s:{ use_case } /error@none" ,
64
- "tags" : {
65
- "environment" : "production" ,
66
- "session.status" : "errored" ,
67
- f"metric_e2e_{ use_case } _set_k_{ rand_str } " : f"metric_e2e_{ use_case } _set_v_{ rand_str } " ,
68
- },
69
- "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
70
- "type" : "g" ,
71
- "value" : {
72
- "min" : 1 ,
73
- "max" : 1 ,
74
- "sum" : 1 ,
75
- "count" : 1 ,
76
- "last" : 1 ,
77
- },
78
- "org_id" : org_id ,
79
- "retention_days" : 90 ,
80
- "project_id" : 3 ,
81
- }
20
+
21
+ def make_counter_payload (use_case , org_id , rand_str ):
22
+ return {
23
+ "name" : f"c:{ use_case } /{ use_case } @none" ,
24
+ "tags" : {
25
+ "environment" : "production" ,
26
+ "session.status" : "init" ,
27
+ f"metric_e2e_{ use_case } _counter_k_{ rand_str } " : f"metric_e2e_{ use_case } _counter_v_{ rand_str } " ,
28
+ },
29
+ "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
30
+ "type" : "c" ,
31
+ "value" : 1 ,
32
+ "org_id" : org_id ,
33
+ "retention_days" : 90 ,
34
+ "project_id" : 3 ,
35
+ }
36
+
37
+
38
+ def make_dist_payload (use_case , org_id , rand_str , value_len , b64_encode ):
39
+ nums = [random .random () for _ in range (value_len )]
40
+ return {
41
+ "name" : f"d:{ use_case } /duration@second" ,
42
+ "tags" : {
43
+ "environment" : "production" ,
44
+ "session.status" : "healthy" ,
45
+ f"metric_e2e_{ use_case } _dist_k_{ rand_str } " : f"metric_e2e_{ use_case } _dist_v_{ rand_str } " ,
46
+ },
47
+ "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
48
+ "type" : "d" ,
49
+ "value" : (
50
+ {
51
+ "format" : "base64" ,
52
+ "data" : base64 .b64encode (struct .pack (f"<{ len (nums )} d" , * nums )),
53
+ }
54
+ if b64_encode
55
+ else {
56
+ "format" : "array" ,
57
+ "data" : nums ,
58
+ }
59
+ ),
60
+ "org_id" : org_id ,
61
+ "retention_days" : 90 ,
62
+ "project_id" : 3 ,
63
+ }
64
+
65
+
66
+ def make_set_payload (use_case , org_id , rand_str , value_len , b64_encode ):
67
+ INT_WIDTH = 4
68
+ nums = [random .randint (0 , 2048 ) for _ in range (value_len )]
69
+ return {
70
+ "name" : f"s:{ use_case } /error@none" ,
71
+ "tags" : {
72
+ "environment" : "production" ,
73
+ "session.status" : "errored" ,
74
+ f"metric_e2e_{ use_case } _set_k_{ rand_str } " : f"metric_e2e_{ use_case } _set_v_{ rand_str } " ,
75
+ },
76
+ "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
77
+ "type" : "s" ,
78
+ "value" : (
79
+ {
80
+ "format" : "base64" ,
81
+ "data" : base64 .b64encode (
82
+ b"" .join ([num .to_bytes (INT_WIDTH , byteorder = "little" ) for num in nums ])
83
+ ),
84
+ }
85
+ if b64_encode
86
+ else {
87
+ "format" : "array" ,
88
+ "data" : nums ,
89
+ }
90
+ ),
91
+ "org_id" : org_id ,
92
+ "retention_days" : 90 ,
93
+ "project_id" : 3 ,
94
+ }
95
+
96
+
97
+ def make_gauge_payload (use_case , org_id , rand_str ):
98
+ return {
99
+ "name" : f"s:{ use_case } /error@none" ,
100
+ "tags" : {
101
+ "environment" : "production" ,
102
+ "session.status" : "errored" ,
103
+ f"metric_e2e_{ use_case } _set_k_{ rand_str } " : f"metric_e2e_{ use_case } _set_v_{ rand_str } " ,
104
+ },
105
+ "timestamp" : int (datetime .datetime .now (tz = datetime .UTC ).timestamp ()),
106
+ "type" : "g" ,
107
+ "value" : {
108
+ "min" : 1 ,
109
+ "max" : 1 ,
110
+ "sum" : 1 ,
111
+ "count" : 1 ,
112
+ "last" : 1 ,
113
+ },
114
+ "org_id" : org_id ,
115
+ "retention_days" : 90 ,
116
+ "project_id" : 3 ,
117
+ }
118
+
82
119
83
120
make_psql = (
84
121
lambda rand_str , is_generic : f"""
@@ -144,6 +181,9 @@ def produce_msgs(messages, is_generic, host, dryrun, quiet):
144
181
145
182
146
183
@click .command ()
184
+ @click .option (
185
+ "--metric-types" , default = "cdsg" , show_default = True , help = "The types of metrics to send"
186
+ )
147
187
@click .option (
148
188
"--use-cases" ,
149
189
multiple = True ,
@@ -197,8 +237,24 @@ def produce_msgs(messages, is_generic, host, dryrun, quiet):
197
237
show_default = True ,
198
238
help = "Number of elements for metrics (sets and distributions)." ,
199
239
)
240
+ @click .option (
241
+ "--b64-encode" ,
242
+ default = True ,
243
+ show_default = True ,
244
+ help = "Encode sets and distribution metrics values in base64" ,
245
+ )
200
246
def main (
201
- use_cases , rand_str , host , dryrun , quiet , start_org_id , end_org_id , num_bad_msg , value_len
247
+ metric_types ,
248
+ use_cases ,
249
+ rand_str ,
250
+ host ,
251
+ dryrun ,
252
+ quiet ,
253
+ start_org_id ,
254
+ end_org_id ,
255
+ num_bad_msg ,
256
+ value_len ,
257
+ b64_encode ,
202
258
):
203
259
if UseCaseID .SESSIONS .value in use_cases and len (use_cases ) > 1 :
204
260
click .secho (
@@ -208,32 +264,36 @@ def main(
208
264
)
209
265
exit (1 )
210
266
211
- rand_str = rand_str or "" .join (random .choices (string .ascii_uppercase + string .digits , k = 8 ))
212
-
213
267
is_generic = UseCaseID .SESSIONS .value not in use_cases
268
+ metric_types = "" .join (set (metric_types ))
269
+ rand_str = rand_str or "" .join (random .choices (string .ascii_uppercase + string .digits , k = 8 ))
270
+ payload_generators = {
271
+ "c" : functools .partial (make_counter_payload , rand_str = rand_str ),
272
+ "d" : functools .partial (
273
+ make_dist_payload , rand_str = rand_str , value_len = value_len , b64_encode = b64_encode
274
+ ),
275
+ "s" : functools .partial (
276
+ make_set_payload , rand_str = rand_str , value_len = value_len , b64_encode = b64_encode
277
+ ),
278
+ "g" : functools .partial (make_gauge_payload , rand_str = rand_str ),
279
+ }
214
280
215
281
messages = list (
216
282
itertools .chain .from_iterable (
217
283
(
218
- make_counter_payload (use_case , org , rand_str ),
219
- make_dist_payload (use_case , org , rand_str , value_len ),
220
- make_set_payload (use_case , org , rand_str , value_len ),
221
- make_gauge_payload (use_case , org , rand_str ),
284
+ payload_generators [metric_type ](use_case = use_case , org_id = org_id )
285
+ for metric_type in metric_types
222
286
)
223
287
for use_case in use_cases
224
- for org in range (start_org_id , end_org_id + 1 )
288
+ for org_id in range (start_org_id , end_org_id + 1 )
225
289
)
226
290
)
227
-
228
291
messages .extend ([{"BAD_VALUE" : rand_str , "idx" : i } for i in range (num_bad_msg )])
229
292
230
293
random .shuffle (messages )
231
-
232
294
produce_msgs (messages , is_generic , host , dryrun , quiet )
233
295
234
- metrics_per_use_case = 4
235
296
strs_per_use_case = 3
236
-
237
297
print (
238
298
f"Use the following SQL to verify postgres, "
239
299
f"there should be { strs_per_use_case } strings for each use cases, "
@@ -244,8 +304,8 @@ def main(
244
304
if is_generic :
245
305
print (
246
306
f"Use the following SQL to verify clickhouse, "
247
- f"there should be { metrics_per_use_case } metrics for each use cases, "
248
- f"{ metrics_per_use_case * len (use_cases ) * (end_org_id - start_org_id + 1 )} in total."
307
+ f"there should be { len ( metric_types ) } metrics for each use cases, "
308
+ f"{ len ( metric_types ) * len (use_cases ) * (end_org_id - start_org_id + 1 )} in total."
249
309
)
250
310
print (make_csql (rand_str , is_generic ))
251
311
0 commit comments