2
3
#include "log2journal.h"
4
5
-// ----------------------------------------------------------------------------
6
-
7
-static char *rewrite_value(struct log_job *jb, const char *key, XXH64_hash_t hash, const char *value, size_t value_len) {
8
- static __thread char rewritten_value[MAX_VALUE_LEN + 1];
9
-
10
- for (size_t i = 0; i < jb->rewrites.used; i++) {
11
- struct key_rewrite *rw = &jb->rewrites.array[i];
12
-
13
- if (rw->hash == hash && strcmp(rw->key, key) == 0) {
14
- if (!jb_pcre2_match(rw->re, rw->match_data, (char *)value, value_len, false)) {
15
- continue; // No match found, skip to next rewrite rule
16
- }
5
+static inline void send_duplications_for_key(LOG_JOB *jb, HASHED_KEY *k, const char *value, size_t value_len);
6
18
- PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(rw->match_data);
7
+// ----------------------------------------------------------------------------
8
20
- char *buffer = rewritten_value;
21
- size_t buffer_remaining = sizeof(rewritten_value);
9
+const char journal_key_characters_map[256] = {
10
+ // control characters
11
+ [0] = '\0', [1] = '_', [2] = '_', [3] = '_', [4] = '_', [5] = '_', [6] = '_', [7] = '_',
12
+ [8] = '_', [9] = '_', [10] = '_', [11] = '_', [12] = '_', [13] = '_', [14] = '_', [15] = '_',
13
+ [16] = '_', [17] = '_', [18] = '_', [19] = '_', [20] = '_', [21] = '_', [22] = '_', [23] = '_',
14
+ [24] = '_', [25] = '_', [26] = '_', [27] = '_', [28] = '_', [29] = '_', [30] = '_', [31] = '_',
15
+
16
+ // symbols
17
+ [' '] = '_', ['!'] = '_', ['"'] = '_', ['#'] = '_', ['$'] = '_', ['%'] = '_', ['&'] = '_', ['\''] = '_',
18
+ ['('] = '_', [')'] = '_', ['*'] = '_', ['+'] = '_', [','] = '_', ['-'] = '_', ['.'] = '_', ['/'] = '_',
19
+
20
+ // numbers
21
+ ['0'] = '0', ['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4', ['5'] = '5', ['6'] = '6', ['7'] = '7',
22
+ ['8'] = '8', ['9'] = '9',
23
+
24
+ // symbols
25
+ [':'] = '_', [';'] = '_', ['<'] = '_', ['='] = '_', ['>'] = '_', ['?'] = '_', ['@'] = '_',
26
+
27
+ // capitals
28
+ ['A'] = 'A', ['B'] = 'B', ['C'] = 'C', ['D'] = 'D', ['E'] = 'E', ['F'] = 'F', ['G'] = 'G', ['H'] = 'H',
29
+ ['I'] = 'I', ['J'] = 'J', ['K'] = 'K', ['L'] = 'L', ['M'] = 'M', ['N'] = 'N', ['O'] = 'O', ['P'] = 'P',
30
+ ['Q'] = 'Q', ['R'] = 'R', ['S'] = 'S', ['T'] = 'T', ['U'] = 'U', ['V'] = 'V', ['W'] = 'W', ['X'] = 'X',
31
+ ['Y'] = 'Y', ['Z'] = 'Z',
32
+
33
+ // symbols
34
+ ['['] = '_', ['\\'] = '_', [']'] = '_', ['^'] = '_', ['_'] = '_', ['`'] = '_',
35
+
36
+ // lower to upper
37
+ ['a'] = 'A', ['b'] = 'B', ['c'] = 'C', ['d'] = 'D', ['e'] = 'E', ['f'] = 'F', ['g'] = 'G', ['h'] = 'H',
38
+ ['i'] = 'I', ['j'] = 'J', ['k'] = 'K', ['l'] = 'L', ['m'] = 'M', ['n'] = 'N', ['o'] = 'O', ['p'] = 'P',
39
+ ['q'] = 'Q', ['r'] = 'R', ['s'] = 'S', ['t'] = 'T', ['u'] = 'U', ['v'] = 'V', ['w'] = 'W', ['x'] = 'X',
40
+ ['y'] = 'Y', ['z'] = 'Z',
41
+
42
+ // symbols
43
+ ['{'] = '_', ['|'] = '_', ['}'] = '_', ['~'] = '_', [127] = '_', // Delete (DEL)
44
+
45
+ // Extended ASCII characters (128-255) set to underscore
46
+ [128] = '_', [129] = '_', [130] = '_', [131] = '_', [132] = '_', [133] = '_', [134] = '_', [135] = '_',
47
+ [136] = '_', [137] = '_', [138] = '_', [139] = '_', [140] = '_', [141] = '_', [142] = '_', [143] = '_',
48
+ [144] = '_', [145] = '_', [146] = '_', [147] = '_', [148] = '_', [149] = '_', [150] = '_', [151] = '_',
49
+ [152] = '_', [153] = '_', [154] = '_', [155] = '_', [156] = '_', [157] = '_', [158] = '_', [159] = '_',
50
+ [160] = '_', [161] = '_', [162] = '_', [163] = '_', [164] = '_', [165] = '_', [166] = '_', [167] = '_',
51
+ [168] = '_', [169] = '_', [170] = '_', [171] = '_', [172] = '_', [173] = '_', [174] = '_', [175] = '_',
52
+ [176] = '_', [177] = '_', [178] = '_', [179] = '_', [180] = '_', [181] = '_', [182] = '_', [183] = '_',
53
+ [184] = '_', [185] = '_', [186] = '_', [187] = '_', [188] = '_', [189] = '_', [190] = '_', [191] = '_',
54
+ [192] = '_', [193] = '_', [194] = '_', [195] = '_', [196] = '_', [197] = '_', [198] = '_', [199] = '_',
55
+ [200] = '_', [201] = '_', [202] = '_', [203] = '_', [204] = '_', [205] = '_', [206] = '_', [207] = '_',
56
+ [208] = '_', [209] = '_', [210] = '_', [211] = '_', [212] = '_', [213] = '_', [214] = '_', [215] = '_',
57
+ [216] = '_', [217] = '_', [218] = '_', [219] = '_', [220] = '_', [221] = '_', [222] = '_', [223] = '_',
58
+ [224] = '_', [225] = '_', [226] = '_', [227] = '_', [228] = '_', [229] = '_', [230] = '_', [231] = '_',
59
+ [232] = '_', [233] = '_', [234] = '_', [235] = '_', [236] = '_', [237] = '_', [238] = '_', [239] = '_',
60
+ [240] = '_', [241] = '_', [242] = '_', [243] = '_', [244] = '_', [245] = '_', [246] = '_', [247] = '_',
61
+ [248] = '_', [249] = '_', [250] = '_', [251] = '_', [252] = '_', [253] = '_', [254] = '_', [255] = '_',
62
+};
63
23
- // Iterate through the linked list of replacement nodes
24
- for (struct replacement_node *node = rw->nodes; node != NULL; node = node->next) {
25
- if (node->is_variable) {
26
- uint32_t groupnumber = pcre2_substring_number_from_name(rw->re, (PCRE2_SPTR)node->s);
27
- PCRE2_SIZE start_offset = ovector[2 * groupnumber];
28
- PCRE2_SIZE end_offset = ovector[2 * groupnumber + 1];
29
- PCRE2_SIZE length = end_offset - start_offset;
64
+// ----------------------------------------------------------------------------
65
31
- size_t copied = copy_to_buffer(buffer, buffer_remaining, value + start_offset, length);
32
- buffer += copied;
33
- buffer_remaining -= copied;
34
- }
35
- else {
36
- size_t len = node->len;
37
- size_t copied = copy_to_buffer(buffer, buffer_remaining, node->s, len);
38
- buffer += copied;
39
- buffer_remaining -= copied;
66
+static char *rewrite_value(LOG_JOB *jb, HASHED_KEY *k, const char *value, size_t value_len) {
67
+ static __thread char rewritten_value[JOURNAL_MAX_VALUE_LEN + 1];
68
+
69
+ if(!(k->flags & HK_REWRITES_CHECKED) || k->flags & HK_HAS_REWRITES) {
70
+ k->flags |= HK_REWRITES_CHECKED;
71
+
72
+ for(size_t i = 0; i < jb->rewrites.used; i++) {
73
+ REWRITE *rw = &jb->rewrites.array[i];
74
+
75
+ if(rw->key.hash == k->hash && strcmp(rw->key.key, k->key) == 0) {
76
+ if(!search_pattern_matches(&rw->search, value, value_len))
77
+ continue; // No match found, skip to next rewrite rule
78
+
79
+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(rw->search.match_data);
80
+
81
+ char *buffer = rewritten_value;
82
+ size_t buffer_remaining = sizeof(rewritten_value);
83
+
84
+ // Iterate through the linked list of replacement nodes
85
+ for(REPLACE_NODE *node = rw->replace.nodes; node != NULL; node = node->next) {
86
+ if(node->is_variable) {
87
+ int group_number = pcre2_substring_number_from_name(rw->search.re, (PCRE2_SPTR) node->name.key);
88
+ if(group_number >= 0) {
89
+ PCRE2_SIZE start_offset = ovector[2 * group_number];
90
+ PCRE2_SIZE end_offset = ovector[2 * group_number + 1];
91
+ PCRE2_SIZE length = end_offset - start_offset;
92
+
93
+ size_t copied = copy_to_buffer(buffer, buffer_remaining, value + start_offset, length);
94
+ buffer += copied;
95
+ buffer_remaining -= copied;
96
+ }
97
+ else {
98
+ // TODO: lookup in key names to get their values
99
+
100
+ if(!node->logged_error) {
101
+ log2stderr("WARNING: variable '${%s}' in rewrite rule cannot be resolved.",
102
+ node->name.key);
103
+ node->logged_error = true;
104
+ }
105
+ }
106
+ }
107
+ else {
108
+ size_t copied = copy_to_buffer(buffer, buffer_remaining, node->name.key, node->name.len);
109
+ buffer += copied;
110
+ buffer_remaining -= copied;
111
+ }
112
}
41
- }
113
43
- return rewritten_value;
114
+ k->flags |= HK_HAS_REWRITES;
115
+ return rewritten_value;
116
+ }
117
}
118
}
119
120
return NULL;
121
}
122
50
-static inline const char *rename_key(struct log_job *jb, const char *key, XXH64_hash_t hash, XXH64_hash_t *new_hash) {
51
- for(size_t i = 0; i < jb->renames.used ;i++) {
52
- struct key_rename *rn = &jb->renames.array[i];
123
+static inline HASHED_KEY *rename_key(LOG_JOB *jb, HASHED_KEY *k) {
124
+ if(!(k->flags & HK_RENAMES_CHECKED) || k->flags & HK_HAS_RENAMES) {
125
+ k->flags |= HK_RENAMES_CHECKED;
126
54
- if(rn->old_hash == hash && strcmp(rn->old_key, key) == 0) {
55
- *new_hash = rn->new_hash;
56
- return rn->new_key;
127
+ for(size_t i = 0; i < jb->renames.used; i++) {
128
+ RENAME *rn = &jb->renames.array[i];
129
+
130
+ if(rn->old_key.hash == k->hash && strcmp(rn->old_key.key, k->key) == 0) {
131
+ k->flags |= HK_HAS_RENAMES;
132
+ return &rn->new_key;
133
+ }
134
}
135
}
136
60
- *new_hash = hash;
61
- return key;
137
+ return k;
138
}
139
140
// ----------------------------------------------------------------------------
149
printf("\n");
150
}
151
76
-inline void jb_send_key_value_and_rewrite(struct log_job *jb, const char *key, XXH64_hash_t hash, const char *value, size_t len) {
77
- char *rewritten = rewrite_value(jb, key, hash, value, len);
152
+static inline void send_key_value_and_rewrite(LOG_JOB *jb, HASHED_KEY *k, const char *value, size_t len) {
153
+ char *rewritten = rewrite_value(jb, k, value, len);
154
if(!rewritten)
79
- printf("%s=%.*s\n", key, (int)len, value);
155
+ printf("%s=%.*s\n", k->key, (int)len, value);
156
else
81
- printf("%s=%s\n", key, rewritten);
157
+ printf("%s=%s\n", k->key, rewritten);
158
+}
159
+
160
+static inline HASHED_KEY *get_key_from_hashtable(LOG_JOB *jb, const char *key) {
161
+ size_t key_len = strlen(key);
162
+ XXH64_hash_t key_hash = XXH3_64bits(key, key_len);
163
+
164
+ HASHED_KEY *k;
165
+ SIMPLE_HASHTABLE_SLOT *slot = simple_hashtable_get_slot(&jb->hashtable, key_hash, true);
166
+ if(slot->data) {
167
+ k = slot->data;
168
+
169
+ if(!(k->flags & HK_COLLISION_CHECKED)) {
170
+ k->flags |= HK_COLLISION_CHECKED;
171
+
172
+ if(strcmp(k->key, key) != 0)
173
+ log2stderr("Hashtable collision detected on key '%s' (hash %lx) and '%s' (hash %lx). "
174
+ "Please report this to Netdata.",
175
+ k->key, (unsigned long)k->hash, key, (unsigned long)key_hash);
176
+ }
177
+ }
178
+ else {
179
+ k = mallocz(sizeof(HASHED_KEY));
180
+ k->key = strdupz(key);
181
+ k->len = key_len;
182
+ k->hash = key_hash;
183
+ k->flags = HK_ALLOCATED;
184
+
185
+ slot->hash = k->hash;
186
+ slot->data = k;
187
+ jb->hashtable.used++;
188
+ }
189
+
190
+ return k;
191
}
192
84
-inline void jb_send_extracted_key_value(struct log_job *jb, const char *key, const char *value, size_t len) {
85
- XXH64_hash_t hash = XXH3_64bits(key, strlen(key));
193
+inline void log_job_send_extracted_key_value(LOG_JOB *jb, const char *key, const char *value, size_t len) {
194
+ HASHED_KEY *k = get_key_from_hashtable(jb, key);
195
+
196
+ if(!(k->flags & HK_FILTERED)) {
197
+ k->flags |= HK_FILTERED;
198
+
199
+ bool included = jb->filter.include.re ? search_pattern_matches(&jb->filter.include, k->key, k->len) : true;
200
+ bool excluded = jb->filter.exclude.re ? search_pattern_matches(&jb->filter.exclude, k->key, k->len) : false;
201
87
- // process renames (changing the key)
88
- XXH64_hash_t new_hash;
89
- const char *new_key = rename_key(jb, key, hash, &new_hash);
202
+ if(included && !excluded)
203
+ k->flags |= HK_FILTERED_INCLUDED;
204
+ else
205
+ k->flags &= ~HK_FILTERED_INCLUDED;
206
+ }
207
91
- // process rewrites (changing the value)
92
- // and send it to output
93
- jb_send_key_value_and_rewrite(jb, new_key, new_hash, value, len);
208
+ if(k->flags & HK_FILTERED_INCLUDED) {
209
+ // process renames (changing the key)
210
+ HASHED_KEY *nk = rename_key(jb, k);
211
+
212
+ // process rewrites (changing the value)
213
+ // and send it to output
214
+ send_key_value_and_rewrite(jb, nk, value, len);
215
+ }
216
217
// process the duplications (using the original key)
218
// and send them to output
97
- jb_send_duplications_for_key(jb, key, hash, value, len);
219
+ send_duplications_for_key(jb, k, value, len);
220
}
221
100
-static inline void send_key_value_constant(struct log_job *jb, const char *key, const char *value) {
222
+static inline void send_key_value_constant(LOG_JOB *jb __maybe_unused, const char *key, const char *value) {
223
printf("%s=%s\n", key, value);
224
}
225
226
// ----------------------------------------------------------------------------
227
// injection of constant fields
228
107
-static void jb_select_which_injections_should_be_injected_on_unmatched(struct log_job *jb) {
229
+static void select_which_injections_should_be_injected_on_unmatched(LOG_JOB *jb) {
230
// mark all injections to be added to unmatched logs
231
for(size_t i = 0; i < jb->injections.used ; i++)
232
jb->injections.keys[i].on_unmatched = true;
239
240
for(size_t i = 0; i < jb->injections.used ;i++) {
241
for(size_t u = 0; u < jb->unmatched.injections.used ; u++) {
120
- if(strcmp(jb->injections.keys[i].key, jb->unmatched.injections.keys[u].key) == 0)
242
+ if(strcmp(jb->injections.keys[i].key.key, jb->unmatched.injections.keys[u].key.key) == 0)
243
jb->injections.keys[i].on_unmatched = false;
244
}
245
}
247
}
248
249
128
-static inline void jb_finalize_injections(struct log_job *jb, bool line_is_matched) {
250
+static inline void jb_finalize_injections(LOG_JOB *jb, bool line_is_matched) {
251
for (size_t j = 0; j < jb->injections.used; j++) {
252
if(!line_is_matched && !jb->injections.keys[j].on_unmatched)
253
continue;
254
133
- send_key_value_constant(jb, jb->injections.keys[j].key, jb->injections.keys[j].value.s);
255
+ send_key_value_constant(jb, jb->injections.keys[j].key.key, jb->injections.keys[j].value.txt);
256
}
257
}
258
137
-static inline void jb_reset_injections(struct log_job *jb) {
259
+static inline void log_job_duplications_reset(LOG_JOB *jb) {
260
for(size_t d = 0; d < jb->dups.used ; d++) {
139
- struct key_dup *kd = &jb->dups.array[d];
261
+ DUPLICATION *kd = &jb->dups.array[d];
262
kd->exposed = false;
263
264
for(size_t g = 0; g < kd->used ; g++) {
143
- if(kd->values[g].s)
144
- kd->values[g].s[0] = '\0';
265
+ if(kd->values[g].txt)
266
+ kd->values[g].txt[0] = '\0';
267
}
268
}
269
}
271
// ----------------------------------------------------------------------------
272
// duplications
273
152
-inline void jb_send_duplications_for_key(struct log_job *jb, const char *key, XXH64_hash_t hash, const char *value, size_t value_len) {
274
+static inline void send_duplications_for_key(LOG_JOB *jb, HASHED_KEY *k, const char *value, size_t value_len) {
275
// IMPORTANT:
276
// The 'value' may not be NULL terminated and have more data that the value we need
277
156
- for (size_t d = 0; d < jb->dups.used; d++) {
157
- struct key_dup *kd = &jb->dups.array[d];
278
+ if(!(k->flags & HK_DUPS_CHECKED) || k->flags & HK_HAS_DUPS) {
279
+ k->flags |= HK_DUPS_CHECKED;
280
159
- if(kd->exposed || kd->used == 0)
160
- continue;
281
+ for(size_t d = 0; d < jb->dups.used; d++) {
282
+ DUPLICATION *kd = &jb->dups.array[d];
283
+
284
+ if(kd->exposed || kd->used == 0)
285
+ continue;
286
162
- if(kd->used == 1) {
163
- // just one key to be duplicated
164
- if(strcmp(kd->keys[0], key) == 0) {
165
- jb_send_key_value_and_rewrite(jb, kd->target, kd->hash, value, value_len);
166
- kd->exposed = true;
287
+ if(kd->used == 1) {
288
+ // just one key to be duplicated
289
+ if(kd->keys[0].hash == k->hash && strcmp(kd->keys[0].key, k->key) == 0) {
290
+ k->flags |= HK_HAS_DUPS;
291
+ send_key_value_and_rewrite(jb, &kd->target, value, value_len);
292
+ kd->exposed = true;
293
+ }
294
}
168
- }
169
- else {
170
- // multiple keys to be duplicated
171
- for(size_t g = 0; g < kd->used ; g++) {
172
- if(strcmp(kd->keys[g], key) == 0)
173
- txt_replace(&kd->values[g], value, value_len);
295
+ else {
296
+ // multiple keys to be duplicated
297
+ for(size_t g = 0; g < kd->used; g++) {
298
+ if(kd->keys[g].hash == k->hash && strcmp(kd->keys[g].key, k->key) == 0) {
299
+ k->flags |= HK_HAS_DUPS;
300
+ txt_replace(&kd->values[g], value, value_len);
301
+ }
302
+ }
303
}
304
}
305
}
306
}
307
179
-static inline void jb_send_remaining_duplications(struct log_job *jb) {
180
- static __thread char buffer[MAX_VALUE_LEN + 1];
308
+static inline void jb_send_remaining_duplications(LOG_JOB *jb) {
309
+ static __thread char buffer[JOURNAL_MAX_VALUE_LEN + 1];
310
311
// IMPORTANT:
312
// all duplications are exposed, even the ones we haven't found their keys in the source,
313
// so that the output always has the same fields for matched entries.
314
315
for(size_t d = 0; d < jb->dups.used ; d++) {
187
- struct key_dup *kd = &jb->dups.array[d];
316
+ DUPLICATION *kd = &jb->dups.array[d];
317
318
if(kd->exposed || kd->used == 0)
319
continue;
324
325
for(size_t g = 0; g < kd->used ; g++) {
326
if(remaining < 2) {
198
- log2stderr("Warning: duplicated key '%s' cannot fit the values.", kd->target);
327
+ log2stderr("Warning: duplicated key '%s' cannot fit the values.", kd->target.key);
328
break;
329
}
330
334
remaining--;
335
}
336
208
- char *value = (kd->values[g].s && kd->values[g].s[0]) ? kd->values[g].s : "[unavailable]";
337
+ char *value = (kd->values[g].txt && kd->values[g].txt[0]) ? kd->values[g].txt : "[unavailable]";
338
size_t len = strlen(value);
339
size_t copied = copy_to_buffer(s, remaining, value, len);
340
remaining -= copied;
341
s += copied;
342
343
if(copied != len) {
215
- log2stderr("Warning: duplicated key '%s' will have truncated value", jb->dups.array[d].target);
344
+ log2stderr("Warning: duplicated key '%s' will have truncated value", jb->dups.array[d].target.key);
345
break;
346
}
347
}
219
- jb_send_key_value_and_rewrite(jb, kd->target, kd->hash, buffer, s - buffer);
348
+ send_key_value_and_rewrite(jb, &kd->target, buffer, s - buffer);
349
}
350
}
351
352
// ----------------------------------------------------------------------------
353
// filename injection
354
226
-static inline void jb_inject_filename(struct log_job *jb) {
355
+static inline void jb_inject_filename(LOG_JOB *jb) {
356
if (jb->filename.key && jb->filename.current[0])
357
send_key_value_constant(jb, jb->filename.key, jb->filename.current);
358
}
359
231
-static inline bool jb_switched_filename(struct log_job *jb, const char *line, size_t len) {
360
+static inline bool jb_switched_filename(LOG_JOB *jb, const char *line, size_t len) {
361
// IMPORTANT:
362
// Return TRUE when the caller should skip this line (because it is ours).
363
// Unfortunately, we have to consume empty lines too.
387
}
388
389
// ----------------------------------------------------------------------------
261
-// input reading
390
263
-static char *get_next_line(struct log_job *jb, char *buffer, size_t size, size_t *line_length) {
391
+static void simple_hashtable_cleanup_allocated(SIMPLE_HASHTABLE *ht) {
392
+ for(size_t i = 0; i < ht->used ;i++) {
393
+ HASHED_KEY *k = ht->hashtable[i].data;
394
+ if(k && k->flags & HK_ALLOCATED) {
395
+ hashed_key_cleanup(k);
396
+ freez(k);
397
+ ht->hashtable[i].data = NULL;
398
+ ht->hashtable[i].hash = 0;
399
+ }
400
+ }
401
+}
402
+
403
+// ----------------------------------------------------------------------------
404
+// running a job
405
+
406
+static char *get_next_line(LOG_JOB *jb __maybe_unused, char *buffer, size_t size, size_t *line_length) {
407
if(!fgets(buffer, (int)size, stdin)) {
408
*line_length = 0;
409
return NULL;
426
return line;
427
}
428
286
-// ----------------------------------------------------------------------------
287
-
288
-static inline void jb_traverse_pcre2_named_groups_and_send_keys(struct log_job *jb, pcre2_code *re, pcre2_match_data *match_data, char *line) {
289
- PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
290
- uint32_t namecount;
291
- pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &namecount);
292
-
293
- if (namecount > 0) {
294
- PCRE2_SPTR name_table;
295
- pcre2_pattern_info(re, PCRE2_INFO_NAMETABLE, &name_table);
296
- uint32_t name_entry_size;
297
- pcre2_pattern_info(re, PCRE2_INFO_NAMEENTRYSIZE, &name_entry_size);
298
-
299
- const unsigned char *tabptr = name_table;
300
- for (uint32_t i = 0; i < namecount; i++) {
301
- int n = (tabptr[0] << 8) | tabptr[1];
302
- const char *group_name = (const char *)(tabptr + 2);
303
-
304
- PCRE2_SIZE start_offset = ovector[2 * n];
305
- PCRE2_SIZE end_offset = ovector[2 * n + 1];
306
- PCRE2_SIZE group_length = end_offset - start_offset;
307
-
308
- jb_send_extracted_key_value(jb, group_name, line + start_offset, group_length);
309
- tabptr += name_entry_size;
310
- }
311
- }
312
-}
313
-
314
-// ----------------------------------------------------------------------------
315
-
316
-struct log_job log_job = { 0 };
317
-int main(int argc, char *argv[]) {
318
- struct log_job *jb = &log_job;
319
-
320
- if(!parse_log2journal_parameters(jb, argc, argv))
321
- exit(1);
322
-
323
- if(jb->show_config)
324
- log_job_to_yaml(jb);
429
+int log_job_run(LOG_JOB *jb) {
430
+ select_which_injections_should_be_injected_on_unmatched(jb);
431
326
- jb_select_which_injections_should_be_injected_on_unmatched(jb);
432
+ simple_hashtable_init(&jb->hashtable, 32);
433
328
- pcre2_code *pcre2 = NULL;
329
- pcre2_match_data *match_data = NULL;
434
+ PCRE2_STATE *pcre2 = NULL;
435
LOG_JSON_STATE *json = NULL;
436
LOGFMT_STATE *logfmt = NULL;
437
+
438
if(strcmp(jb->pattern, "json") == 0) {
439
json = json_parser_create(jb);
440
}
442
logfmt = logfmt_parser_create(jb);
443
}
444
else {
339
- pcre2 = jb_compile_pcre2_pattern(jb->pattern);
340
- if(!pcre2)
341
- return 1;
342
-
343
- match_data = pcre2_match_data_create_from_pattern(pcre2, NULL);
344
- if(!match_data)
445
+ pcre2 = pcre2_parser_create(jb);
446
+ if(pcre2_has_error(pcre2)) {
447
+ log2stderr("%s", pcre2_parser_error(pcre2));
448
+ pcre2_parser_destroy(pcre2);
449
return 1;
450
+ }
451
}
452
453
char buffer[MAX_LINE_LENGTH];
458
if(jb_switched_filename(jb, line, len))
459
continue;
460
356
- jb_reset_injections(jb);
461
+ log_job_duplications_reset(jb);
462
463
bool line_is_matched;
464
467
else if(logfmt)
468
line_is_matched = logfmt_parse_document(logfmt, line);
469
else
365
- line_is_matched = jb_pcre2_match(pcre2, match_data, line, len, true);
470
+ line_is_matched = pcre2_parse_document(pcre2, line, len);
471
472
if(!line_is_matched) {
473
if(json)
474
log2stderr("%s", json_parser_error(json));
475
else if(logfmt)
476
log2stderr("%s", logfmt_parser_error(logfmt));
477
+ else
478
+ log2stderr("%s", pcre2_parser_error(pcre2));
479
480
if (jb->unmatched.key) {
481
// we are sending errors to systemd-journal
482
send_key_value_error(jb->unmatched.key, "Parsing error on: %s", line);
483
484
for (size_t j = 0; j < jb->unmatched.injections.used; j++)
378
- send_key_value_constant(jb, jb->unmatched.injections.keys[j].key,
379
- jb->unmatched.injections.keys[j].value.s);
485
+ send_key_value_constant(jb, jb->unmatched.injections.keys[j].key.key,
486
+ jb->unmatched.injections.keys[j].value.txt);
487
}
488
else {
489
// we are just logging errors to stderr
491
}
492
}
493
else {
387
- if(pcre2)
388
- jb_traverse_pcre2_named_groups_and_send_keys(jb, pcre2, match_data, line);
389
-
494
// print all non-exposed duplications
495
jb_send_remaining_duplications(jb);
496
}
508
else if(logfmt)
509
logfmt_parser_destroy(logfmt);
510
407
- else if(pcre2) {
408
- pcre2_match_data_free(match_data);
409
- pcre2_code_free(pcre2);
410
- }
511
+ else if(pcre2)
512
+ pcre2_parser_destroy(pcre2);
513
+
514
+ simple_hashtable_cleanup_allocated(&jb->hashtable);
515
+ simple_hashtable_free(&jb->hashtable);
516
412
- nd_log_destroy(jb);
517
return 0;
518
}
519
+
520
+// ----------------------------------------------------------------------------
521
+
522
+int main(int argc, char *argv[]) {
523
+ LOG_JOB log_job = { 0 };
524
+
525
+ if(!log_job_command_line_parse_parameters(&log_job, argc, argv))
526
+ exit(1);
527
+
528
+ if(log_job.show_config)
529
+ log_job_configuration_to_yaml(&log_job);
530
+
531
+ int ret = log_job_run(&log_job);
532
+
533
+ nd_log_cleanup(&log_job);
534
+ return ret;
535
+}