2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
10 #include <common/error.h>
11 #include <common/macros.h>
12 #include <common/optional.h>
13 #include <common/payload.h>
14 #include <common/payload-view.h>
15 #include <common/runas.h>
16 #include <common/hashtable/hashtable.h>
17 #include <common/hashtable/utils.h>
18 #include <common/string-utils/string-utils.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/python-logging-internal.h>
21 #include <lttng/log-level-rule.h>
22 #include <lttng/event.h>
24 #define IS_PYTHON_LOGGING_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING)
27 static void lttng_event_rule_python_logging_destroy(struct lttng_event_rule
*rule
)
29 struct lttng_event_rule_python_logging
*python_logging
;
35 python_logging
= container_of(
36 rule
, struct lttng_event_rule_python_logging
, parent
);
38 lttng_log_level_rule_destroy(python_logging
->log_level_rule
);
39 free(python_logging
->pattern
);
40 free(python_logging
->filter_expression
);
41 free(python_logging
->internal_filter
.filter
);
42 free(python_logging
->internal_filter
.bytecode
);
46 static bool lttng_event_rule_python_logging_validate(
47 const struct lttng_event_rule
*rule
)
50 struct lttng_event_rule_python_logging
*python_logging
;
56 python_logging
= container_of(
57 rule
, struct lttng_event_rule_python_logging
, parent
);
60 if (!python_logging
->pattern
) {
61 ERR("Invalid python_logging event rule: a pattern must be set.");
70 static int lttng_event_rule_python_logging_serialize(
71 const struct lttng_event_rule
*rule
,
72 struct lttng_payload
*payload
)
75 size_t pattern_len
, filter_expression_len
, header_offset
;
76 size_t size_before_log_level_rule
;
77 struct lttng_event_rule_python_logging
*python_logging
;
78 struct lttng_event_rule_python_logging_comm python_logging_comm
;
79 struct lttng_event_rule_python_logging_comm
*header
;
81 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
)) {
86 header_offset
= payload
->buffer
.size
;
88 DBG("Serializing python_logging event rule.");
89 python_logging
= container_of(
90 rule
, struct lttng_event_rule_python_logging
, parent
);
92 pattern_len
= strlen(python_logging
->pattern
) + 1;
94 if (python_logging
->filter_expression
!= NULL
) {
95 filter_expression_len
=
96 strlen(python_logging
->filter_expression
) + 1;
98 filter_expression_len
= 0;
101 python_logging_comm
.pattern_len
= pattern_len
;
102 python_logging_comm
.filter_expression_len
= filter_expression_len
;
104 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &python_logging_comm
,
105 sizeof(python_logging_comm
));
110 ret
= lttng_dynamic_buffer_append(
111 &payload
->buffer
, python_logging
->pattern
, pattern_len
);
116 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, python_logging
->filter_expression
,
117 filter_expression_len
);
122 size_before_log_level_rule
= payload
->buffer
.size
;
124 ret
= lttng_log_level_rule_serialize(python_logging
->log_level_rule
, payload
);
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
;
137 static bool lttng_event_rule_python_logging_is_equal(
138 const struct lttng_event_rule
*_a
,
139 const struct lttng_event_rule
*_b
)
141 bool is_equal
= false;
142 struct lttng_event_rule_python_logging
*a
, *b
;
144 a
= container_of(_a
, struct lttng_event_rule_python_logging
, parent
);
145 b
= container_of(_b
, struct lttng_event_rule_python_logging
, parent
);
149 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
156 if (strcmp(a
->pattern
, b
->pattern
)) {
160 if (a
->filter_expression
&& b
->filter_expression
) {
161 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
164 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
165 /* One is set; not the other. */
169 if (!lttng_log_level_rule_is_equal(
170 a
->log_level_rule
, b
->log_level_rule
)) {
180 * On success ret is 0;
182 * On error ret is negative.
184 * An event with NO loglevel and the name is * will return NULL.
186 static int generate_agent_filter(
187 const struct lttng_event_rule
*rule
, char **_agent_filter
)
191 char *agent_filter
= NULL
;
194 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
195 enum lttng_event_rule_status status
;
198 assert(_agent_filter
);
200 status
= lttng_event_rule_python_logging_get_name_pattern(rule
, &pattern
);
201 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
206 status
= lttng_event_rule_python_logging_get_filter(rule
, &filter
);
207 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
209 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
215 /* Don't add filter for the '*' event. */
216 if (strcmp(pattern
, "*") != 0) {
218 err
= asprintf(&agent_filter
,
219 "(%s) && (logger_name == \"%s\")",
222 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
227 PERROR("Failed to format agent filter string");
233 status
= lttng_event_rule_python_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
;
240 switch (lttng_log_level_rule_get_type(log_level_rule
))
242 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
243 llr_status
= lttng_log_level_rule_exactly_get_level(
244 log_level_rule
, &level
);
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
);
256 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
261 if (filter
|| agent_filter
) {
264 err
= asprintf(&new_filter
,
265 "(%s) && (int_loglevel %s %d)",
266 agent_filter
? agent_filter
: filter
,
271 agent_filter
= new_filter
;
273 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
278 PERROR("Failed to format agent filter string");
284 *_agent_filter
= agent_filter
;
292 static enum lttng_error_code
293 lttng_event_rule_python_logging_generate_filter_bytecode(
294 struct lttng_event_rule
*rule
,
295 const struct lttng_credentials
*creds
)
298 enum lttng_error_code ret_code
;
299 struct lttng_event_rule_python_logging
*python_logging
;
300 enum lttng_event_rule_status status
;
302 struct lttng_bytecode
*bytecode
= NULL
;
307 python_logging
= container_of(
308 rule
, struct lttng_event_rule_python_logging
, parent
);
310 status
= lttng_event_rule_python_logging_get_filter(rule
, &filter
);
311 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
313 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
314 ret_code
= LTTNG_ERR_FILTER_INVAL
;
318 if (filter
&& filter
[0] == '\0') {
319 ret_code
= LTTNG_ERR_FILTER_INVAL
;
323 ret
= generate_agent_filter(rule
, &agent_filter
);
325 ret_code
= LTTNG_ERR_FILTER_INVAL
;
329 python_logging
->internal_filter
.filter
= agent_filter
;
331 if (python_logging
->internal_filter
.filter
== NULL
) {
336 ret
= run_as_generate_filter_bytecode(
337 python_logging
->internal_filter
.filter
, creds
,
340 ret_code
= LTTNG_ERR_FILTER_INVAL
;
344 python_logging
->internal_filter
.bytecode
= bytecode
;
354 static const char *lttng_event_rule_python_logging_get_internal_filter(
355 const struct lttng_event_rule
*rule
)
357 struct lttng_event_rule_python_logging
*python_logging
;
360 python_logging
= container_of(
361 rule
, struct lttng_event_rule_python_logging
, parent
);
362 return python_logging
->internal_filter
.filter
;
365 static const struct lttng_bytecode
*
366 lttng_event_rule_python_logging_get_internal_filter_bytecode(
367 const struct lttng_event_rule
*rule
)
369 struct lttng_event_rule_python_logging
*python_logging
;
372 python_logging
= container_of(
373 rule
, struct lttng_event_rule_python_logging
, parent
);
374 return python_logging
->internal_filter
.bytecode
;
377 static enum lttng_event_rule_generate_exclusions_status
378 lttng_event_rule_python_logging_generate_exclusions(
379 const struct lttng_event_rule
*rule
,
380 struct lttng_event_exclusion
**_exclusions
)
384 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
387 static unsigned long lttng_event_rule_python_logging_hash(
388 const struct lttng_event_rule
*rule
)
391 struct lttng_event_rule_python_logging
*tp_rule
=
392 container_of(rule
, typeof(*tp_rule
), parent
);
394 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING
,
396 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
398 if (tp_rule
->filter_expression
) {
399 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
402 if (tp_rule
->log_level_rule
) {
403 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
409 static struct lttng_event
*lttng_event_rule_python_logging_generate_lttng_event(
410 const struct lttng_event_rule
*rule
)
413 const struct lttng_event_rule_python_logging
*python_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
;
421 python_logging
= container_of(
422 rule
, const struct lttng_event_rule_python_logging
, parent
);
424 local_event
= zmalloc(sizeof(*local_event
));
429 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
430 ret
= lttng_strncpy(local_event
->name
, python_logging
->pattern
,
431 sizeof(local_event
->name
));
433 ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
434 python_logging
->pattern
);
439 /* Map the log level rule to an equivalent lttng_loglevel. */
440 status
= lttng_event_rule_python_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
;
445 } else if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
446 enum lttng_log_level_rule_status llr_status
;
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
;
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
;
464 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
471 local_event
->loglevel_type
= loglevel_type
;
472 local_event
->loglevel
= loglevel_value
;
481 struct lttng_event_rule
*lttng_event_rule_python_logging_create(void)
483 struct lttng_event_rule
*rule
= NULL
;
484 struct lttng_event_rule_python_logging
*tp_rule
;
485 enum lttng_event_rule_status status
;
487 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_python_logging
));
492 rule
= &tp_rule
->parent
;
493 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING
);
494 tp_rule
->parent
.validate
= lttng_event_rule_python_logging_validate
;
495 tp_rule
->parent
.serialize
= lttng_event_rule_python_logging_serialize
;
496 tp_rule
->parent
.equal
= lttng_event_rule_python_logging_is_equal
;
497 tp_rule
->parent
.destroy
= lttng_event_rule_python_logging_destroy
;
498 tp_rule
->parent
.generate_filter_bytecode
=
499 lttng_event_rule_python_logging_generate_filter_bytecode
;
500 tp_rule
->parent
.get_filter
=
501 lttng_event_rule_python_logging_get_internal_filter
;
502 tp_rule
->parent
.get_filter_bytecode
=
503 lttng_event_rule_python_logging_get_internal_filter_bytecode
;
504 tp_rule
->parent
.generate_exclusions
=
505 lttng_event_rule_python_logging_generate_exclusions
;
506 tp_rule
->parent
.hash
= lttng_event_rule_python_logging_hash
;
507 tp_rule
->parent
.generate_lttng_event
=
508 lttng_event_rule_python_logging_generate_lttng_event
;
510 tp_rule
->log_level_rule
= NULL
;
512 /* Default pattern is '*'. */
513 status
= lttng_event_rule_python_logging_set_name_pattern(rule
, "*");
514 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
515 lttng_event_rule_destroy(rule
);
524 ssize_t
lttng_event_rule_python_logging_create_from_payload(
525 struct lttng_payload_view
*view
,
526 struct lttng_event_rule
**_event_rule
)
528 ssize_t ret
, offset
= 0;
529 enum lttng_event_rule_status status
;
530 const struct lttng_event_rule_python_logging_comm
*python_logging_comm
;
532 const char *filter_expression
= NULL
;
533 struct lttng_buffer_view current_buffer_view
;
534 struct lttng_event_rule
*rule
= NULL
;
535 struct lttng_log_level_rule
*log_level_rule
= NULL
;
542 current_buffer_view
= lttng_buffer_view_from_view(
543 &view
->buffer
, offset
, sizeof(*python_logging_comm
));
544 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
545 ERR("Failed to initialize from malformed event rule python_logging: buffer too short to contain header.");
550 python_logging_comm
= (typeof(python_logging_comm
)) current_buffer_view
.data
;
552 rule
= lttng_event_rule_python_logging_create();
554 ERR("Failed to create event rule python_logging.");
559 /* Skip to payload. */
560 offset
+= current_buffer_view
.size
;
562 /* Map the pattern. */
563 current_buffer_view
= lttng_buffer_view_from_view(
564 &view
->buffer
, offset
, python_logging_comm
->pattern_len
);
566 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
571 pattern
= current_buffer_view
.data
;
572 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
573 python_logging_comm
->pattern_len
)) {
578 /* Skip after the pattern. */
579 offset
+= python_logging_comm
->pattern_len
;
581 if (!python_logging_comm
->filter_expression_len
) {
582 goto skip_filter_expression
;
585 /* Map the filter_expression. */
586 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
587 python_logging_comm
->filter_expression_len
);
588 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
593 filter_expression
= current_buffer_view
.data
;
594 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
596 python_logging_comm
->filter_expression_len
)) {
601 /* Skip after the pattern. */
602 offset
+= python_logging_comm
->filter_expression_len
;
604 skip_filter_expression
:
605 if (!python_logging_comm
->log_level_rule_len
) {
606 goto skip_log_level_rule
;
610 /* Map the log level rule. */
611 struct lttng_payload_view current_payload_view
=
612 lttng_payload_view_from_view(view
, offset
,
613 python_logging_comm
->log_level_rule_len
);
615 ret
= lttng_log_level_rule_create_from_payload(
616 ¤t_payload_view
, &log_level_rule
);
622 assert(ret
== python_logging_comm
->log_level_rule_len
);
625 /* Skip after the log level rule. */
626 offset
+= python_logging_comm
->log_level_rule_len
;
630 status
= lttng_event_rule_python_logging_set_name_pattern(rule
, pattern
);
631 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
632 ERR("Failed to set event rule python_logging pattern.");
637 if (filter_expression
) {
638 status
= lttng_event_rule_python_logging_set_filter(
639 rule
, filter_expression
);
640 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
641 ERR("Failed to set event rule python_logging pattern.");
647 if (log_level_rule
) {
648 status
= lttng_event_rule_python_logging_set_log_level_rule(
649 rule
, log_level_rule
);
650 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
651 ERR("Failed to set event rule python_logging log level rule.");
661 lttng_log_level_rule_destroy(log_level_rule
);
662 lttng_event_rule_destroy(rule
);
666 enum lttng_event_rule_status
lttng_event_rule_python_logging_set_name_pattern(
667 struct lttng_event_rule
*rule
, const char *pattern
)
669 char *pattern_copy
= NULL
;
670 struct lttng_event_rule_python_logging
*python_logging
;
671 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
673 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
) || !pattern
||
674 strlen(pattern
) == 0) {
675 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
679 python_logging
= container_of(
680 rule
, struct lttng_event_rule_python_logging
, parent
);
681 pattern_copy
= strdup(pattern
);
683 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
687 /* Normalize the pattern. */
688 strutils_normalize_star_glob_pattern(pattern_copy
);
690 free(python_logging
->pattern
);
692 python_logging
->pattern
= pattern_copy
;
698 enum lttng_event_rule_status
lttng_event_rule_python_logging_get_name_pattern(
699 const struct lttng_event_rule
*rule
, const char **pattern
)
701 struct lttng_event_rule_python_logging
*python_logging
;
702 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
704 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
) || !pattern
) {
705 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
709 python_logging
= container_of(
710 rule
, struct lttng_event_rule_python_logging
, parent
);
711 if (!python_logging
->pattern
) {
712 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
716 *pattern
= python_logging
->pattern
;
721 enum lttng_event_rule_status
lttng_event_rule_python_logging_set_filter(
722 struct lttng_event_rule
*rule
, const char *expression
)
724 char *expression_copy
= NULL
;
725 struct lttng_event_rule_python_logging
*python_logging
;
726 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
728 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
) || !expression
||
729 strlen(expression
) == 0) {
730 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
734 python_logging
= container_of(
735 rule
, struct lttng_event_rule_python_logging
, parent
);
736 expression_copy
= strdup(expression
);
737 if (!expression_copy
) {
738 PERROR("Failed to copy filter expression");
739 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
743 if (python_logging
->filter_expression
) {
744 free(python_logging
->filter_expression
);
747 python_logging
->filter_expression
= expression_copy
;
748 expression_copy
= NULL
;
753 enum lttng_event_rule_status
lttng_event_rule_python_logging_get_filter(
754 const struct lttng_event_rule
*rule
, const char **expression
)
756 struct lttng_event_rule_python_logging
*python_logging
;
757 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
759 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
) || !expression
) {
760 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
764 python_logging
= container_of(
765 rule
, struct lttng_event_rule_python_logging
, parent
);
766 if (!python_logging
->filter_expression
) {
767 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
771 *expression
= python_logging
->filter_expression
;
776 static bool log_level_rule_valid(const struct lttng_log_level_rule
*rule
)
779 * For python, custom log level are possible, it is not clear if
780 * negative value are accepted (NOTSET == 0) but the source code
781 * validates against the int type implying that negative values
787 enum lttng_event_rule_status
lttng_event_rule_python_logging_set_log_level_rule(
788 struct lttng_event_rule
*rule
,
789 const struct lttng_log_level_rule
*log_level_rule
)
791 struct lttng_event_rule_python_logging
*python_logging
;
792 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
793 struct lttng_log_level_rule
*copy
= NULL
;
795 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
)) {
796 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
800 python_logging
= container_of(
801 rule
, struct lttng_event_rule_python_logging
, parent
);
803 if (!log_level_rule_valid(log_level_rule
)) {
804 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
808 copy
= lttng_log_level_rule_copy(log_level_rule
);
810 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
814 if (python_logging
->log_level_rule
) {
815 lttng_log_level_rule_destroy(python_logging
->log_level_rule
);
818 python_logging
->log_level_rule
= copy
;
824 enum lttng_event_rule_status
lttng_event_rule_python_logging_get_log_level_rule(
825 const struct lttng_event_rule
*rule
,
826 const struct lttng_log_level_rule
**log_level_rule
829 struct lttng_event_rule_python_logging
*python_logging
;
830 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
832 if (!rule
|| !IS_PYTHON_LOGGING_EVENT_RULE(rule
) || !log_level_rule
) {
833 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
837 python_logging
= container_of(
838 rule
, struct lttng_event_rule_python_logging
, parent
);
839 if (python_logging
->log_level_rule
== NULL
) {
840 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
844 *log_level_rule
= python_logging
->log_level_rule
;