prometheus-client-mmap 0.28.1-x86_64-linux → 1.0.1-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -1
  3. data/README.md +2 -30
  4. data/ext/fast_mmaped_file_rs/extconf.rb +1 -3
  5. data/ext/fast_mmaped_file_rs/src/error.rs +8 -0
  6. data/ext/fast_mmaped_file_rs/src/file_info.rs +51 -1
  7. data/ext/fast_mmaped_file_rs/src/mmap/inner.rs +38 -13
  8. data/ext/fast_mmaped_file_rs/src/mmap.rs +71 -5
  9. data/lib/2.7/fast_mmaped_file_rs.so +0 -0
  10. data/lib/3.0/fast_mmaped_file_rs.so +0 -0
  11. data/lib/3.1/fast_mmaped_file_rs.so +0 -0
  12. data/lib/3.2/fast_mmaped_file_rs.so +0 -0
  13. data/lib/prometheus/client/configuration.rb +1 -2
  14. data/lib/prometheus/client/formats/text.rb +1 -12
  15. data/lib/prometheus/client/helper/mmaped_file.rb +3 -14
  16. data/lib/prometheus/client/rack/exporter.rb +1 -3
  17. data/lib/prometheus/client/version.rb +1 -1
  18. metadata +4 -46
  19. data/ext/fast_mmaped_file/extconf.rb +0 -30
  20. data/ext/fast_mmaped_file/fast_mmaped_file.c +0 -122
  21. data/ext/fast_mmaped_file/file_format.c +0 -5
  22. data/ext/fast_mmaped_file/file_format.h +0 -11
  23. data/ext/fast_mmaped_file/file_parsing.c +0 -195
  24. data/ext/fast_mmaped_file/file_parsing.h +0 -27
  25. data/ext/fast_mmaped_file/file_reading.c +0 -102
  26. data/ext/fast_mmaped_file/file_reading.h +0 -30
  27. data/ext/fast_mmaped_file/globals.h +0 -14
  28. data/ext/fast_mmaped_file/mmap.c +0 -428
  29. data/ext/fast_mmaped_file/mmap.h +0 -61
  30. data/ext/fast_mmaped_file/rendering.c +0 -199
  31. data/ext/fast_mmaped_file/rendering.h +0 -8
  32. data/ext/fast_mmaped_file/utils.c +0 -56
  33. data/ext/fast_mmaped_file/utils.h +0 -22
  34. data/ext/fast_mmaped_file/value_access.c +0 -242
  35. data/ext/fast_mmaped_file/value_access.h +0 -15
  36. data/lib/2.7/fast_mmaped_file.so +0 -0
  37. data/lib/3.0/fast_mmaped_file.so +0 -0
  38. data/lib/3.1/fast_mmaped_file.so +0 -0
  39. data/lib/3.2/fast_mmaped_file.so +0 -0
  40. data/lib/prometheus/client/helper/loader.rb +0 -44
  41. data/vendor/c/hashmap/.gitignore +0 -52
  42. data/vendor/c/hashmap/LICENSE +0 -21
  43. data/vendor/c/hashmap/README.md +0 -90
  44. data/vendor/c/hashmap/_config.yml +0 -1
  45. data/vendor/c/hashmap/src/hashmap.c +0 -692
  46. data/vendor/c/hashmap/src/hashmap.h +0 -267
  47. data/vendor/c/hashmap/test/Makefile +0 -22
  48. data/vendor/c/hashmap/test/hashmap_test.c +0 -608
  49. data/vendor/c/jsmn/.travis.yml +0 -4
  50. data/vendor/c/jsmn/LICENSE +0 -20
  51. data/vendor/c/jsmn/Makefile +0 -41
  52. data/vendor/c/jsmn/README.md +0 -168
  53. data/vendor/c/jsmn/example/jsondump.c +0 -126
  54. data/vendor/c/jsmn/example/simple.c +0 -76
  55. data/vendor/c/jsmn/jsmn.c +0 -314
  56. data/vendor/c/jsmn/jsmn.h +0 -76
  57. data/vendor/c/jsmn/library.json +0 -16
  58. data/vendor/c/jsmn/test/test.h +0 -27
  59. data/vendor/c/jsmn/test/tests.c +0 -407
  60. data/vendor/c/jsmn/test/testutil.h +0 -94
