/tests/unit/test_buffer_view
/tests/unit/test_kernel_probe
/tests/unit/test_event_expr_to_bytecode
+/tests/unit/test_log_level_rule
/tests/utils/testapp/gen-ust-nevents-str/gen-ust-nevents-str
/tests/utils/testapp/userspace-probe-elf-binary/userspace-probe-elf-binary
/tests/utils/testapp/userspace-probe-elf-cxx-binary/userspace-probe-elf-cxx-binary
lttng/kernel-probe.h \
lttng/load.h \
lttng/location.h \
+ lttng/log-level-rule.h \
lttng/lttng-error.h \
lttng/lttng.h \
lttng/rotation.h \
lttng/kernel-probe-internal.h \
lttng/load-internal.h \
lttng/location-internal.h \
+ lttng/log-level-rule-internal.h \
lttng/notification/channel-internal.h \
lttng/notification/notification-internal.h \
lttng/ref-internal.h \
#include <common/payload-view.h>
#include <common/macros.h>
+#include <common/optional.h>
#include <lttng/domain.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/event-rule/tracepoint.h>
#include <lttng/event.h>
+#include <lttng/log-level-rule-internal.h>
struct lttng_event_rule_tracepoint {
struct lttng_event_rule parent;
/* Filter. */
char *filter_expression;
- /* Loglevel. */
- struct {
- enum lttng_loglevel_type type;
- int value;
- } loglevel;
+ /* Log level. */
+ struct lttng_log_level_rule *log_level_rule;
/* Exclusions. */
struct lttng_dynamic_pointer_array exclusions;
struct lttng_event_rule_tracepoint_comm {
/* enum lttng_domain_type. */
int8_t domain_type;
- /* enum lttng_event_logleven_type. */
- int8_t loglevel_type;
- int32_t loglevel_value;
/* Includes terminator `\0`. */
uint32_t pattern_len;
/* Includes terminator `\0`. */
uint32_t filter_expression_len;
+ /* enum lttng_log_level_rule_comm + payload if any */
+ uint32_t log_level_rule_len;
uint32_t exclusions_count;
uint32_t exclusions_len;
/*
* Payload is composed of, in that order:
* - pattern (null terminated),
* - filter expression (null terminated),
+ * - log level rule serialized object,
* - exclusions (32 bit length + null terminated string).
*/
char payload[];
#include <lttng/domain.h>
#include <lttng/event-rule/event-rule.h>
+#include <lttng/log-level-rule.h>
#include <lttng/event.h>
#ifdef __cplusplus
const struct lttng_event_rule *rule, const char **expression);
/*
- * Set the single log level of a tracepoint event rule.
+ * Set the log level rule of a tracepoint event rule.
*
- * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
- * if invalid parameters are passed.
- */
-extern enum lttng_event_rule_status lttng_event_rule_tracepoint_set_log_level(
- struct lttng_event_rule *rule, int level);
-
-/*
- * Set the log level range lower bound of a tracepoint event rule.
+ * The log level rule is copied internally.
*
* Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
* if invalid parameters are passed.
*/
extern enum lttng_event_rule_status
-lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
- struct lttng_event_rule *rule, int level);
+lttng_event_rule_tracepoint_set_log_level_rule(struct lttng_event_rule *rule,
+ const struct lttng_log_level_rule *log_level_rule);
/*
- * Set the log level to all of a tracepoint event rule.
+ * Get the log level rule of a tracepoint event rule.
*
- * Return LTTNG_EVENT_RULE_STATUS_OK on success, LTTNG_EVENT_RULE_STATUS_INVALID
- * if invalid parameters are passed.
- */
-extern enum lttng_event_rule_status
-lttng_event_rule_tracepoint_set_log_level_all(struct lttng_event_rule *rule);
-
-/*
- * Get the log level type of a tracepoint event rule.
+ * The caller does not assume the ownership of the returned log level rule. The
+ * log level rule shall only only be used for the duration of the event rule's
+ * lifetime, or before a different log level rule is set.
*
- * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the log level type output
+ * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the log level rule output
* parameter on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter
- * is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level was not set prior
+ * is passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level rule was not set prior
* to this call.
*/
extern enum lttng_event_rule_status
-lttng_event_rule_tracepoint_get_log_level_type(
+lttng_event_rule_tracepoint_get_log_level_rule(
const struct lttng_event_rule *rule,
- enum lttng_loglevel_type *type);
-
-/*
- * Get the log level of a tracepoint event rule.
- *
- * For range log level , the lower bound log level is returned.
- *
- * Returns LTTNG_EVENT_RULE_STATUS_OK and sets the log level output parameter
- * on success, LTTNG_EVENT_RULE_STATUS_INVALID if an invalid parameter is
- * passed, or LTTNG_EVENT_RULE_STATUS_UNSET if a log level was not set prior to
- * this call.
- */
-extern enum lttng_event_rule_status lttng_event_rule_tracepoint_get_log_level(
- const struct lttng_event_rule *rule, int *level);
+ const struct lttng_log_level_rule **log_level_rule);
/*
* Add an exclusion to the set of exclusion of an event rule.
--- /dev/null
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_LOG_LEVEL_RULE_INTERNAL_H
+#define LTTNG_LOG_LEVEL_RULE_INTERNAL_H
+
+#include <stdint.h>
+
+#include <common/buffer-view.h>
+#include <common/dynamic-array.h>
+#include <common/macros.h>
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/event.h>
+#include <lttng/log-level-rule.h>
+
+/*
+ * For now only a single backing struct is used for both type of log level
+ * rule (exactly, as_severe) since both only have require "level" as property.
+ */
+struct lttng_log_level_rule {
+ enum lttng_log_level_rule_type type;
+ int level;
+};
+
+struct lttng_log_level_rule_comm {
+ /* enum lttng_log_level_rule_type */
+ int8_t type;
+ int32_t level;
+};
+
+LTTNG_HIDDEN
+ssize_t lttng_log_level_rule_create_from_payload(
+ struct lttng_payload_view *view,
+ struct lttng_log_level_rule **rule);
+
+LTTNG_HIDDEN
+int lttng_log_level_rule_serialize(const struct lttng_log_level_rule *rule,
+ struct lttng_payload *payload);
+
+LTTNG_HIDDEN
+bool lttng_log_level_rule_is_equal(const struct lttng_log_level_rule *a,
+ const struct lttng_log_level_rule *b);
+
+LTTNG_HIDDEN
+struct lttng_log_level_rule *lttng_log_level_rule_copy(
+ const struct lttng_log_level_rule *source);
+
+LTTNG_HIDDEN
+void lttng_log_level_rule_to_loglevel(
+ const struct lttng_log_level_rule *log_level_rule,
+ enum lttng_loglevel_type *loglevel_type,
+ int *loglevel_value);
+
+LTTNG_HIDDEN
+unsigned long lttng_log_level_rule_hash(
+ const struct lttng_log_level_rule *log_level_rule);
+
+#endif /* LTTNG_LOG_LEVEL_RULE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_LOG_LEVEL_RULE_H
+#define LTTNG_LOG_LEVEL_RULE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_log_level_rule;
+
+enum lttng_log_level_rule_type {
+ LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN = -1,
+ LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY = 0,
+ LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS = 1,
+};
+
+enum lttng_log_level_rule_status {
+ LTTNG_LOG_LEVEL_RULE_STATUS_OK = 0,
+ LTTNG_LOG_LEVEL_RULE_STATUS_ERROR = -1,
+ LTTNG_LOG_LEVEL_RULE_STATUS_INVALID = -3,
+};
+
+/*
+ * Returns the type of the log level rule `rule`, or:
+ *
+ * `LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN`:
+ * `rule` is `NULL`.
+ */
+extern enum lttng_log_level_rule_type lttng_log_level_rule_get_type(
+ const struct lttng_log_level_rule *rule);
+
+/*
+ * Creates a log level rule for which a log level must match exactly `level` to
+ * be considered.
+ *
+ * Returns `NULL` if:
+ *
+ * * There's a memory error.
+ *
+ * The returned log level rule must be destroyed using
+ * lttng_log_level_rule_destroy().
+ */
+extern struct lttng_log_level_rule *lttng_log_level_rule_exactly_create(
+ int level);
+
+/*
+ * Sets `level` to the level of the "exactly" log level rule `rule`.
+ *
+ * Returns:
+ *
+ * `LTTNG_LOG_LEVEL_RULE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_LOG_LEVEL_RULE_STATUS_INVALID`:
+ * * `rule` is NULL.
+ * * `level` is NULL.
+ * * The type of `rule` is not `LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY`.
+ */
+extern enum lttng_log_level_rule_status lttng_log_level_rule_exactly_get_level(
+ const struct lttng_log_level_rule *rule, int *level);
+
+/*
+ * Creates a log level rule for which a log level must be at least as severe as
+ * `level` to be considered.
+ *
+ * Returns `NULL` if:
+ *
+ * * There's a memory error.
+ *
+ * The returned log level rule must be destroyed using
+ * lttng_log_level_rule_destroy().
+ */
+extern struct lttng_log_level_rule *
+lttng_log_level_rule_at_least_as_severe_as_create(int level);
+
+/*
+ * Sets `level` to the level of the "at least as severe as" log level rule
+ * `rule`.
+ *
+ * Returns:
+ *
+ * `LTTNG_LOG_LEVEL_RULE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_LOG_LEVEL_RULE_STATUS_INVALID`:
+ * * `rule` is NULL.
+ * * `level` is NULL.
+ * * The type of `rule` is not
+ * `LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS`.
+ */
+extern enum lttng_log_level_rule_status
+lttng_log_level_rule_at_least_as_severe_as_get_level(
+ const struct lttng_log_level_rule *rule, int *level);
+
+/*
+ * Destroy the log level rule `log_level_rule` if not `NULL`.
+ */
+extern void lttng_log_level_rule_destroy(
+ struct lttng_log_level_rule *log_level_rule);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_LOG_LEVEL_RULE_H */
#include <lttng/load.h>
#include <lttng/location.h>
#include <lttng/lttng-error.h>
+#include <lttng/log-level-rule.h>
#include <lttng/notification/channel.h>
#include <lttng/notification/notification.h>
#include <lttng/rotation.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/on-event.h>
#include <lttng/domain-internal.h>
+#include <lttng/log-level-rule-internal.h>
#include <common/common.h>
#include <common/sessiond-comm/agent.h>
const struct lttng_event_rule *rule;
const char *name;
const char *filter_expression;
+ const struct lttng_log_level_rule *log_level_rule;
/* Unused when loglevel_type is 'ALL'. */
int loglevel_value = 0;
enum lttng_loglevel_type loglevel_type;
/* Get the internal filter expression. */
filter_expression = lttng_event_rule_get_filter(rule);
- er_status = lttng_event_rule_tracepoint_get_log_level_type(
- rule, &loglevel_type);
- assert(er_status == LTTNG_EVENT_RULE_STATUS_OK);
-
- if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
- er_status = lttng_event_rule_tracepoint_get_log_level(
- rule, &loglevel_value);
- assert(er_status == LTTNG_EVENT_RULE_STATUS_OK);
+ /* Map log_level_rule to loglevel value. */
+ er_status = lttng_event_rule_tracepoint_get_log_level_rule(
+ rule, &log_level_rule);
+ if (er_status == LTTNG_EVENT_RULE_STATUS_UNSET) {
+ loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+ loglevel_value = 0;
+ } else if (er_status == LTTNG_EVENT_RULE_STATUS_OK) {
+ lttng_log_level_rule_to_loglevel(log_level_rule, &loglevel_type, &loglevel_value);
+ } else {
+ abort();
}
return agent_find_event(name, loglevel_type, loglevel_value,
struct lttng_ust_abi_event_notifier *event_notifier)
{
enum lttng_event_rule_status status;
- enum lttng_loglevel_type loglevel_type;
enum lttng_ust_abi_loglevel_type ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
int loglevel = -1, ret = 0;
const char *pattern;
loglevel = 0;
ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
} else {
- status = lttng_event_rule_tracepoint_get_pattern(
- rule, &pattern);
- if (status != LTTNG_EVENT_RULE_STATUS_OK) {
- /* At this point, this is a fatal error. */
- abort();
- }
+ const struct lttng_log_level_rule *log_level_rule;
- status = lttng_event_rule_tracepoint_get_log_level_type(
- rule, &loglevel_type);
+ status = lttng_event_rule_tracepoint_get_pattern(rule, &pattern);
if (status != LTTNG_EVENT_RULE_STATUS_OK) {
/* At this point, this is a fatal error. */
abort();
}
- switch (loglevel_type) {
- case LTTNG_EVENT_LOGLEVEL_ALL:
+ status = lttng_event_rule_tracepoint_get_log_level_rule(
+ rule, &log_level_rule);
+ if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
- break;
- case LTTNG_EVENT_LOGLEVEL_RANGE:
- ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_RANGE;
- break;
- case LTTNG_EVENT_LOGLEVEL_SINGLE:
- ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_SINGLE;
- break;
- default:
- /* Unknown log level specification type. */
- abort();
- }
+ } else if (status == LTTNG_EVENT_RULE_STATUS_OK) {
+ enum lttng_log_level_rule_status llr_status;
+
+ switch (lttng_log_level_rule_get_type(log_level_rule)) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_SINGLE;
+ llr_status = lttng_log_level_rule_exactly_get_level(
+ log_level_rule, &loglevel);
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_RANGE;
+ llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+ log_level_rule, &loglevel);
+ break;
+ default:
+ abort();
+ }
- if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
- status = lttng_event_rule_tracepoint_get_log_level(
- rule, &loglevel);
- assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+ assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
+ } else {
+ /* At this point this is a fatal error. */
+ abort();
}
}
struct parse_event_rule_res res = { 0 };
struct lttng_event_expr *event_expr = NULL;
struct filter_parser_ctx *parser_ctx = NULL;
+ struct lttng_log_level_rule *log_level_rule = NULL;
/* Was the -a/--all flag provided? */
bool all_events = false;
}
if (loglevel_only) {
- event_rule_status = lttng_event_rule_tracepoint_set_log_level(
- res.er,
- loglevel);
+ log_level_rule = lttng_log_level_rule_exactly_create(loglevel);
} else {
- event_rule_status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
- res.er,
- loglevel);
+ log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(loglevel);
+ }
+
+ if (log_level_rule == NULL) {
+ ERR("Failed to create log level rule object.");
+ goto error;
}
+ event_rule_status =
+ lttng_event_rule_tracepoint_set_log_level_rule(
+ res.er, log_level_rule);
+
if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
ERR("Failed to set log level on event fule.");
goto error;
strutils_free_null_terminated_array_of_strings(exclusion_list);
lttng_kernel_probe_location_destroy(kernel_probe_location);
lttng_userspace_probe_location_destroy(userspace_probe_location);
+ lttng_log_level_rule_destroy(log_level_rule);
return res;
}
#include "lttng/condition/condition-internal.h"
/* For lttng_domain_type_str(). */
#include "lttng/domain-internal.h"
+#include "../loglevel.h"
#ifdef LTTNG_EMBED_HELP
static const char help_msg[] =
ARGPAR_OPT_DESCR_SENTINEL,
};
+/*
+ * Returns the human-readable log level name associated with a numerical value
+ * if there is one. The Log4j and JUL domains have discontinuous log level
+ * values (a value can fall between two labels). In those cases, NULL is
+ * returned.
+ */
+static const char *get_pretty_loglevel_name(
+ enum lttng_domain_type domain, int loglevel)
+{
+ const char *name = NULL;
+
+ switch (domain) {
+ case LTTNG_DOMAIN_UST:
+ name = loglevel_value_to_name(loglevel);
+ break;
+ case LTTNG_DOMAIN_LOG4J:
+ name = loglevel_log4j_value_to_name(loglevel);
+ break;
+ case LTTNG_DOMAIN_JUL:
+ name = loglevel_jul_value_to_name(loglevel);
+ break;
+ case LTTNG_DOMAIN_PYTHON:
+ name = loglevel_python_value_to_name(loglevel);
+ break;
+ default:
+ break;
+ }
+
+ return name;
+}
+
static
void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule)
{
const char *pattern;
const char *filter;
int log_level;
+ const struct lttng_log_level_rule *log_level_rule = NULL;
unsigned int exclusions_count;
int i;
assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
}
- event_rule_status = lttng_event_rule_tracepoint_get_log_level(
- event_rule, &log_level);
+ event_rule_status = lttng_event_rule_tracepoint_get_log_level_rule(
+ event_rule, &log_level_rule);
if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
- enum lttng_loglevel_type log_level_type;
+ enum lttng_log_level_rule_status llr_status;
const char *log_level_op;
+ const char *pretty_loglevel_name;
+
+ switch (lttng_log_level_rule_get_type(log_level_rule)) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ log_level_op = "is";
+ llr_status = lttng_log_level_rule_exactly_get_level(
+ log_level_rule, &log_level);
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ log_level_op = "at least";
+ llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+ log_level_rule, &log_level);
+ break;
+ default:
+ abort();
+ }
- event_rule_status = lttng_event_rule_tracepoint_get_log_level_type(
- event_rule, &log_level_type);
- assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
- assert(log_level_type == LTTNG_EVENT_LOGLEVEL_RANGE ||
- log_level_type == LTTNG_EVENT_LOGLEVEL_SINGLE);
-
- log_level_op = (log_level_type == LTTNG_EVENT_LOGLEVEL_RANGE ? "<=" : "==");
+ assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
- _MSG(", log level %s %s", log_level_op,
- mi_lttng_loglevel_string(
- log_level, domain_type));
+ pretty_loglevel_name = get_pretty_loglevel_name(
+ domain_type, log_level);
+ if (pretty_loglevel_name) {
+ _MSG(", log level %s %s", log_level_op,
+ pretty_loglevel_name);
+ } else {
+ _MSG(", log level %s %d", log_level_op, log_level);
+ }
} else {
assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
}
static
const struct loglevel_name_value loglevel_values[] = {
- { .name = "TRACE_EMERG", .value = LTTNG_LOGLEVEL_EMERG },
{ .name = "EMERG", .value = LTTNG_LOGLEVEL_EMERG },
- { .name = "TRACE_ALERT", .value = LTTNG_LOGLEVEL_ALERT },
+ { .name = "TRACE_EMERG", .value = LTTNG_LOGLEVEL_EMERG },
{ .name = "ALERT", .value = LTTNG_LOGLEVEL_ALERT },
- { .name = "TRACE_CRIT", .value = LTTNG_LOGLEVEL_CRIT },
+ { .name = "TRACE_ALERT", .value = LTTNG_LOGLEVEL_ALERT },
{ .name = "CRIT", .value = LTTNG_LOGLEVEL_CRIT },
- { .name = "TRACE_ERR", .value = LTTNG_LOGLEVEL_ERR },
+ { .name = "TRACE_CRIT", .value = LTTNG_LOGLEVEL_CRIT },
{ .name = "ERR", .value = LTTNG_LOGLEVEL_ERR },
- { .name = "TRACE_WARNING", .value = LTTNG_LOGLEVEL_WARNING },
+ { .name = "TRACE_ERR", .value = LTTNG_LOGLEVEL_ERR },
{ .name = "WARNING", .value = LTTNG_LOGLEVEL_WARNING },
- { .name = "TRACE_NOTICE", .value = LTTNG_LOGLEVEL_NOTICE },
+ { .name = "TRACE_WARNING", .value = LTTNG_LOGLEVEL_WARNING },
{ .name = "NOTICE", .value = LTTNG_LOGLEVEL_NOTICE },
- { .name = "TRACE_INFO", .value = LTTNG_LOGLEVEL_INFO },
+ { .name = "TRACE_NOTICE", .value = LTTNG_LOGLEVEL_NOTICE },
{ .name = "INFO", .value = LTTNG_LOGLEVEL_INFO },
- { .name = "TRACE_DEBUG_SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
+ { .name = "TRACE_INFO", .value = LTTNG_LOGLEVEL_INFO },
{ .name = "DEBUG_SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
+ { .name = "TRACE_DEBUG_SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
{ .name = "SYSTEM", .value = LTTNG_LOGLEVEL_DEBUG_SYSTEM },
- { .name = "TRACE_DEBUG_PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
{ .name = "DEBUG_PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
+ { .name = "TRACE_DEBUG_PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
{ .name = "PROGRAM", .value = LTTNG_LOGLEVEL_DEBUG_PROGRAM },
- { .name = "TRACE_DEBUG_PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
{ .name = "DEBUG_PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
+ { .name = "TRACE_DEBUG_PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
{ .name = "PROCESS", .value = LTTNG_LOGLEVEL_DEBUG_PROCESS },
- { .name = "TRACE_DEBUG_MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
{ .name = "DEBUG_MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
+ { .name = "TRACE_DEBUG_MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
{ .name = "MODULE", .value = LTTNG_LOGLEVEL_DEBUG_MODULE },
- { .name = "TRACE_DEBUG_UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
{ .name = "DEBUG_UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
+ { .name = "TRACE_DEBUG_UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
{ .name = "UNIT", .value = LTTNG_LOGLEVEL_DEBUG_UNIT },
- { .name = "TRACE_DEBUG_FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
{ .name = "DEBUG_FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
+ { .name = "TRACE_DEBUG_FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
{ .name = "FUNCTION", .value = LTTNG_LOGLEVEL_DEBUG_FUNCTION },
- { .name = "TRACE_DEBUG_LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
{ .name = "DEBUG_LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
+ { .name = "TRACE_DEBUG_LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
{ .name = "LINE", .value = LTTNG_LOGLEVEL_DEBUG_LINE },
- { .name = "TRACE_DEBUG", .value = LTTNG_LOGLEVEL_DEBUG },
{ .name = "DEBUG", .value = LTTNG_LOGLEVEL_DEBUG },
+ { .name = "TRACE_DEBUG", .value = LTTNG_LOGLEVEL_DEBUG },
};
static
const struct loglevel_name_value loglevel_log4j_values[] = {
- { .name = "LOG4J_OFF", .value = LTTNG_LOGLEVEL_LOG4J_OFF },
{ .name = "OFF", .value = LTTNG_LOGLEVEL_LOG4J_OFF },
- { .name = "LOG4J_FATAL", .value = LTTNG_LOGLEVEL_LOG4J_FATAL },
+ { .name = "LOG4J_OFF", .value = LTTNG_LOGLEVEL_LOG4J_OFF },
{ .name = "FATAL", .value = LTTNG_LOGLEVEL_LOG4J_FATAL },
- { .name = "LOG4J_ERROR", .value = LTTNG_LOGLEVEL_LOG4J_ERROR },
+ { .name = "LOG4J_FATAL", .value = LTTNG_LOGLEVEL_LOG4J_FATAL },
{ .name = "ERROR", .value = LTTNG_LOGLEVEL_LOG4J_ERROR },
- { .name = "LOG4J_WARN", .value = LTTNG_LOGLEVEL_LOG4J_WARN },
+ { .name = "LOG4J_ERROR", .value = LTTNG_LOGLEVEL_LOG4J_ERROR },
{ .name = "WARN", .value = LTTNG_LOGLEVEL_LOG4J_WARN },
- { .name = "LOG4J_INFO", .value = LTTNG_LOGLEVEL_LOG4J_INFO },
+ { .name = "LOG4J_WARN", .value = LTTNG_LOGLEVEL_LOG4J_WARN },
{ .name = "INFO", .value = LTTNG_LOGLEVEL_LOG4J_INFO },
- { .name = "LOG4J_DEBUG", .value = LTTNG_LOGLEVEL_LOG4J_DEBUG },
+ { .name = "LOG4J_INFO", .value = LTTNG_LOGLEVEL_LOG4J_INFO },
{ .name = "DEBUG", .value = LTTNG_LOGLEVEL_LOG4J_DEBUG },
- { .name = "LOG4J_TRACE", .value = LTTNG_LOGLEVEL_LOG4J_TRACE },
+ { .name = "LOG4J_DEBUG", .value = LTTNG_LOGLEVEL_LOG4J_DEBUG },
{ .name = "TRACE", .value = LTTNG_LOGLEVEL_LOG4J_TRACE },
- { .name = "LOG4J_ALL", .value = LTTNG_LOGLEVEL_LOG4J_ALL },
+ { .name = "LOG4J_TRACE", .value = LTTNG_LOGLEVEL_LOG4J_TRACE },
{ .name = "ALL", .value = LTTNG_LOGLEVEL_LOG4J_ALL },
+ { .name = "LOG4J_ALL", .value = LTTNG_LOGLEVEL_LOG4J_ALL },
};
static
const struct loglevel_name_value loglevel_jul_values[] = {
- { .name = "JUL_OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
{ .name = "OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
- { .name = "JUL_SEVERE", .value = LTTNG_LOGLEVEL_JUL_SEVERE },
+ { .name = "JUL_OFF", .value = LTTNG_LOGLEVEL_JUL_OFF },
{ .name = "SEVERE", .value = LTTNG_LOGLEVEL_JUL_SEVERE },
- { .name = "JUL_WARNING", .value = LTTNG_LOGLEVEL_JUL_WARNING },
+ { .name = "JUL_SEVERE", .value = LTTNG_LOGLEVEL_JUL_SEVERE },
{ .name = "WARNING", .value = LTTNG_LOGLEVEL_JUL_WARNING },
- { .name = "JUL_INFO", .value = LTTNG_LOGLEVEL_JUL_INFO },
+ { .name = "JUL_WARNING", .value = LTTNG_LOGLEVEL_JUL_WARNING },
{ .name = "INFO", .value = LTTNG_LOGLEVEL_JUL_INFO },
- { .name = "JUL_CONFIG", .value = LTTNG_LOGLEVEL_JUL_CONFIG },
+ { .name = "JUL_INFO", .value = LTTNG_LOGLEVEL_JUL_INFO },
{ .name = "CONFIG", .value = LTTNG_LOGLEVEL_JUL_CONFIG },
- { .name = "JUL_FINE", .value = LTTNG_LOGLEVEL_JUL_FINE },
+ { .name = "JUL_CONFIG", .value = LTTNG_LOGLEVEL_JUL_CONFIG },
{ .name = "FINE", .value = LTTNG_LOGLEVEL_JUL_FINE },
- { .name = "JUL_FINER", .value = LTTNG_LOGLEVEL_JUL_FINER },
+ { .name = "JUL_FINE", .value = LTTNG_LOGLEVEL_JUL_FINE },
{ .name = "FINER", .value = LTTNG_LOGLEVEL_JUL_FINER },
- { .name = "JUL_FINEST", .value = LTTNG_LOGLEVEL_JUL_FINEST },
+ { .name = "JUL_FINER", .value = LTTNG_LOGLEVEL_JUL_FINER },
{ .name = "FINEST", .value = LTTNG_LOGLEVEL_JUL_FINEST },
- { .name = "JUL_ALL", .value = LTTNG_LOGLEVEL_JUL_ALL },
+ { .name = "JUL_FINEST", .value = LTTNG_LOGLEVEL_JUL_FINEST },
{ .name = "ALL", .value = LTTNG_LOGLEVEL_JUL_ALL },
+ { .name = "JUL_ALL", .value = LTTNG_LOGLEVEL_JUL_ALL },
};
static
const struct loglevel_name_value loglevel_python_values[] = {
- { .name = "PYTHON_CRITICAL", .value = LTTNG_LOGLEVEL_PYTHON_CRITICAL },
{ .name = "CRITICAL", .value = LTTNG_LOGLEVEL_PYTHON_CRITICAL },
- { .name = "PYTHON_ERROR", .value = LTTNG_LOGLEVEL_PYTHON_ERROR },
+ { .name = "PYTHON_CRITICAL", .value = LTTNG_LOGLEVEL_PYTHON_CRITICAL },
{ .name = "ERROR", .value = LTTNG_LOGLEVEL_PYTHON_ERROR },
- { .name = "PYTHON_WARNING", .value = LTTNG_LOGLEVEL_PYTHON_WARNING },
+ { .name = "PYTHON_ERROR", .value = LTTNG_LOGLEVEL_PYTHON_ERROR },
{ .name = "WARNING", .value = LTTNG_LOGLEVEL_PYTHON_WARNING },
- { .name = "PYTHON_INFO", .value = LTTNG_LOGLEVEL_PYTHON_INFO },
+ { .name = "PYTHON_WARNING", .value = LTTNG_LOGLEVEL_PYTHON_WARNING },
{ .name = "INFO", .value = LTTNG_LOGLEVEL_PYTHON_INFO },
- { .name = "PYTNON_DEBUG", .value = LTTNG_LOGLEVEL_PYTHON_DEBUG },
+ { .name = "PYTHON_INFO", .value = LTTNG_LOGLEVEL_PYTHON_INFO },
{ .name = "DEBUG", .value = LTTNG_LOGLEVEL_PYTHON_DEBUG },
- { .name = "PYTHON_NOTSET", .value = LTTNG_LOGLEVEL_PYTHON_NOTSET },
+ { .name = "PYTNON_DEBUG", .value = LTTNG_LOGLEVEL_PYTHON_DEBUG },
{ .name = "NOTSET", .value = LTTNG_LOGLEVEL_PYTHON_NOTSET },
+ { .name = "PYTHON_NOTSET", .value = LTTNG_LOGLEVEL_PYTHON_NOTSET },
};
static
return ret;
}
+
+static
+const char *lookup_name_from_value(const struct loglevel_name_value values[],
+ size_t values_count, int loglevel)
+{
+ size_t i;
+ const char *name = NULL;
+
+ for (i = 0; i < values_count; i++) {
+ if (values[i].value == loglevel) {
+ /* Match found. */
+ name = values[i].name;
+ goto end;
+ }
+ }
+
+end:
+ return name;
+}
+
+LTTNG_HIDDEN
+const char *loglevel_value_to_name(int loglevel)
+{
+ return lookup_name_from_value(
+ loglevel_values, ARRAY_SIZE(loglevel_values), loglevel);
+}
+
+LTTNG_HIDDEN
+const char *loglevel_log4j_value_to_name(int loglevel)
+{
+ return lookup_name_from_value(loglevel_log4j_values,
+ ARRAY_SIZE(loglevel_log4j_values), loglevel);
+}
+
+LTTNG_HIDDEN
+const char *loglevel_jul_value_to_name(int loglevel)
+{
+ return lookup_name_from_value(loglevel_jul_values,
+ ARRAY_SIZE(loglevel_jul_values), loglevel);
+}
+
+LTTNG_HIDDEN
+const char *loglevel_python_value_to_name(int loglevel)
+{
+ return lookup_name_from_value(loglevel_python_values,
+ ARRAY_SIZE(loglevel_python_values), loglevel);
+}
int loglevel_python_name_to_value(
const char *name, enum lttng_loglevel_python *loglevel);
+LTTNG_HIDDEN
+const char *loglevel_value_to_name(int loglevel);
+
+LTTNG_HIDDEN
+const char *loglevel_log4j_value_to_name(int loglevel);
+
+LTTNG_HIDDEN
+const char *loglevel_jul_value_to_name(int loglevel);
+
+LTTNG_HIDDEN
+const char *loglevel_python_value_to_name(int loglevel);
+
#endif /* _LTTNG_LOGLEVEL_UTILS_H */
futex.c futex.h \
kernel-probe.c \
location.c \
+ log-level-rule.c \
mi-lttng.c mi-lttng.h \
notification.c \
optional.h \
#include <common/credentials.h>
#include <common/error.h>
#include <common/macros.h>
+#include <common/optional.h>
#include <common/payload.h>
#include <common/payload-view.h>
#include <common/runas.h>
#include <common/hashtable/utils.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/event-rule/tracepoint-internal.h>
+#include <lttng/log-level-rule.h>
#include <lttng/event.h>
#define IS_TRACEPOINT_EVENT_RULE(rule) \
struct lttng_payload *payload)
{
int ret, i;
- size_t pattern_len, filter_expression_len, exclusions_len;
+ size_t pattern_len, filter_expression_len, exclusions_len, header_offset;
+ size_t size_before_log_level_rule;
struct lttng_event_rule_tracepoint *tracepoint;
struct lttng_event_rule_tracepoint_comm tracepoint_comm;
enum lttng_event_rule_status status;
unsigned int exclusion_count;
size_t exclusions_appended_len = 0;
+ struct lttng_event_rule_tracepoint_comm *header;
if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
ret = -1;
goto end;
}
+ header_offset = payload->buffer.size;
+
DBG("Serializing tracepoint event rule.");
tracepoint = container_of(
rule, struct lttng_event_rule_tracepoint, parent);
}
tracepoint_comm.domain_type = (int8_t) tracepoint->domain;
- tracepoint_comm.loglevel_type = (int8_t) tracepoint->loglevel.type;
- tracepoint_comm.loglevel_value = tracepoint->loglevel.value;
tracepoint_comm.pattern_len = pattern_len;
tracepoint_comm.filter_expression_len = filter_expression_len;
tracepoint_comm.exclusions_count = exclusion_count;
goto end;
}
+ size_before_log_level_rule = payload->buffer.size;
+
+ ret = lttng_log_level_rule_serialize(tracepoint->log_level_rule, payload);
+ if (ret < 0) {
+ goto end;
+ }
+
+ header = (typeof(header)) ((char *) payload->buffer.data + header_offset);
+ header->log_level_rule_len =
+ payload->buffer.size - size_before_log_level_rule;
+
for (i = 0; i < exclusion_count; i++) {
size_t len;
const char *exclusion;
goto end;
}
- if (a->loglevel.type != b->loglevel.type) {
- goto end;
- }
-
- if (a->loglevel.value != b->loglevel.value) {
+ if (!lttng_log_level_rule_is_equal(
+ a->log_level_rule, b->log_level_rule)) {
goto end;
}
char *agent_filter = NULL;
const char *pattern;
const char *filter;
- enum lttng_loglevel_type loglevel_type;
+ const struct lttng_log_level_rule *log_level_rule = NULL;
enum lttng_event_rule_status status;
assert(rule);
goto end;
}
- status = lttng_event_rule_tracepoint_get_log_level_type(
- rule, &loglevel_type);
- if (status != LTTNG_EVENT_RULE_STATUS_OK) {
- ret = -1;
- goto end;
- }
/* Don't add filter for the '*' event. */
if (strcmp(pattern, "*") != 0) {
}
}
- if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
+ status = lttng_event_rule_tracepoint_get_log_level_rule(
+ rule, &log_level_rule);
+ if (status == LTTNG_EVENT_RULE_STATUS_OK) {
+ enum lttng_log_level_rule_status llr_status;
const char *op;
- int loglevel_value;
+ int level;
- status = lttng_event_rule_tracepoint_get_log_level(
- rule, &loglevel_value);
- if (status != LTTNG_EVENT_RULE_STATUS_OK) {
- ret = -1;
- goto end;
+ switch (lttng_log_level_rule_get_type(log_level_rule))
+ {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ llr_status = lttng_log_level_rule_exactly_get_level(
+ log_level_rule, &level);
+ op = "==";
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+ log_level_rule, &level);
+ op = ">=";
+ break;
+ default:
+ abort();
}
- if (loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) {
- op = ">=";
- } else {
- op = "==";
+ if (llr_status != LTTNG_LOG_LEVEL_RULE_STATUS_OK) {
+ ret = -1;
+ goto end;
}
if (filter || agent_filter) {
err = asprintf(&new_filter,
"(%s) && (int_loglevel %s %d)",
agent_filter ? agent_filter : filter,
- op, loglevel_value);
+ op, level);
if (agent_filter) {
free(agent_filter);
}
agent_filter = new_filter;
} else {
err = asprintf(&agent_filter, "int_loglevel %s %d", op,
- loglevel_value);
+ level);
}
if (err < 0) {
hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
}
- hash ^= hash_key_ulong((void *) tp_rule->loglevel.type,
- lttng_ht_seed);
- if (tp_rule->loglevel.type != LTTNG_EVENT_LOGLEVEL_ALL) {
- hash ^= hash_key_ulong(
- (void *) (unsigned long) tp_rule->loglevel.value,
- lttng_ht_seed);
+ if (tp_rule->log_level_rule) {
+ hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
}
status = lttng_event_rule_tracepoint_get_exclusions_count(rule,
const struct lttng_event_rule_tracepoint *tracepoint;
struct lttng_event *local_event = NULL;
struct lttng_event *event = NULL;
+ enum lttng_loglevel_type loglevel_type;
+ int loglevel_value = 0;
+ enum lttng_event_rule_status status;
+ const struct lttng_log_level_rule *log_level_rule;
tracepoint = container_of(
rule, const struct lttng_event_rule_tracepoint, parent);
goto error;
}
- local_event->loglevel_type = tracepoint->loglevel.type;
- local_event->loglevel = tracepoint->loglevel.value;
+
+ /* Map the log level rule to an equivalent lttng_loglevel. */
+ status = lttng_event_rule_tracepoint_get_log_level_rule(
+ rule, &log_level_rule);
+ if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
+ loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+ loglevel_value = 0;
+ } else if (status == LTTNG_EVENT_RULE_STATUS_OK) {
+ enum lttng_log_level_rule_status llr_status;
+
+ switch (lttng_log_level_rule_get_type(log_level_rule)) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ llr_status = lttng_log_level_rule_exactly_get_level(
+ log_level_rule, &loglevel_value);
+ loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+ log_level_rule, &loglevel_value);
+ loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ if (llr_status != LTTNG_LOG_LEVEL_RULE_STATUS_OK) {
+ goto error;
+ }
+ } else {
+ goto error;
+ }
+
+ local_event->loglevel_type = loglevel_type;
+ local_event->loglevel = loglevel_value;
event = local_event;
local_event = NULL;
lttng_event_rule_tracepoint_generate_lttng_event;
tp_rule->domain = domain_type;
- tp_rule->loglevel.type = LTTNG_EVENT_LOGLEVEL_ALL;
+ tp_rule->log_level_rule = NULL;
lttng_dynamic_pointer_array_init(&tp_rule->exclusions,
destroy_lttng_exclusions_element);
int i;
enum lttng_event_rule_status status;
enum lttng_domain_type domain_type;
- enum lttng_loglevel_type loglevel_type;
const struct lttng_event_rule_tracepoint_comm *tracepoint_comm;
const char *pattern;
const char *filter_expression = NULL;
const char *exclusion;
struct lttng_buffer_view current_buffer_view;
struct lttng_event_rule *rule = NULL;
+ struct lttng_log_level_rule *log_level_rule = NULL;
if (!_event_rule) {
ret = -1;
goto end;
}
- loglevel_type = (enum lttng_loglevel_type)
- tracepoint_comm->loglevel_type;
- switch (loglevel_type) {
- case LTTNG_EVENT_LOGLEVEL_ALL:
- status = lttng_event_rule_tracepoint_set_log_level_all(rule);
- break;
- case LTTNG_EVENT_LOGLEVEL_RANGE:
- status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule,
- (enum lttng_loglevel_type) tracepoint_comm
- ->loglevel_value);
- break;
- case LTTNG_EVENT_LOGLEVEL_SINGLE:
- status = lttng_event_rule_tracepoint_set_log_level(rule,
- (enum lttng_loglevel_type) tracepoint_comm
- ->loglevel_value);
- break;
- default:
- ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
- ret = -1;
- goto end;
- }
-
- if (status != LTTNG_EVENT_RULE_STATUS_OK) {
- ERR("Failed to set event rule tracepoint loglevel.");
- }
-
/* Skip to payload. */
offset += current_buffer_view.size;
offset += tracepoint_comm->filter_expression_len;
skip_filter_expression:
+ if (!tracepoint_comm->log_level_rule_len) {
+ goto skip_log_level_rule;
+ }
+
+ {
+ /* Map the log level rule. */
+ struct lttng_payload_view current_payload_view =
+ lttng_payload_view_from_view(view, offset,
+ tracepoint_comm->log_level_rule_len);
+
+ ret = lttng_log_level_rule_create_from_payload(
+ ¤t_payload_view, &log_level_rule);
+ if (ret < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ assert(ret == tracepoint_comm->log_level_rule_len);
+ }
+
+ /* Skip after the log level rule. */
+ offset += tracepoint_comm->log_level_rule_len;
+
+skip_log_level_rule:
for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
current_buffer_view = lttng_buffer_view_from_view(
&view->buffer, offset, sizeof(*exclusion_len));
}
}
+ if (log_level_rule) {
+ status = lttng_event_rule_tracepoint_set_log_level_rule(
+ rule, log_level_rule);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ ERR("Failed to set event rule tracepoint log level rule.");
+ ret = -1;
+ goto end;
+ }
+ }
+
*_event_rule = rule;
rule = NULL;
ret = offset;
end:
free(exclusions);
+ lttng_log_level_rule_destroy(log_level_rule);
lttng_event_rule_destroy(rule);
return ret;
}
return status;
}
-static bool log_level_value_valid(
- int level, enum lttng_domain_type domain)
+static bool log_level_rule_valid(const struct lttng_log_level_rule *rule,
+ enum lttng_domain_type domain)
{
bool valid = false;
+ enum lttng_log_level_rule_status status;
+ int level;
+
+ switch (lttng_log_level_rule_get_type(rule)) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ status = lttng_log_level_rule_exactly_get_level(rule, &level);
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+ rule, &level);
+ break;
+ default:
+ abort();
+ }
+
+ assert(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ valid = false;
+ break;
case LTTNG_DOMAIN_UST:
if (level < LTTNG_LOGLEVEL_EMERG) {
/* Invalid. */
case LTTNG_DOMAIN_PYTHON:
/*
* For both JUL and LOG4J custom log level are possible and can
- * spawn the entire int32 range.
+ * span the entire int32 range.
+ *
* For python, custom log level are possible, it is not clear if
* negative value are accepted (NOTSET == 0) but the source code
- * validate against the int type implying that negative values
+ * validates against the int type implying that negative values
* are accepted.
*/
valid = true;
goto end;
-
case LTTNG_DOMAIN_NONE:
default:
abort();
return valid;
}
-enum lttng_event_rule_status lttng_event_rule_tracepoint_set_log_level(
- struct lttng_event_rule *rule, int level)
+enum lttng_event_rule_status lttng_event_rule_tracepoint_set_log_level_rule(
+ struct lttng_event_rule *rule,
+ const struct lttng_log_level_rule *log_level_rule)
{
struct lttng_event_rule_tracepoint *tracepoint;
enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+ struct lttng_log_level_rule *copy = NULL;
if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
status = LTTNG_EVENT_RULE_STATUS_INVALID;
tracepoint = container_of(
rule, struct lttng_event_rule_tracepoint, parent);
- if (!log_level_value_valid(level, tracepoint->domain)) {
+ if (!log_level_rule_valid(log_level_rule, tracepoint->domain)) {
status = LTTNG_EVENT_RULE_STATUS_INVALID;
goto end;
}
- tracepoint->loglevel.value = level;
- tracepoint->loglevel.type = LTTNG_EVENT_LOGLEVEL_SINGLE;
-end:
- return status;
-}
-
-enum lttng_event_rule_status
-lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
- struct lttng_event_rule *rule, int level)
-{
- struct lttng_event_rule_tracepoint *tracepoint;
- enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
-
- if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
- status = LTTNG_EVENT_RULE_STATUS_INVALID;
+ copy = lttng_log_level_rule_copy(log_level_rule);
+ if (copy == NULL) {
+ status = LTTNG_EVENT_RULE_STATUS_ERROR;
goto end;
}
- tracepoint = container_of(
- rule, struct lttng_event_rule_tracepoint, parent);
-
- if (!log_level_value_valid(level, tracepoint->domain)) {
- status = LTTNG_EVENT_RULE_STATUS_INVALID;
- goto end;
+ if (tracepoint->log_level_rule) {
+ lttng_log_level_rule_destroy(tracepoint->log_level_rule);
}
- tracepoint->loglevel.value = level;
- tracepoint->loglevel.type = LTTNG_EVENT_LOGLEVEL_RANGE;
-end:
- return status;
-}
-
-enum lttng_event_rule_status lttng_event_rule_tracepoint_set_log_level_all(
- struct lttng_event_rule *rule)
-{
- struct lttng_event_rule_tracepoint *tracepoint;
- enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
+ tracepoint->log_level_rule = copy;
- if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
- status = LTTNG_EVENT_RULE_STATUS_INVALID;
- goto end;
- }
-
- tracepoint = container_of(
- rule, struct lttng_event_rule_tracepoint, parent);
- tracepoint->loglevel.type = LTTNG_EVENT_LOGLEVEL_ALL;
end:
return status;
}
-enum lttng_event_rule_status lttng_event_rule_tracepoint_get_log_level_type(
+enum lttng_event_rule_status lttng_event_rule_tracepoint_get_log_level_rule(
const struct lttng_event_rule *rule,
- enum lttng_loglevel_type *type)
-{
- struct lttng_event_rule_tracepoint *tracepoint;
- enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
-
- if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !type) {
- status = LTTNG_EVENT_RULE_STATUS_INVALID;
- goto end;
- }
-
- tracepoint = container_of(
- rule, struct lttng_event_rule_tracepoint, parent);
- *type = tracepoint->loglevel.type;
-end:
- return status;
-}
-
-enum lttng_event_rule_status lttng_event_rule_tracepoint_get_log_level(
- const struct lttng_event_rule *rule, int *level)
+ const struct lttng_log_level_rule **log_level_rule
+ )
{
struct lttng_event_rule_tracepoint *tracepoint;
enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
- if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !level) {
+ if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !log_level_rule) {
status = LTTNG_EVENT_RULE_STATUS_INVALID;
goto end;
}
tracepoint = container_of(
rule, struct lttng_event_rule_tracepoint, parent);
- if (tracepoint->loglevel.type == LTTNG_EVENT_LOGLEVEL_ALL) {
+ if (tracepoint->log_level_rule == NULL) {
status = LTTNG_EVENT_RULE_STATUS_UNSET;
goto end;
}
- *level = tracepoint->loglevel.value;
+ *log_level_rule = tracepoint->log_level_rule;
end:
return status;
}
--- /dev/null
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <assert.h>
+#include <common/dynamic-buffer.h>
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
+#include <lttng/log-level-rule-internal.h>
+#include <lttng/log-level-rule.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+static bool is_log_level_rule_exactly_type(const struct lttng_log_level_rule *rule)
+{
+ enum lttng_log_level_rule_type type =
+ lttng_log_level_rule_get_type(rule);
+
+ return type == LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY;
+}
+
+static bool is_log_level_rule_at_least_as_severe_type(const struct lttng_log_level_rule *rule)
+{
+
+ enum lttng_log_level_rule_type type =
+ lttng_log_level_rule_get_type(rule);
+
+ return type == LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS;
+}
+
+enum lttng_log_level_rule_type lttng_log_level_rule_get_type(
+ const struct lttng_log_level_rule *rule)
+{
+ return rule ? rule->type : LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN;
+}
+
+struct lttng_log_level_rule *lttng_log_level_rule_exactly_create(
+ int level)
+{
+ struct lttng_log_level_rule *rule = NULL;
+
+ rule = zmalloc(sizeof(struct lttng_log_level_rule));
+ if (!rule) {
+ goto end;
+ }
+
+ rule->type = LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY;
+ rule->level = level;
+
+end:
+ return rule;
+}
+
+enum lttng_log_level_rule_status lttng_log_level_rule_exactly_get_level(
+ const struct lttng_log_level_rule *rule, int *level)
+{
+ enum lttng_log_level_rule_status status =
+ LTTNG_LOG_LEVEL_RULE_STATUS_OK;
+
+ if (!rule || !level || !is_log_level_rule_exactly_type(rule)) {
+ status = LTTNG_LOG_LEVEL_RULE_STATUS_INVALID;
+ goto end;
+ }
+
+ *level = rule->level;
+end:
+ return status;
+}
+
+struct lttng_log_level_rule *
+lttng_log_level_rule_at_least_as_severe_as_create(int level)
+{
+ struct lttng_log_level_rule *rule = NULL;
+
+ rule = zmalloc(sizeof(struct lttng_log_level_rule));
+ if (!rule) {
+ goto end;
+ }
+
+ rule->type = LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS;
+ rule->level = level;
+
+end:
+ return rule;
+}
+
+enum lttng_log_level_rule_status
+lttng_log_level_rule_at_least_as_severe_as_get_level(
+ const struct lttng_log_level_rule *rule, int *level)
+{
+ enum lttng_log_level_rule_status status = LTTNG_LOG_LEVEL_RULE_STATUS_OK;
+
+ if (!rule || !level ||
+ !is_log_level_rule_at_least_as_severe_type(rule)) {
+ status = LTTNG_LOG_LEVEL_RULE_STATUS_INVALID;
+ goto end;
+ }
+
+ *level = rule->level;
+end:
+ return status;
+}
+
+void lttng_log_level_rule_destroy(struct lttng_log_level_rule *log_level_rule)
+{
+ free(log_level_rule);
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_log_level_rule_create_from_payload(
+ struct lttng_payload_view *view,
+ struct lttng_log_level_rule **_rule)
+{
+ ssize_t ret;
+ size_t offset = 0;
+ struct lttng_log_level_rule *rule = NULL;
+ const struct lttng_log_level_rule_comm *comm =
+ (const struct lttng_log_level_rule_comm *)
+ view->buffer.data;
+
+ offset += sizeof(*comm);
+
+ if (!_rule) {
+ ret = -1;
+ goto end;
+ }
+
+ if (view->buffer.size < sizeof(*comm)) {
+ ret = -1;
+ goto end;
+ }
+
+ switch (comm->type) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ rule = lttng_log_level_rule_exactly_create((int) comm->level);
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ rule = lttng_log_level_rule_at_least_as_severe_as_create(
+ (int) comm->level);
+ break;
+ default:
+ abort();
+ }
+
+ if (!rule) {
+ ret = -1;
+ goto end;
+ }
+
+ *_rule = rule;
+ ret = offset;
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int lttng_log_level_rule_serialize(const struct lttng_log_level_rule *rule,
+ struct lttng_payload *payload)
+{
+ int ret;
+ struct lttng_log_level_rule_comm comm;
+
+
+ if (!rule) {
+ ret = 0;
+ goto end;
+ }
+
+ comm.type = (int8_t) rule->type;
+ comm.level = (int32_t) rule->level;
+
+ DBG("Serializing log level rule of type %d", rule->type);
+ ret = lttng_dynamic_buffer_append(&payload->buffer, &comm,
+ sizeof(comm));
+ if (ret) {
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+bool lttng_log_level_rule_is_equal(const struct lttng_log_level_rule *a,
+ const struct lttng_log_level_rule *b)
+{
+ bool is_equal = false;
+
+ if (a == NULL && b == NULL) {
+ /* Both are null. */
+ is_equal = true;
+ goto end;
+ }
+
+ if (a == NULL || b == NULL) {
+ /* One is NULL.*/
+ goto end;
+ }
+
+ if (a == b) {
+ /* Same object.*/
+ is_equal = true;
+ goto end;
+ }
+
+ if (a->type != b->type) {
+ goto end;
+ }
+
+ if (a->level != b->level) {
+ goto end;
+ }
+
+ is_equal = true;
+
+end:
+ return is_equal;
+}
+
+LTTNG_HIDDEN
+struct lttng_log_level_rule *lttng_log_level_rule_copy(
+ const struct lttng_log_level_rule *source)
+{
+ struct lttng_log_level_rule *copy = NULL;
+
+ assert(source);
+
+ copy = zmalloc(sizeof(struct lttng_log_level_rule));
+ if (!copy) {
+ goto end;
+ }
+
+ copy->type = source->type;
+ copy->level = source->level;
+end:
+ return copy;
+}
+
+LTTNG_HIDDEN
+void lttng_log_level_rule_to_loglevel(
+ const struct lttng_log_level_rule *log_level_rule,
+ enum lttng_loglevel_type *loglevel_type,
+ int *loglevel_value)
+{
+ assert(log_level_rule);
+
+ switch (log_level_rule->type) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ *loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ *loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
+ break;
+ default:
+ abort();
+ }
+
+ *loglevel_value = log_level_rule->level;
+}
+
+LTTNG_HIDDEN
+unsigned long lttng_log_level_rule_hash(
+ const struct lttng_log_level_rule *log_level_rule)
+{
+ unsigned long hash;
+ enum lttng_log_level_rule_status llr_status;
+ int log_level_value;
+ enum lttng_log_level_rule_type type;
+
+ assert(log_level_rule);
+
+ type = lttng_log_level_rule_get_type(log_level_rule);
+
+ switch (type) {
+ case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
+ llr_status = lttng_log_level_rule_exactly_get_level(
+ log_level_rule, &log_level_value);
+ break;
+ case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
+ llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
+ log_level_rule, &log_level_value);
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
+
+ hash = hash_key_ulong((void *) (unsigned long) type, lttng_ht_seed);
+
+ hash ^= hash_key_ulong((void *) (unsigned long) log_level_value,
+ lttng_ht_seed);
+
+ return hash;
+}
test_fd_tracker \
test_kernel_data \
test_kernel_probe \
+ test_log_level_rule \
test_notification \
test_payload \
test_relayd_backward_compat_group_by_session \
test_fd_tracker \
test_kernel_data \
test_kernel_probe \
+ test_log_level_rule \
test_notification \
test_payload \
test_relayd_backward_compat_group_by_session \
# Event expression to bytecode test
test_event_expr_to_bytecode_SOURCES = test_event_expr_to_bytecode.c
test_event_expr_to_bytecode_LDADD = $(LIBTAP) $(LIBLTTNG_CTL) $(LIBCOMMON)
+
+# Log level rule api
+test_log_level_rule_SOURCES = test_log_level_rule.c
+test_log_level_rule_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBLTTNG_CTL) $(DL_LIBS)
#include <lttng/condition/condition-internal.h>
#include <lttng/condition/on-event.h>
#include <lttng/domain.h>
+#include <lttng/log-level-rule.h>
#include <common/dynamic-buffer.h>
#include <common/buffer-view.h>
const char *pattern="my_event_*";
const char *filter="msg_id == 23 && size >= 2048";
const char *exclusions[] = { "my_event_test1", "my_event_test2", "my_event_test3" };
+ struct lttng_log_level_rule *log_level_rule_at_least_as_severe = NULL;
struct lttng_payload buffer;
lttng_payload_init(&buffer);
+ /* Create log level rule. */
+ log_level_rule_at_least_as_severe =
+ lttng_log_level_rule_at_least_as_severe_as_create(
+ LTTNG_LOGLEVEL_WARNING);
+ assert(log_level_rule_at_least_as_severe);
+
tracepoint = lttng_event_rule_tracepoint_create(LTTNG_DOMAIN_UST);
ok(tracepoint, "tracepoint UST_DOMAIN");
status = lttng_event_rule_tracepoint_set_filter(tracepoint, filter);
ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting filter");
- status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
- tracepoint, LTTNG_LOGLEVEL_WARNING);
+ status = lttng_event_rule_tracepoint_set_log_level_rule(
+ tracepoint, log_level_rule_at_least_as_severe);
ok(status == LTTNG_EVENT_RULE_STATUS_OK, "Setting log level range");
for (i = 0; i < 3; i++) {
lttng_event_rule_destroy(tracepoint);
lttng_condition_destroy(condition);
lttng_condition_destroy(condition_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule_at_least_as_severe);
}
int main(int argc, const char *argv[])
int lttng_opt_verbose;
int lttng_opt_mi;
-#define NUM_TESTS 184
+#define NUM_TESTS 144
struct tracepoint_test {
enum lttng_domain_type type;
static
void test_event_rule_tracepoint_by_domain(const struct tracepoint_test *test)
{
- int ret;
unsigned int count;
struct lttng_event_rule *tracepoint = NULL;
struct lttng_event_rule *tracepoint_from_buffer = NULL;
enum lttng_event_rule_status status;
enum lttng_domain_type domain_type, type;
- enum lttng_loglevel_type log_level_type;
const char *pattern="my_event_*";
const char *filter="msg_id == 23 && size >= 2048";
const char *tmp;
const char *exclusions[] = {"my_event_test1", "my_event_test2" ,"my_event_test3"};
+ struct lttng_log_level_rule *log_level_rule = NULL;
+ const struct lttng_log_level_rule *log_level_rule_return = NULL;
struct lttng_payload payload;
type = test->type;
lttng_payload_init(&payload);
+ log_level_rule = lttng_log_level_rule_exactly_create(LTTNG_LOGLEVEL_INFO);
+ assert(log_level_rule);
+
tracepoint = lttng_event_rule_tracepoint_create(type);
ok(tracepoint, "tracepoint object.");
ok(status == LTTNG_EVENT_RULE_STATUS_OK, "getting filter.");
ok(!strncmp(filter, tmp, strlen(filter)), "filter is equal.");
- status = lttng_event_rule_tracepoint_set_log_level_all(tracepoint);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting all log level.");
- status = lttng_event_rule_tracepoint_get_log_level_type(tracepoint, &log_level_type);
- ok(log_level_type == LTTNG_EVENT_LOGLEVEL_ALL, "getting loglevel type all.");
- status = lttng_event_rule_tracepoint_get_log_level(tracepoint, &ret);
- ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset loglevel value.");
-
- status = lttng_event_rule_tracepoint_set_log_level(tracepoint, LTTNG_LOGLEVEL_INFO);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting single loglevel.");
- status = lttng_event_rule_tracepoint_get_log_level_type(tracepoint, &log_level_type);
- ok(log_level_type == LTTNG_EVENT_LOGLEVEL_SINGLE, "getting loglevel type single.");
- status = lttng_event_rule_tracepoint_get_log_level(tracepoint, &ret);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get loglevel value.");
- ok(ret == LTTNG_LOGLEVEL_INFO, "loglevel value is equal.");
-
- status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(tracepoint, LTTNG_LOGLEVEL_WARNING);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting range loglevel.");
- status = lttng_event_rule_tracepoint_get_log_level_type(tracepoint, &log_level_type);
- ok(log_level_type == LTTNG_EVENT_LOGLEVEL_RANGE, "getting loglevel type range.");
- status = lttng_event_rule_tracepoint_get_log_level(tracepoint, &ret);
- ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get loglevel value.");
- ok(ret == LTTNG_LOGLEVEL_WARNING, "loglevel valuei is equal.");
+ status = lttng_event_rule_tracepoint_get_log_level_rule(tracepoint, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_UNSET, "get unset log level rule.");
+
+ status = lttng_event_rule_tracepoint_set_log_level_rule(tracepoint, log_level_rule);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "setting log level rule.");
+ status = lttng_event_rule_tracepoint_get_log_level_rule(tracepoint, &log_level_rule_return);
+ ok(status == LTTNG_EVENT_RULE_STATUS_OK, "get log level rule.");
if (test->support_exclusion) {
int i;
lttng_payload_reset(&payload);
lttng_event_rule_destroy(tracepoint);
lttng_event_rule_destroy(tracepoint_from_buffer);
+ lttng_log_level_rule_destroy(log_level_rule);
}
static
--- /dev/null
+/*
+ * Unit tests for the log level rule API.
+ *
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/log-level-rule-internal.h>
+#include <lttng/log-level-rule.h>
+
+/* For error.h. */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 29
+
+static void test_log_level_rule_error(void)
+{
+ int level = 9000;
+ struct lttng_log_level_rule *exactly =
+ lttng_log_level_rule_exactly_create(level);
+ struct lttng_log_level_rule *at_least_as_severe =
+ lttng_log_level_rule_at_least_as_severe_as_create(
+ level);
+
+ ok(lttng_log_level_rule_get_type(NULL) == LTTNG_LOG_LEVEL_RULE_TYPE_UNKNOWN, "Get type on invalid pointer");
+
+ ok(lttng_log_level_rule_exactly_get_level(NULL, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (NULL, NULL) returns invalid");
+ ok(lttng_log_level_rule_exactly_get_level(exactly, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (valid, NULL) returns invalid");
+ ok(lttng_log_level_rule_exactly_get_level(NULL, &level) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_exactly_get_level (NULL, valid) returns invalid");
+
+ ok(lttng_log_level_rule_at_least_as_severe_as_get_level(NULL, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (NULL, NULL) returns invalid");
+ ok(lttng_log_level_rule_at_least_as_severe_as_get_level(exactly, NULL) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (valid, NULL) returns invalid");
+ ok(lttng_log_level_rule_at_least_as_severe_as_get_level(NULL, &level) == LTTNG_LOG_LEVEL_RULE_STATUS_INVALID, "lttng_log_level_rule_at_least_as_severe_as_get_level (NULL, valid) returns invalid");
+
+ lttng_log_level_rule_destroy(exactly);
+ lttng_log_level_rule_destroy(at_least_as_severe);
+}
+
+static
+void test_log_level_rule_serialize_deserialize(const struct lttng_log_level_rule *rule)
+{
+ struct lttng_log_level_rule *log_level_rule_from_buffer = NULL;
+ struct lttng_payload payload;
+
+ lttng_payload_init(&payload);
+
+ ok(lttng_log_level_rule_serialize(rule, &payload) == 0, "Serializing.");
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+
+ ok(lttng_log_level_rule_create_from_payload(
+ &view, &log_level_rule_from_buffer) > 0,
+ "Deserializing.");
+ }
+
+ ok(lttng_log_level_rule_is_equal(rule, log_level_rule_from_buffer), "Serialized and from buffer are equal");
+
+ lttng_log_level_rule_destroy(log_level_rule_from_buffer);
+}
+
+static
+void test_log_level_rule_is_equal_exactly(void)
+{
+ int level = 9000, no_eq_level = 420;
+ struct lttng_log_level_rule *a, *b, *different_level, *different_type;
+
+ /* Identical log level rules. */
+ a = lttng_log_level_rule_exactly_create(level);
+ b = lttng_log_level_rule_exactly_create(level);
+
+ /* Different level, same type. */
+ different_level = lttng_log_level_rule_exactly_create(no_eq_level);
+
+ /* Different type. */
+ different_type = lttng_log_level_rule_at_least_as_severe_as_create(level);
+
+ assert(a && b && different_level && different_type);
+
+ ok(lttng_log_level_rule_is_equal(a, a), "Same object is equal");
+ ok(lttng_log_level_rule_is_equal(a, b), "Object a and b are equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_level), " Object of different levels are not equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_type), " Object of different types are not equal");
+
+ lttng_log_level_rule_destroy(a);
+ lttng_log_level_rule_destroy(b);
+ lttng_log_level_rule_destroy(different_level);
+ lttng_log_level_rule_destroy(different_type);
+}
+
+static
+void test_log_level_rule_is_equal_at_least_as_severe_as(void)
+{
+ int level = 9000, no_eq_level = 420;
+ struct lttng_log_level_rule *a, *b, *different_level, *different_type;
+
+ /* Identical log level rules. */
+ a = lttng_log_level_rule_at_least_as_severe_as_create(level);
+ b = lttng_log_level_rule_at_least_as_severe_as_create(level);
+
+ /* Different level, same type. */
+ different_level = lttng_log_level_rule_at_least_as_severe_as_create(no_eq_level);
+
+ /* Different type. */
+ different_type = lttng_log_level_rule_exactly_create(level);
+
+ assert(a && b && different_level && different_type);
+
+ ok(lttng_log_level_rule_is_equal(a, a), "Same object is equal");
+ ok(lttng_log_level_rule_is_equal(a, b), "Object a and b are equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_level), " Object of different levels are not equal");
+ ok(!lttng_log_level_rule_is_equal(a, different_type), " Object of different types are not equal");
+
+ lttng_log_level_rule_destroy(a);
+ lttng_log_level_rule_destroy(b);
+ lttng_log_level_rule_destroy(different_level);
+ lttng_log_level_rule_destroy(different_type);
+}
+
+static void test_log_level_rule_exactly(void)
+{
+ int level = 9000;
+ int _level;
+ struct lttng_log_level_rule *exactly = NULL;
+ enum lttng_log_level_rule_status status;
+
+ exactly = lttng_log_level_rule_exactly_create(level);
+
+ ok(exactly, "Log level exactly allocated");
+ ok(lttng_log_level_rule_get_type(exactly) ==
+ LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY,
+ "Log level rule exactly type");
+
+ status = lttng_log_level_rule_exactly_get_level(exactly, &_level);
+ ok(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK, "Get the level");
+ ok(_level == level, "Level property is valid");
+
+ test_log_level_rule_is_equal_exactly();
+ test_log_level_rule_serialize_deserialize(exactly);
+}
+
+static void test_log_level_rule_at_least_as_severe_as(void)
+{
+ int level = 9000;
+ int _level;
+ struct lttng_log_level_rule *at_least_as_severe_as = NULL;
+ enum lttng_log_level_rule_status status;
+
+ at_least_as_severe_as = lttng_log_level_rule_at_least_as_severe_as_create(level);
+
+ ok(at_least_as_severe_as, "Log level at_least_as_severe_as allocated");
+ ok(lttng_log_level_rule_get_type(at_least_as_severe_as) ==
+ LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS,
+ "Log level rule at_least_as_severe_as type");
+
+ status = lttng_log_level_rule_at_least_as_severe_as_get_level(at_least_as_severe_as, &_level);
+ ok(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK, "Get the level");
+ ok(_level == level, "Level property is valid");
+
+ test_log_level_rule_is_equal_at_least_as_severe_as();
+ test_log_level_rule_serialize_deserialize(at_least_as_severe_as);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_log_level_rule_exactly();
+ test_log_level_rule_at_least_as_severe_as();
+ test_log_level_rule_error();
+ return exit_status();
+}