937331a36a315a533be2c161b7e571c2ed7023a8
[lttng-tools.git] / src / common / event-rule / log4j-logging.cpp
1 /*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/credentials.hpp>
9 #include <common/error.hpp>
10 #include <common/hashtable/hashtable.hpp>
11 #include <common/hashtable/utils.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <common/optional.hpp>
15 #include <common/payload-view.hpp>
16 #include <common/payload.hpp>
17 #include <common/runas.hpp>
18 #include <common/string-utils/string-utils.hpp>
19 #include <lttng/event-rule/event-rule-internal.hpp>
20 #include <lttng/event-rule/log4j-logging-internal.hpp>
21 #include <lttng/event.h>
22 #include <lttng/log-level-rule.h>
23
24 #define IS_LOG4J_LOGGING_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING)
26
27 static void lttng_event_rule_log4j_logging_destroy(struct lttng_event_rule *rule)
28 {
29 struct lttng_event_rule_log4j_logging *log4j_logging;
30
31 if (rule == NULL) {
32 return;
33 }
34
35 log4j_logging = container_of(
36 rule, struct lttng_event_rule_log4j_logging, parent);
37
38 lttng_log_level_rule_destroy(log4j_logging->log_level_rule);
39 free(log4j_logging->pattern);
40 free(log4j_logging->filter_expression);
41 free(log4j_logging->internal_filter.filter);
42 free(log4j_logging->internal_filter.bytecode);
43 free(log4j_logging);
44 }
45
46 static bool lttng_event_rule_log4j_logging_validate(
47 const struct lttng_event_rule *rule)
48 {
49 bool valid = false;
50 struct lttng_event_rule_log4j_logging *log4j_logging;
51
52 if (!rule) {
53 goto end;
54 }
55
56 log4j_logging = container_of(
57 rule, struct lttng_event_rule_log4j_logging, parent);
58
59 /* Required field. */
60 if (!log4j_logging->pattern) {
61 ERR("Invalid log4j_logging event rule: a pattern must be set.");
62 goto end;
63 }
64
65 valid = true;
66 end:
67 return valid;
68 }
69
70 static int lttng_event_rule_log4j_logging_serialize(
71 const struct lttng_event_rule *rule,
72 struct lttng_payload *payload)
73 {
74 int ret;
75 size_t pattern_len, filter_expression_len, header_offset;
76 size_t size_before_log_level_rule;
77 struct lttng_event_rule_log4j_logging *log4j_logging;
78 struct lttng_event_rule_log4j_logging_comm log4j_logging_comm;
79 struct lttng_event_rule_log4j_logging_comm *header;
80
81 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule)) {
82 ret = -1;
83 goto end;
84 }
85
86 header_offset = payload->buffer.size;
87
88 DBG("Serializing log4j_logging event rule.");
89 log4j_logging = container_of(
90 rule, struct lttng_event_rule_log4j_logging, parent);
91
92 pattern_len = strlen(log4j_logging->pattern) + 1;
93
94 if (log4j_logging->filter_expression != NULL) {
95 filter_expression_len =
96 strlen(log4j_logging->filter_expression) + 1;
97 } else {
98 filter_expression_len = 0;
99 }
100
101 log4j_logging_comm.pattern_len = pattern_len;
102 log4j_logging_comm.filter_expression_len = filter_expression_len;
103
104 ret = lttng_dynamic_buffer_append(&payload->buffer, &log4j_logging_comm,
105 sizeof(log4j_logging_comm));
106 if (ret) {
107 goto end;
108 }
109
110 ret = lttng_dynamic_buffer_append(
111 &payload->buffer, log4j_logging->pattern, pattern_len);
112 if (ret) {
113 goto end;
114 }
115
116 ret = lttng_dynamic_buffer_append(&payload->buffer, log4j_logging->filter_expression,
117 filter_expression_len);
118 if (ret) {
119 goto end;
120 }
121
122 size_before_log_level_rule = payload->buffer.size;
123
124 ret = lttng_log_level_rule_serialize(log4j_logging->log_level_rule, payload);
125 if (ret < 0) {
126 goto end;
127 }
128
129 header = (typeof(header)) ((char *) payload->buffer.data + header_offset);
130 header->log_level_rule_len =
131 payload->buffer.size - size_before_log_level_rule;
132
133 end:
134 return ret;
135 }
136
137 static bool lttng_event_rule_log4j_logging_is_equal(
138 const struct lttng_event_rule *_a,
139 const struct lttng_event_rule *_b)
140 {
141 bool is_equal = false;
142 struct lttng_event_rule_log4j_logging *a, *b;
143
144 a = container_of(_a, struct lttng_event_rule_log4j_logging, parent);
145 b = container_of(_b, struct lttng_event_rule_log4j_logging, parent);
146
147 /* Quick checks. */
148
149 if (!!a->filter_expression != !!b->filter_expression) {
150 goto end;
151 }
152
153 /* Long check. */
154 LTTNG_ASSERT(a->pattern);
155 LTTNG_ASSERT(b->pattern);
156 if (strcmp(a->pattern, b->pattern)) {
157 goto end;
158 }
159
160 if (a->filter_expression && b->filter_expression) {
161 if (strcmp(a->filter_expression, b->filter_expression)) {
162 goto end;
163 }
164 } else if (!!a->filter_expression != !!b->filter_expression) {
165 /* One is set; not the other. */
166 goto end;
167 }
168
169 if (!lttng_log_level_rule_is_equal(
170 a->log_level_rule, b->log_level_rule)) {
171 goto end;
172 }
173
174 is_equal = true;
175 end:
176 return is_equal;
177 }
178
179 /*
180 * On success ret is 0;
181 *
182 * On error ret is negative.
183 *
184 * An event with NO loglevel and the name is * will return NULL.
185 */
186 static int generate_agent_filter(
187 const struct lttng_event_rule *rule, char **_agent_filter)
188 {
189 int err;
190 int ret = 0;
191 char *agent_filter = NULL;
192 const char *pattern;
193 const char *filter;
194 const struct lttng_log_level_rule *log_level_rule = NULL;
195 enum lttng_event_rule_status status;
196
197 LTTNG_ASSERT(rule);
198 LTTNG_ASSERT(_agent_filter);
199
200 status = lttng_event_rule_log4j_logging_get_name_pattern(rule, &pattern);
201 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
202 ret = -1;
203 goto end;
204 }
205
206 status = lttng_event_rule_log4j_logging_get_filter(rule, &filter);
207 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
208 filter = NULL;
209 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
210 ret = -1;
211 goto end;
212 }
213
214
215 /* Don't add filter for the '*' event. */
216 if (strcmp(pattern, "*") != 0) {
217 if (filter) {
218 err = asprintf(&agent_filter,
219 "(%s) && (logger_name == \"%s\")",
220 filter, pattern);
221 } else {
222 err = asprintf(&agent_filter, "logger_name == \"%s\"",
223 pattern);
224 }
225
226 if (err < 0) {
227 PERROR("Failed to format agent filter string");
228 ret = -1;
229 goto end;
230 }
231 }
232
233 status = lttng_event_rule_log4j_logging_get_log_level_rule(
234 rule, &log_level_rule);
235 if (status == LTTNG_EVENT_RULE_STATUS_OK) {
236 enum lttng_log_level_rule_status llr_status;
237 const char *op;
238 int level;
239
240 switch (lttng_log_level_rule_get_type(log_level_rule))
241 {
242 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
243 llr_status = lttng_log_level_rule_exactly_get_level(
244 log_level_rule, &level);
245 op = "==";
246 break;
247 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
248 llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
249 log_level_rule, &level);
250 op = ">=";
251 break;
252 default:
253 abort();
254 }
255
256 if (llr_status != LTTNG_LOG_LEVEL_RULE_STATUS_OK) {
257 ret = -1;
258 goto end;
259 }
260
261 if (filter || agent_filter) {
262 char *new_filter;
263
264 err = asprintf(&new_filter,
265 "(%s) && (int_loglevel %s %d)",
266 agent_filter ? agent_filter : filter,
267 op, level);
268 if (agent_filter) {
269 free(agent_filter);
270 }
271 agent_filter = new_filter;
272 } else {
273 err = asprintf(&agent_filter, "int_loglevel %s %d", op,
274 level);
275 }
276
277 if (err < 0) {
278 PERROR("Failed to format agent filter string");
279 ret = -1;
280 goto end;
281 }
282 }
283
284 *_agent_filter = agent_filter;
285 agent_filter = NULL;
286
287 end:
288 free(agent_filter);
289 return ret;
290 }
291
292 static enum lttng_error_code
293 lttng_event_rule_log4j_logging_generate_filter_bytecode(
294 struct lttng_event_rule *rule,
295 const struct lttng_credentials *creds)
296 {
297 int ret;
298 enum lttng_error_code ret_code;
299 struct lttng_event_rule_log4j_logging *log4j_logging;
300 enum lttng_event_rule_status status;
301 const char *filter;
302 struct lttng_bytecode *bytecode = NULL;
303 char *agent_filter;
304
305 LTTNG_ASSERT(rule);
306
307 log4j_logging = container_of(
308 rule, struct lttng_event_rule_log4j_logging, parent);
309
310 status = lttng_event_rule_log4j_logging_get_filter(rule, &filter);
311 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
312 filter = NULL;
313 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
314 ret_code = LTTNG_ERR_FILTER_INVAL;
315 goto end;
316 }
317
318 if (filter && filter[0] == '\0') {
319 ret_code = LTTNG_ERR_FILTER_INVAL;
320 goto error;
321 }
322
323 ret = generate_agent_filter(rule, &agent_filter);
324 if (ret) {
325 ret_code = LTTNG_ERR_FILTER_INVAL;
326 goto error;
327 }
328
329 log4j_logging->internal_filter.filter = agent_filter;
330
331 if (log4j_logging->internal_filter.filter == NULL) {
332 ret_code = LTTNG_OK;
333 goto end;
334 }
335
336 ret = run_as_generate_filter_bytecode(
337 log4j_logging->internal_filter.filter, creds,
338 &bytecode);
339 if (ret) {
340 ret_code = LTTNG_ERR_FILTER_INVAL;
341 goto end;
342 }
343
344 log4j_logging->internal_filter.bytecode = bytecode;
345 bytecode = NULL;
346 ret_code = LTTNG_OK;
347
348 error:
349 end:
350 free(bytecode);
351 return ret_code;
352 }
353
354 static const char *lttng_event_rule_log4j_logging_get_internal_filter(
355 const struct lttng_event_rule *rule)
356 {
357 struct lttng_event_rule_log4j_logging *log4j_logging;
358
359 LTTNG_ASSERT(rule);
360 log4j_logging = container_of(
361 rule, struct lttng_event_rule_log4j_logging, parent);
362 return log4j_logging->internal_filter.filter;
363 }
364
365 static const struct lttng_bytecode *
366 lttng_event_rule_log4j_logging_get_internal_filter_bytecode(
367 const struct lttng_event_rule *rule)
368 {
369 struct lttng_event_rule_log4j_logging *log4j_logging;
370
371 LTTNG_ASSERT(rule);
372 log4j_logging = container_of(
373 rule, struct lttng_event_rule_log4j_logging, parent);
374 return log4j_logging->internal_filter.bytecode;
375 }
376
377 static enum lttng_event_rule_generate_exclusions_status
378 lttng_event_rule_log4j_logging_generate_exclusions(
379 const struct lttng_event_rule *rule __attribute__((unused)),
380 struct lttng_event_exclusion **_exclusions)
381 {
382 /* Unsupported. */
383 *_exclusions = NULL;
384 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
385 }
386
387 static unsigned long lttng_event_rule_log4j_logging_hash(
388 const struct lttng_event_rule *rule)
389 {
390 unsigned long hash;
391 struct lttng_event_rule_log4j_logging *tp_rule =
392 container_of(rule, typeof(*tp_rule), parent);
393
394 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING,
395 lttng_ht_seed);
396 hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
397
398 if (tp_rule->filter_expression) {
399 hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
400 }
401
402 if (tp_rule->log_level_rule) {
403 hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
404 }
405
406 return hash;
407 }
408
409 static struct lttng_event *lttng_event_rule_log4j_logging_generate_lttng_event(
410 const struct lttng_event_rule *rule)
411 {
412 int ret;
413 const struct lttng_event_rule_log4j_logging *log4j_logging;
414 struct lttng_event *local_event = NULL;
415 struct lttng_event *event = NULL;
416 enum lttng_loglevel_type loglevel_type;
417 int loglevel_value = 0;
418 enum lttng_event_rule_status status;
419 const struct lttng_log_level_rule *log_level_rule;
420
421 log4j_logging = container_of(
422 rule, const struct lttng_event_rule_log4j_logging, parent);
423
424 local_event = (lttng_event *) zmalloc(sizeof(*local_event));
425 if (!local_event) {
426 goto error;
427 }
428
429 local_event->type = LTTNG_EVENT_TRACEPOINT;
430 ret = lttng_strncpy(local_event->name, log4j_logging->pattern,
431 sizeof(local_event->name));
432 if (ret) {
433 ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
434 log4j_logging->pattern);
435 goto error;
436 }
437
438
439 /* Map the log level rule to an equivalent lttng_loglevel. */
440 status = lttng_event_rule_log4j_logging_get_log_level_rule(
441 rule, &log_level_rule);
442 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
443 loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
444 loglevel_value = 0;
445 } else if (status == LTTNG_EVENT_RULE_STATUS_OK) {
446 enum lttng_log_level_rule_status llr_status;
447
448 switch (lttng_log_level_rule_get_type(log_level_rule)) {
449 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
450 llr_status = lttng_log_level_rule_exactly_get_level(
451 log_level_rule, &loglevel_value);
452 loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
453 break;
454 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
455 llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
456 log_level_rule, &loglevel_value);
457 loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
458 break;
459 default:
460 abort();
461 break;
462 }
463
464 if (llr_status != LTTNG_LOG_LEVEL_RULE_STATUS_OK) {
465 goto error;
466 }
467 } else {
468 goto error;
469 }
470
471 local_event->loglevel_type = loglevel_type;
472 local_event->loglevel = loglevel_value;
473
474 event = local_event;
475 local_event = NULL;
476 error:
477 free(local_event);
478 return event;
479 }
480
481 static enum lttng_error_code lttng_event_rule_log4j_logging_mi_serialize(
482 const struct lttng_event_rule *rule, struct mi_writer *writer)
483 {
484 int ret;
485 enum lttng_error_code ret_code;
486 enum lttng_event_rule_status status;
487 const char *filter = NULL;
488 const char *name_pattern = NULL;
489 const struct lttng_log_level_rule *log_level_rule = NULL;
490
491 LTTNG_ASSERT(rule);
492 LTTNG_ASSERT(writer);
493 LTTNG_ASSERT(IS_LOG4J_LOGGING_EVENT_RULE(rule));
494
495 status = lttng_event_rule_log4j_logging_get_name_pattern(
496 rule, &name_pattern);
497 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
498 LTTNG_ASSERT(name_pattern);
499
500 status = lttng_event_rule_log4j_logging_get_filter(rule, &filter);
501 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
502 status == LTTNG_EVENT_RULE_STATUS_UNSET);
503
504 status = lttng_event_rule_log4j_logging_get_log_level_rule(
505 rule, &log_level_rule);
506 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
507 status == LTTNG_EVENT_RULE_STATUS_UNSET);
508
509 /* Open event rule log4j logging element. */
510 ret = mi_lttng_writer_open_element(
511 writer, mi_lttng_element_event_rule_log4j_logging);
512 if (ret) {
513 goto mi_error;
514 }
515
516 /* Name pattern. */
517 ret = mi_lttng_writer_write_element_string(writer,
518 mi_lttng_element_event_rule_name_pattern, name_pattern);
519 if (ret) {
520 goto mi_error;
521 }
522
523 /* Filter expression. */
524 if (filter != NULL) {
525 ret = mi_lttng_writer_write_element_string(writer,
526 mi_lttng_element_event_rule_filter_expression,
527 filter);
528 if (ret) {
529 goto mi_error;
530 }
531 }
532
533 /* Log level rule. */
534 if (log_level_rule) {
535 ret_code = lttng_log_level_rule_mi_serialize(
536 log_level_rule, writer);
537 if (ret_code != LTTNG_OK) {
538 goto end;
539 }
540 }
541
542 /* Close event rule log4j logging element. */
543 ret = mi_lttng_writer_close_element(writer);
544 if (ret) {
545 goto mi_error;
546 }
547
548 ret_code = LTTNG_OK;
549 goto end;
550
551 mi_error:
552 ret_code = LTTNG_ERR_MI_IO_FAIL;
553 end:
554 return ret_code;
555 }
556
557 struct lttng_event_rule *lttng_event_rule_log4j_logging_create(void)
558 {
559 struct lttng_event_rule *rule = NULL;
560 struct lttng_event_rule_log4j_logging *tp_rule;
561 enum lttng_event_rule_status status;
562
563 tp_rule = (lttng_event_rule_log4j_logging *) zmalloc(sizeof(struct lttng_event_rule_log4j_logging));
564 if (!tp_rule) {
565 goto end;
566 }
567
568 rule = &tp_rule->parent;
569 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING);
570 tp_rule->parent.validate = lttng_event_rule_log4j_logging_validate;
571 tp_rule->parent.serialize = lttng_event_rule_log4j_logging_serialize;
572 tp_rule->parent.equal = lttng_event_rule_log4j_logging_is_equal;
573 tp_rule->parent.destroy = lttng_event_rule_log4j_logging_destroy;
574 tp_rule->parent.generate_filter_bytecode =
575 lttng_event_rule_log4j_logging_generate_filter_bytecode;
576 tp_rule->parent.get_filter =
577 lttng_event_rule_log4j_logging_get_internal_filter;
578 tp_rule->parent.get_filter_bytecode =
579 lttng_event_rule_log4j_logging_get_internal_filter_bytecode;
580 tp_rule->parent.generate_exclusions =
581 lttng_event_rule_log4j_logging_generate_exclusions;
582 tp_rule->parent.hash = lttng_event_rule_log4j_logging_hash;
583 tp_rule->parent.generate_lttng_event =
584 lttng_event_rule_log4j_logging_generate_lttng_event;
585 tp_rule->parent.mi_serialize = lttng_event_rule_log4j_logging_mi_serialize;
586
587 tp_rule->log_level_rule = NULL;
588
589 /* Default pattern is '*'. */
590 status = lttng_event_rule_log4j_logging_set_name_pattern(rule, "*");
591 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
592 lttng_event_rule_destroy(rule);
593 rule = NULL;
594 }
595
596 end:
597 return rule;
598 }
599
600 ssize_t lttng_event_rule_log4j_logging_create_from_payload(
601 struct lttng_payload_view *view,
602 struct lttng_event_rule **_event_rule)
603 {
604 ssize_t ret, offset = 0;
605 enum lttng_event_rule_status status;
606 const struct lttng_event_rule_log4j_logging_comm *log4j_logging_comm;
607 const char *pattern;
608 const char *filter_expression = NULL;
609 struct lttng_buffer_view current_buffer_view;
610 struct lttng_event_rule *rule = NULL;
611 struct lttng_log_level_rule *log_level_rule = NULL;
612
613 if (!_event_rule) {
614 ret = -1;
615 goto end;
616 }
617
618 current_buffer_view = lttng_buffer_view_from_view(
619 &view->buffer, offset, sizeof(*log4j_logging_comm));
620 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
621 ERR("Failed to initialize from malformed event rule log4j_logging: buffer too short to contain header.");
622 ret = -1;
623 goto end;
624 }
625
626 log4j_logging_comm = (typeof(log4j_logging_comm)) current_buffer_view.data;
627
628 rule = lttng_event_rule_log4j_logging_create();
629 if (!rule) {
630 ERR("Failed to create event rule log4j_logging.");
631 ret = -1;
632 goto end;
633 }
634
635 /* Skip to payload. */
636 offset += current_buffer_view.size;
637
638 /* Map the pattern. */
639 current_buffer_view = lttng_buffer_view_from_view(
640 &view->buffer, offset, log4j_logging_comm->pattern_len);
641
642 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
643 ret = -1;
644 goto end;
645 }
646
647 pattern = current_buffer_view.data;
648 if (!lttng_buffer_view_contains_string(&current_buffer_view, pattern,
649 log4j_logging_comm->pattern_len)) {
650 ret = -1;
651 goto end;
652 }
653
654 /* Skip after the pattern. */
655 offset += log4j_logging_comm->pattern_len;
656
657 if (!log4j_logging_comm->filter_expression_len) {
658 goto skip_filter_expression;
659 }
660
661 /* Map the filter_expression. */
662 current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
663 log4j_logging_comm->filter_expression_len);
664 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
665 ret = -1;
666 goto end;
667 }
668
669 filter_expression = current_buffer_view.data;
670 if (!lttng_buffer_view_contains_string(&current_buffer_view,
671 filter_expression,
672 log4j_logging_comm->filter_expression_len)) {
673 ret = -1;
674 goto end;
675 }
676
677 /* Skip after the pattern. */
678 offset += log4j_logging_comm->filter_expression_len;
679
680 skip_filter_expression:
681 if (!log4j_logging_comm->log_level_rule_len) {
682 goto skip_log_level_rule;
683 }
684
685 {
686 /* Map the log level rule. */
687 struct lttng_payload_view current_payload_view =
688 lttng_payload_view_from_view(view, offset,
689 log4j_logging_comm->log_level_rule_len);
690
691 ret = lttng_log_level_rule_create_from_payload(
692 &current_payload_view, &log_level_rule);
693 if (ret < 0) {
694 ret = -1;
695 goto end;
696 }
697
698 LTTNG_ASSERT(ret == log4j_logging_comm->log_level_rule_len);
699 }
700
701 /* Skip after the log level rule. */
702 offset += log4j_logging_comm->log_level_rule_len;
703
704 skip_log_level_rule:
705
706 status = lttng_event_rule_log4j_logging_set_name_pattern(rule, pattern);
707 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
708 ERR("Failed to set event rule log4j_logging pattern.");
709 ret = -1;
710 goto end;
711 }
712
713 if (filter_expression) {
714 status = lttng_event_rule_log4j_logging_set_filter(
715 rule, filter_expression);
716 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
717 ERR("Failed to set event rule log4j_logging pattern.");
718 ret = -1;
719 goto end;
720 }
721 }
722
723 if (log_level_rule) {
724 status = lttng_event_rule_log4j_logging_set_log_level_rule(
725 rule, log_level_rule);
726 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
727 ERR("Failed to set event rule log4j_logging log level rule.");
728 ret = -1;
729 goto end;
730 }
731 }
732
733 *_event_rule = rule;
734 rule = NULL;
735 ret = offset;
736 end:
737 lttng_log_level_rule_destroy(log_level_rule);
738 lttng_event_rule_destroy(rule);
739 return ret;
740 }
741
742 enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_name_pattern(
743 struct lttng_event_rule *rule, const char *pattern)
744 {
745 char *pattern_copy = NULL;
746 struct lttng_event_rule_log4j_logging *log4j_logging;
747 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
748
749 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule) || !pattern ||
750 strlen(pattern) == 0) {
751 status = LTTNG_EVENT_RULE_STATUS_INVALID;
752 goto end;
753 }
754
755 log4j_logging = container_of(
756 rule, struct lttng_event_rule_log4j_logging, parent);
757 pattern_copy = strdup(pattern);
758 if (!pattern_copy) {
759 status = LTTNG_EVENT_RULE_STATUS_ERROR;
760 goto end;
761 }
762
763 /* Normalize the pattern. */
764 strutils_normalize_star_glob_pattern(pattern_copy);
765
766 free(log4j_logging->pattern);
767
768 log4j_logging->pattern = pattern_copy;
769 pattern_copy = NULL;
770 end:
771 return status;
772 }
773
774 enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_name_pattern(
775 const struct lttng_event_rule *rule, const char **pattern)
776 {
777 struct lttng_event_rule_log4j_logging *log4j_logging;
778 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
779
780 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule) || !pattern) {
781 status = LTTNG_EVENT_RULE_STATUS_INVALID;
782 goto end;
783 }
784
785 log4j_logging = container_of(
786 rule, struct lttng_event_rule_log4j_logging, parent);
787 if (!log4j_logging->pattern) {
788 status = LTTNG_EVENT_RULE_STATUS_UNSET;
789 goto end;
790 }
791
792 *pattern = log4j_logging->pattern;
793 end:
794 return status;
795 }
796
797 enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_filter(
798 struct lttng_event_rule *rule, const char *expression)
799 {
800 char *expression_copy = NULL;
801 struct lttng_event_rule_log4j_logging *log4j_logging;
802 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
803
804 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule) || !expression ||
805 strlen(expression) == 0) {
806 status = LTTNG_EVENT_RULE_STATUS_INVALID;
807 goto end;
808 }
809
810 log4j_logging = container_of(
811 rule, struct lttng_event_rule_log4j_logging, parent);
812 expression_copy = strdup(expression);
813 if (!expression_copy) {
814 PERROR("Failed to copy filter expression");
815 status = LTTNG_EVENT_RULE_STATUS_ERROR;
816 goto end;
817 }
818
819 if (log4j_logging->filter_expression) {
820 free(log4j_logging->filter_expression);
821 }
822
823 log4j_logging->filter_expression = expression_copy;
824 expression_copy = NULL;
825 end:
826 return status;
827 }
828
829 enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_filter(
830 const struct lttng_event_rule *rule, const char **expression)
831 {
832 struct lttng_event_rule_log4j_logging *log4j_logging;
833 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
834
835 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule) || !expression) {
836 status = LTTNG_EVENT_RULE_STATUS_INVALID;
837 goto end;
838 }
839
840 log4j_logging = container_of(
841 rule, struct lttng_event_rule_log4j_logging, parent);
842 if (!log4j_logging->filter_expression) {
843 status = LTTNG_EVENT_RULE_STATUS_UNSET;
844 goto end;
845 }
846
847 *expression = log4j_logging->filter_expression;
848 end:
849 return status;
850 }
851
852 static bool log_level_rule_valid(
853 const struct lttng_log_level_rule *rule __attribute__((unused)))
854 {
855 /*
856 * For both LOG4J custom log level are possible and can
857 * span the entire int32 range.
858 */
859 return true;
860 }
861
862 enum lttng_event_rule_status lttng_event_rule_log4j_logging_set_log_level_rule(
863 struct lttng_event_rule *rule,
864 const struct lttng_log_level_rule *log_level_rule)
865 {
866 struct lttng_event_rule_log4j_logging *log4j_logging;
867 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
868 struct lttng_log_level_rule *copy = NULL;
869
870 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule)) {
871 status = LTTNG_EVENT_RULE_STATUS_INVALID;
872 goto end;
873 }
874
875 log4j_logging = container_of(
876 rule, struct lttng_event_rule_log4j_logging, parent);
877
878 if (!log_level_rule_valid(log_level_rule)) {
879 status = LTTNG_EVENT_RULE_STATUS_INVALID;
880 goto end;
881 }
882
883 copy = lttng_log_level_rule_copy(log_level_rule);
884 if (copy == NULL) {
885 status = LTTNG_EVENT_RULE_STATUS_ERROR;
886 goto end;
887 }
888
889 if (log4j_logging->log_level_rule) {
890 lttng_log_level_rule_destroy(log4j_logging->log_level_rule);
891 }
892
893 log4j_logging->log_level_rule = copy;
894
895 end:
896 return status;
897 }
898
899 enum lttng_event_rule_status lttng_event_rule_log4j_logging_get_log_level_rule(
900 const struct lttng_event_rule *rule,
901 const struct lttng_log_level_rule **log_level_rule
902 )
903 {
904 struct lttng_event_rule_log4j_logging *log4j_logging;
905 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
906
907 if (!rule || !IS_LOG4J_LOGGING_EVENT_RULE(rule) || !log_level_rule) {
908 status = LTTNG_EVENT_RULE_STATUS_INVALID;
909 goto end;
910 }
911
912 log4j_logging = container_of(
913 rule, struct lttng_event_rule_log4j_logging, parent);
914 if (log4j_logging->log_level_rule == NULL) {
915 status = LTTNG_EVENT_RULE_STATUS_UNSET;
916 goto end;
917 }
918
919 *log_level_rule = log4j_logging->log_level_rule;
920 end:
921 return status;
922 }
This page took 0.048265 seconds and 4 git commands to generate.