@@ -1,428 +0,0 @@
1
- #include "mmap.h"
2
-
3
- #include <errno.h>
4
- #include <fcntl.h>
5
- #include <ruby/util.h>
6
- #include <ruby/version.h>
7
- #include <sys/mman.h>
8
-
9
- #include "file_format.h"
10
- #include "utils.h"
11
-
12
- #if 0
13
- #include <stdio.h>
14
- #define DEBUGF(format, ...) printf("%d: " format "\n", __LINE__, __VA_ARGS__)
15
- #else
16
- #define DEBUGF(format, ...)
17
- #endif
18
-
19
- /* This is the ID of the WeakMap used to track strings allocated that
20
- * are backed by a memory-mapped file.
21
- */
22
- #define WEAK_OBJ_TRACKER "@weak_obj_tracker"
23
-
24
- /**
25
- * Maps a given VALUE to some key for the WeakMap. For now, we just use
26
- * the integer value as the key since that suffices, though this does
27
- * require Ruby 2.7 due to https://bugs.ruby-lang.org/issues/16035.
28
- */
29
- static VALUE weak_obj_tracker_get_key(VALUE val) { return val; }
30
-
31
- static void update_rstring_len(VALUE val, size_t len) {
32
- #if defined(RUBY_API_VERSION_MAJOR) && defined(RUBY_API_VERSION_MINOR) && (RUBY_API_VERSION_MAJOR == 3) && \
33
- (RUBY_API_VERSION_MINOR >= 3)
34
-
35
- RSTRING(val)->len = len;
36
- #else
37
- RSTRING(val)->as.heap.len = len;
38
- #endif
39
- }
40
-
41
- /**
42
- * Adds a T_STRING type to the WeakMap. The WeakMap should be stored
43
- * as an instance variable.
44
- */
45
- static void weak_obj_tracker_add(VALUE obj, VALUE val) {
46
- Check_Type(val, T_STRING);
47
-
48
- VALUE tracker = rb_iv_get(obj, WEAK_OBJ_TRACKER);
49
- VALUE key = weak_obj_tracker_get_key(val);
50
-
51
- rb_funcall(tracker, rb_intern("[]="), 2, key, val);
52
- }
53
-
54
- /**
55
- * Iterator function for updating a single element from the WeakMap.
56
- */
57
- VALUE mm_update_obj_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, self)) {
58
- Check_Type(self, T_DATA);
59
- Check_Type(i, T_STRING);
60
- rb_check_arity(argc, 1, 1);
61
-
62
- mm_ipc *i_mm;
63
- GET_MMAP(self, i_mm, MM_MODIFY);
64
-
65
- RSTRING(i)->as.heap.ptr = i_mm->t->addr;
66
- update_rstring_len(i, i_mm->t->real);
67
-
68
- return Qtrue;
69
- }
70
-
71
- /**
72
- * This iterates through the WeakMap defined on the class and updates
73
- * the RStrings to use the newly-allocated memory region.
74
- */
75
- void mm_update(VALUE obj) {
76
- VALUE tracker = rb_iv_get(obj, WEAK_OBJ_TRACKER);
77
-
78
- rb_block_call(tracker, rb_intern("each_value"), 0, NULL, mm_update_obj_i, obj);
79
- }
80
-
81
- typedef struct {
82
- VALUE obj, *argv;
83
- ID id;
84
- int flag, argc;
85
- } mm_bang;
86
-
87
- static VALUE mm_protect_bang(VALUE *t) { return rb_funcall2(t[0], (ID)t[1], (int)t[2], (VALUE *)t[3]); }
88
-
89
- static VALUE mm_recycle(VALUE str) {
90
- rb_gc_force_recycle(str);
91
- return str;
92
- }
93
-
94
- static VALUE mm_vunlock(VALUE obj) {
95
- mm_ipc *i_mm;
96
-
97
- GET_MMAP(obj, i_mm, 0);
98
- return Qnil;
99
- }
100
-
101
- static VALUE mm_str(VALUE obj, int modify) {
102
- mm_ipc *i_mm;
103
- VALUE ret = Qnil;
104
-
105
- GET_MMAP(obj, i_mm, modify & ~MM_ORIGIN);
106
- if (modify & MM_MODIFY) {
107
- if (i_mm->t->flag & MM_FROZEN) rb_error_frozen("mmap");
108
- }
109
- ret = rb_obj_alloc(rb_cString);
110
- RSTRING(ret)->as.heap.ptr = i_mm->t->addr;
111
- RSTRING(ret)->as.heap.aux.capa = i_mm->t->len;
112
- update_rstring_len(ret, i_mm->t->real);
113
-
114
- weak_obj_tracker_add(obj, ret);
115
-
116
- DEBUGF("RString capa: %d, len: %d", RSTRING(ret)->as.heap.aux.capa, RSTRING(ret)->as.heap.len);
117
-
118
- if (modify & MM_ORIGIN) {
119
- #if HAVE_RB_DEFINE_ALLOC_FUNC
120
- RSTRING(ret)->as.heap.aux.shared = obj;
121
- FL_SET(ret, RSTRING_NOEMBED);
122
- FL_SET(ret, FL_USER18);
123
- #else
124
- RSTRING(ret)->orig = ret;
125
- #endif
126
- }
127
- if (i_mm->t->flag & MM_FROZEN) {
128
- ret = rb_obj_freeze(ret);
129
- }
130
- return ret;
131
- }
132
-
133
- static VALUE mm_i_bang(bang_st) mm_bang *bang_st;
134
- {
135
- VALUE str, res;
136
- mm_ipc *i_mm;
137
-
138
- str = mm_str(bang_st->obj, bang_st->flag);
139
- if (bang_st->flag & MM_PROTECT) {
140
- VALUE tmp[4];
141
- tmp[0] = str;
142
- tmp[1] = (VALUE)bang_st->id;
143
- tmp[2] = (VALUE)bang_st->argc;
144
- tmp[3] = (VALUE)bang_st->argv;
145
- res = rb_ensure(mm_protect_bang, (VALUE)tmp, mm_recycle, str);
146
- } else {
147
- res = rb_funcall2(str, bang_st->id, bang_st->argc, bang_st->argv);
148
- RB_GC_GUARD(res);
149
- }
150
- if (res != Qnil) {
151
- GET_MMAP(bang_st->obj, i_mm, 0);
152
- i_mm->t->real = RSTRING_LEN(str);
153
- }
154
- return res;
155
- }
156
-
157
- static VALUE mm_bang_i(VALUE obj, int flag, ID id, int argc, VALUE *argv) {
158
- VALUE res;
159
- mm_ipc *i_mm;
160
- mm_bang bang_st;
161
-
162
- GET_MMAP(obj, i_mm, 0);
163
- if ((flag & MM_CHANGE) && (i_mm->t->flag & MM_FIXED)) {
164
- rb_raise(rb_eTypeError, "try to change the size of a fixed map");
165
- }
166
- bang_st.obj = obj;
167
- bang_st.flag = flag;
168
- bang_st.id = id;
169
- bang_st.argc = argc;
170
- bang_st.argv = argv;
171
- if (i_mm->t->flag & MM_IPC) {
172
- res = rb_ensure(mm_i_bang, (VALUE)&bang_st, mm_vunlock, obj);
173
- } else {
174
- res = mm_i_bang(&bang_st);
175
- }
176
- if (res == Qnil) return res;
177
- return (flag & MM_ORIGIN) ? res : obj;
178
- }
179
-
180
- static void mm_free(mm_ipc *i_mm) {
181
- if (i_mm->t->path) {
182
- if (munmap(i_mm->t->addr, i_mm->t->len) != 0) {
183
- if (i_mm->t->path != (char *)-1 && i_mm->t->path != NULL) {
184
- free(i_mm->t->path);
185
- }
186
- free(i_mm);
187
-
188
- rb_raise(rb_eRuntimeError, "munmap failed at %s:%d with errno: %d", __FILE__, __LINE__, errno);
189
- }
190
-
191
- if (i_mm->t->path != (char *)-1) {
192
- free(i_mm->t->path);
193
- }
194
- }
195
- free(i_mm);
196
- }
197
-
198
- /*
199
- * call-seq:
200
- * new(file)
201
- *
202
- * create a new Mmap object
203
- *
204
- * * <em>file</em>
205
- *
206
- *
207
- * Creates a mapping that's shared with all other processes
208
- * mapping the same areas of the file.
209
- *
210
- */
211
- VALUE mm_s_new(int argc, VALUE *argv, VALUE obj) {
212
- VALUE res = rb_funcall2(obj, rb_intern("allocate"), 0, 0);
213
- rb_obj_call_init(res, argc, argv);
214
- return res;
215
- }
216
-
217
- VALUE mm_s_alloc(VALUE obj) {
218
- VALUE res;
219
- mm_ipc *i_mm;
220
-
221
- res = Data_Make_Struct(obj, mm_ipc, 0, mm_free, i_mm);
222
- i_mm->t = ALLOC_N(mm_mmap, 1);
223
- MEMZERO(i_mm->t, mm_mmap, 1);
224
- i_mm->t->fd = -1;
225
- return res;
226
- }
227
-
228
- size_t next_page_boundary(size_t value) {
229
- size_t page_size = sysconf(_SC_PAGESIZE);
230
-
231
- while (page_size < value) {
232
- page_size *= 2;
233
- }
234
-
235
- return page_size;
236
- }
237
-
238
- /* Reference implementations:
239
- * mozilla: https://hg.mozilla.org/mozilla-central/file/3d846420a907/xpcom/glue/FileUtils.cpp#l71
240
- * glibc: https://github.com/lattera/glibc/blob/master/sysdeps/posix/posix_fallocate.c
241
- */
242
- int reserve_mmap_file_bytes(int fd, size_t size) {
243
- #if __linux__
244
- /* From https://stackoverflow.com/a/22820221: The difference with
245
- * ftruncate(2) is that (on file systems supporting it, e.g. Ext4)
246
- * disk space is indeed reserved by posix_fallocate but ftruncate
247
- * extends the file by adding holes (and without reserving disk
248
- * space). */
249
- return posix_fallocate(fd, 0, size);
250
- #else
251
- /* We simplify the reference implemnetations since we generally
252
- * don't need to reserve more than a page size. */
253
- return ftruncate(fd, size);
254
- #endif
255
- }
256
-
257
- VALUE mm_init(VALUE obj, VALUE fname) {
258
- struct stat st;
259
- int fd, smode = 0, pmode = 0, vscope, perm, init;
260
- MMAP_RETTYPE addr;
261
- mm_ipc *i_mm;
262
- char *path;
263
- size_t size = 0;
264
- off_t offset;
265
-
266
- vscope = 0;
267
- path = 0;
268
- fd = -1;
269
-
270
- VALUE klass = rb_eval_string("ObjectSpace::WeakMap");
271
- VALUE weak_obj_tracker = rb_class_new_instance(0, NULL, klass);
272
- rb_iv_set(obj, WEAK_OBJ_TRACKER, weak_obj_tracker);
273
-
274
- fname = rb_str_to_str(fname);
275
- SafeStringValue(fname);
276
- path = StringValuePtr(fname);
277
-
278
- vscope = MAP_SHARED;
279
- size = 0;
280
- perm = 0666;
281
-
282
- smode = O_RDWR;
283
- pmode = PROT_READ | PROT_WRITE;
284
-
285
- if ((fd = open(path, smode, perm)) == -1) {
286
- rb_raise(rb_eArgError, "Can't open %s", path);
287
- }
288
-
289
- if (fstat(fd, &st) == -1) {
290
- close(fd);
291
- rb_raise(rb_eArgError, "Can't stat %s", path);
292
- }
293
- size = st.st_size;
294
-
295
- Data_Get_Struct(obj, mm_ipc, i_mm);
296
-
297
- offset = 0;
298
- init = 0;
299
-
300
- if (size == 0) {
301
- init = 1;
302
- size = INITIAL_SIZE;
303
- }
304
-
305
- /* We need to ensure the underlying file descriptor is at least a page size.
306
- * Otherwise, we could get a SIGBUS error if mmap() attempts to read or write
307
- * past the file. */
308
- size_t reserve_size = next_page_boundary(size);
309
-
310
- if (reserve_mmap_file_bytes(fd, reserve_size) != 0) {
311
- close(fd);
312
- rb_raise(rb_eIOError, "Can't reserve %zu bytes for memory-mapped file in %s", reserve_size, path);
313
- }
314
-
315
- addr = mmap(0, size, pmode, vscope, fd, offset);
316
-
317
- if (addr == MAP_FAILED || !addr) {
318
- close(fd);
319
- rb_raise(rb_eArgError, "mmap failed (%d)", errno);
320
- }
321
- i_mm->t->fd = fd;
322
- i_mm->t->addr = addr;
323
- i_mm->t->len = size;
324
- if (!init) {
325
- i_mm->t->real = size;
326
- }
327
- i_mm->t->pmode = pmode;
328
- i_mm->t->vscope = vscope;
329
- i_mm->t->smode = smode & ~O_TRUNC;
330
- i_mm->t->path = (path) ? ruby_strdup(path) : (char *)-1;
331
-
332
- if (smode == O_WRONLY) {
333
- i_mm->t->flag |= MM_FIXED;
334
- }
335
- return obj;
336
- }
337
-
338
- /*
339
- * Document-method: []
340
- * Document-method: slice
341
- *
342
- * call-seq: [](args)
343
- *
344
- * Element reference - with the following syntax:
345
- *
346
- * self[nth]
347
- *
348
- * retrieve the <em>nth</em> character
349
- *
350
- * self[start..last]
351
- *
352
- * return a substring from <em>start</em> to <em>last</em>
353
- *
354
- * self[start, length]
355
- *
356
- * return a substring of <em>lenght</em> characters from <em>start</em>
357
- */
358
- VALUE mm_aref_m(int argc, VALUE *argv, VALUE obj) { return mm_bang_i(obj, MM_ORIGIN, rb_intern("[]"), argc, argv); }
359
-
360
- /*
361
- * Document-method: msync
362
- * Document-method: sync
363
- * Document-method: flush
364
- *
365
- * call-seq: msync
366
- *
367
- * flush the file
368
- */
369
- VALUE mm_msync(int argc, VALUE *argv, VALUE obj) {
370
- mm_ipc *i_mm;
371
- GET_MMAP(obj, i_mm, MM_MODIFY);
372
-
373
- VALUE oflag;
374
- int ret;
375
- int flag = MS_SYNC;
376
-
377
- if (argc) {
378
- rb_scan_args(argc, argv, "01", &oflag);
379
- flag = NUM2INT(oflag);
380
- }
381
- if ((ret = msync(i_mm->t->addr, i_mm->t->len, flag)) != 0) {
382
- rb_raise(rb_eArgError, "msync(%d)", ret);
383
- }
384
-
385
- return obj;
386
- }
387
-
388
- /*
389
- * Document-method: munmap
390
- * Document-method: unmap
391
- *
392
- * call-seq: munmap
393
- *
394
- * terminate the association
395
- */
396
- VALUE mm_unmap(VALUE obj) {
397
- mm_ipc *i_mm;
398
-
399
- GET_MMAP(obj, i_mm, 0);
400
- if (i_mm->t->path) {
401
- if (munmap(i_mm->t->addr, i_mm->t->len) != 0) {
402
- if (i_mm->t->path != (char *)-1 && i_mm->t->path != NULL) {
403
- free(i_mm->t->path);
404
- i_mm->t->path = NULL;
405
- }
406
-
407
- rb_raise(rb_eRuntimeError, "munmap failed at %s:%d with errno: %d", __FILE__, __LINE__, errno);
408
- }
409
-
410
- if (i_mm->t->path != (char *)-1) {
411
- free(i_mm->t->path);
412
- }
413
-
414
- // Ensure any lingering RString values get a length of zero. We
415
- // can't zero out the address since GET_MMAP() inside
416
- // mm_update_obj_i() expects a non-null address and path.
417
- i_mm->t->len = 0;
418
- i_mm->t->real = 0;
419
- mm_update(obj);
420
-
421
- i_mm->t->addr = NULL;
422
- i_mm->t->path = NULL;
423
- }
424
-
425
- close(i_mm->t->fd);
426
-
427
- return Qnil;
428
- }
@@ -1,61 +0,0 @@
1
- #ifndef MMAP_H
2
- #define MMAP_H
3
-
4
- #include <ruby.h>
5
- #include <unistd.h>
6
-
7
- #define MM_MODIFY 1
8
- #define MM_ORIGIN 2
9
- #define MM_CHANGE (MM_MODIFY | 4)
10
- #define MM_PROTECT 8
11
-
12
- #define MM_FROZEN (1 << 0)
13
- #define MM_FIXED (1 << 1)
14
- #define MM_ANON (1 << 2)
15
- #define MM_LOCK (1 << 3)
16
- #define MM_IPC (1 << 4)
17
- #define MM_TMP (1 << 5)
18
-
19
- #ifndef MMAP_RETTYPE
20
- #define MMAP_RETTYPE void *
21
- #endif
22
-
23
- typedef struct {
24
- MMAP_RETTYPE addr;
25
- int smode, pmode, vscope;
26
- int advice, flag;
27
- VALUE key;
28
- size_t len, real;
29
- off_t offset;
30
- int fd;
31
- char *path;
32
- } mm_mmap;
33
-
34
- typedef struct {
35
- int count;
36
- mm_mmap *t;
37
- } mm_ipc;
38
-
39
- #define GET_MMAP(obj, i_mm, t_modify) \
40
- Data_Get_Struct(obj, mm_ipc, i_mm); \
41
- if (!i_mm->t->path || i_mm->t->fd < 0 || i_mm->t->addr == NULL || i_mm->t->addr == MAP_FAILED) { \
42
- rb_raise(rb_eIOError, "unmapped file"); \
43
- } \
44
- if ((t_modify & MM_MODIFY) && (i_mm->t->flag & MM_FROZEN)) { \
45
- rb_error_frozen("mmap"); \
46
- }
47
-
48
- VALUE mm_s_alloc(VALUE obj);
49
- VALUE mm_s_new(int argc, VALUE *argv, VALUE obj);
50
- VALUE mm_init(VALUE obj, VALUE fname);
51
- VALUE mm_aref_m(int argc, VALUE *argv, VALUE obj);
52
- VALUE mm_msync(int argc, VALUE *argv, VALUE obj);
53
- VALUE mm_unmap(VALUE obj);
54
-
55
- /* If memory is ever reallocated, any allocated Ruby strings that have not been
56
- * garbage collected need to be updated with the new region. If this isn't done,
57
- * iterating over the Ruby object space and accessing the string data will seg fault.
58
- */
59
- void mm_update(VALUE obj);
60
-
61
- #endif
@@ -1,199 +0,0 @@
1
- #include "rendering.h"
2
-
3
- #include <float.h>
4
- #include <jsmn.h>
5
-
6
- #include "file_parsing.h"
7
- #include "globals.h"
8
- #include "utils.h"
9
-
10
- #ifndef DBL_DECIMAL_DIG
11
- #define DBL_DECIMAL_DIG 17
12
- #endif
13
-
14
- #define LABELS_START_OFFSET 4
15
-
16
- static inline int is_valid(const jsmntok_t *token) { return token->start < token->end && token->start >= 0; }
17
- static inline int valid_not_null(const entry_t *entry, const jsmntok_t *token) {
18
- static const char null_s[] = "null";
19
-
20
- if (!is_valid(token)) {
21
- return 0;
22
- }
23
-
24
- if (token->type != JSMN_PRIMITIVE) {
25
- return 1;
26
- }
27
-
28
- size_t token_len = token->end - token->start;
29
-
30
- if (token_len < sizeof(null_s) - 1) {
31
- return 1;
32
- }
33
-
34
- return strncmp(null_s, entry->json + token->start, sizeof(null_s) - 1) != 0;
35
- }
36
-
37
- static inline int append_token(VALUE string, const entry_t *entry, const jsmntok_t *token) {
38
- if (!is_valid(token)) {
39
- save_exception(prom_eParsingError, "parsing failed: %s", entry->json);
40
- return 0;
41
- }
42
-
43
- rb_str_cat(string, entry->json + token->start, token->end - token->start);
44
- return 1;
45
- }
46
-
47
- static int append_labels(VALUE string, const entry_t *entry, const int label_count, const jsmntok_t *tokens) {
48
- if (label_count <= 0) {
49
- if (is_pid_significant(entry)) {
50
- rb_str_cat(string, "{pid=\"", 6);
51
- rb_str_append(string, entry->pid);
52
- rb_str_cat(string, "\"}", 2);
53
- }
54
- return 1;
55
- }
56
-
57
- rb_str_cat(string, "{", 1);
58
-
59
- for (int i = 0; i < label_count; i++) {
60
- int key = LABELS_START_OFFSET + i;
61
- int val = LABELS_START_OFFSET + label_count + 1 + i;
62
-
63
- if (!append_token(string, entry, &tokens[key])) {
64
- return 0;
65
- }
66
- rb_str_cat(string, "=", 1);
67
-
68
- rb_str_cat(string, "\"", 1);
69
- if (valid_not_null(entry, &tokens[val])) {
70
- append_token(string, entry, &tokens[val]);
71
- }
72
- rb_str_cat(string, "\"", 1);
73
-
74
- if (i < label_count - 1) {
75
- rb_str_cat(string, ",", 1);
76
- }
77
- }
78
-
79
- if (is_pid_significant(entry)) {
80
- rb_str_cat(string, ",pid=\"", 6);
81
- rb_str_append(string, entry->pid);
82
- rb_str_cat(string, "\"", 1);
83
- }
84
-
85
- rb_str_cat(string, "}", 1);
86
- return 1;
87
- }
88
-
89
- static int validate_token_count(const int token_count, const entry_t *entry) {
90
- if (token_count < 0) {
91
- save_exception(prom_eParsingError, "too many labels or malformed json: %s", entry->json);
92
- return 0;
93
- }
94
-
95
- if (token_count < LABELS_START_OFFSET) {
96
- save_exception(prom_eParsingError, "malformed json: %s", entry->json);
97
- return 0;
98
- }
99
-
100
- if ((token_count - (LABELS_START_OFFSET + 1)) % 2 != 0) {
101
- save_exception(prom_eParsingError, "mismatched number of labels: %s", entry->json);
102
- return 0;
103
- }
104
-
105
- return 1;
106
- }
107
-
108
- static int append_entry(VALUE string, const entry_t *entry) {
109
- jsmn_parser parser;
110
- jsmn_init(&parser);
111
-
112
- jsmntok_t tokens[200];
113
- jsmntok_t *name_token = &tokens[2];
114
-
115
- int token_count = jsmn_parse(&parser, entry->json, entry->json_size, tokens, sizeof(tokens) / sizeof(tokens[0]));
116
- int label_count = (token_count - (LABELS_START_OFFSET + 1)) / 2;
117
-
118
- //
119
- // Example JSON "['metric', 'name',['label_a','label_b'],['value_a', 'value_b']]"
120
- // will be parsed into following token list:
121
- //
122
- // [ "'metric', 'name',['label_a','label_b'],['value_a', 'value_b']",
123
- // "metric", "name",
124
- // "['label_a','label_b']", "label_a", "label_b",
125
- // "['value_a', 'value_b']", "value_a", "value_b" ]
126
- //
127
- // where 'metric' is the name of the metric, while 'name'
128
- // is in summaries and histograms to store names of "submetrics" like:
129
- // histogram_name_bucket or histogram_name_sum
130
-
131
- if (!validate_token_count(token_count, entry)) {
132
- return 0;
133
- }
134
-
135
- if (!append_token(string, entry, name_token)) {
136
- return 0;
137
- }
138
-
139
- if (!append_labels(string, entry, label_count, tokens)) {
140
- return 0;
141
- }
142
-
143
- char value[255];
144
-
145
- // print value with highest possible precision so that we do not lose any data
146
- int written = snprintf(value, sizeof(value), " %.*g\n", DBL_DECIMAL_DIG, entry->value);
147
- rb_str_cat(string, value, written);
148
-
149
- return 1;
150
- }
151
-
152
- static void append_entry_head(VALUE string, const entry_t *entry) {
153
- static const char help_beg[] = "# HELP ";
154
- static const char help_fin[] = " Multiprocess metric\n";
155
-
156
- rb_str_cat(string, help_beg, sizeof(help_beg) - 1);
157
- rb_str_cat(string, entry->name, entry->name_len);
158
- rb_str_cat(string, help_fin, sizeof(help_fin) - 1);
159
-
160
- static const char type_beg[] = "# TYPE ";
161
-
162
- rb_str_cat(string, type_beg, sizeof(type_beg) - 1);
163
- rb_str_cat(string, entry->name, entry->name_len);
164
- rb_str_cat(string, " ", 1);
165
- rb_str_cat2(string, rb_id2name(entry->type));
166
- rb_str_cat(string, "\n", 1);
167
- }
168
-
169
- static inline int entry_name_equal(const entry_t *a, const entry_t *b) {
170
- if (a == NULL || b == NULL) {
171
- return a == b;
172
- }
173
-
174
- if (a->name_len != b->name_len) {
175
- return 0;
176
- }
177
-
178
- return strncmp(a->name, b->name, a->name_len) == 0;
179
- }
180
-
181
- int entries_to_string(VALUE string, entry_t **sorted_entries, size_t entries_count) {
182
- entry_t *previous = NULL;
183
-
184
- for (size_t i = 0; i < entries_count; i++) {
185
- entry_t *entry = sorted_entries[i];
186
-
187
- // when entry->name changes write metric header
188
- if (!entry_name_equal(previous, entry)) {
189
- previous = entry;
190
- append_entry_head(string, entry);
191
- }
192
-
193
- if (!append_entry(string, entry)) {
194
- return 0;
195
- }
196
- }
197
-
198
- return 1;
199
- }
@@ -1,8 +0,0 @@
1
- #ifndef RENDERING_H
2
- #define RENDERING_H
3
- #include <file_parsing.h>
4
- #include <ruby.h>
5
-
6
- int entries_to_string(VALUE string, entry_t **sorted_entries, size_t entries_count);
7
-
8
- #endif