OTELC_DBG(DEBUG, h "%p:{ '%s' %p }", (p), (p)->fmt_expr, (p)->expr)
#define FLT_OTEL_DBG_CONF_SAMPLE(h,p) \
- OTELC_DBG(DEBUG, h "%p:{ '%s' '%s' %s %s %d }", (p), \
+ OTELC_DBG(DEBUG, h "%p:{ '%s' '%s' %s %s %d %p %hhu }", (p), \
(p)->key, (p)->fmt_string, otelc_value_dump(&((p)->extra), ""), \
- flt_otel_list_dump(&((p)->exprs)), (p)->num_exprs)
+ flt_otel_list_dump(&((p)->exprs)), (p)->num_exprs, &((p)->lf_expr), (p)->lf_used)
#define FLT_OTEL_DBG_CONF_HDR(h,p,i) \
OTELC_DBG_STRUCT(DEBUG, h, h FLT_OTEL_CONF_HDR_FMT "}", (p), FLT_OTEL_CONF_HDR_ARGS(p, i))
struct otelc_value extra; /* Optional supplementary data. */
struct list exprs; /* Used to chain sample expressions. */
int num_exprs; /* Number of defined expressions. */
+ struct lf_expr lf_expr; /* The log-format expression. */
+ bool lf_used; /* Whether lf_expr is used instead of exprs. */
};
/*
* err - indirect pointer to error message string
*
* DESCRIPTION
- * Parses a complete sample definition starting at index <idx> in <args>.
- * Creates a conf_sample structure with optional <extra> data (event name or
- * status code), then parses sample expressions. When <n> is 0, all remaining
- * arguments are parsed; otherwise at most <n> expressions are parsed.
+ * Parses a complete sample definition starting at index <idx> in the
+ * <args> array. A new conf_sample structure is allocated and initialized
+ * via flt_otel_conf_sample_init_ex() with the optional <extra> data (an
+ * event name or a status code), then the sample expressions are parsed.
+ *
+ * When <args>[<idx>] contains the "%[" sequence, the argument is parsed
+ * as a log-format string via parse_logformat_string(): the lf_used flag
+ * is set and the result is stored in the lf_expr member while the exprs
+ * list remains empty. Otherwise the arguments are treated as bare sample
+ * expressions: the proxy configuration context is set and the function
+ * calls flt_otel_parse_cfg_sample_expr() in a loop to populate exprs.
+ *
+ * When <n> is 0 all remaining valid arguments are consumed; otherwise at
+ * most <n> expressions are parsed. On error the allocated conf_sample
+ * structure is freed before returning.
*
* RETURN VALUE
* Returns ERR_NONE (== 0) in case of success, or a combination of ERR_* flags
if (sample == NULL)
FLT_OTEL_PARSE_ERR(err, "'%s' : out of memory", args[0]);
- if (!(retval & ERR_CODE)) {
+ if (retval & ERR_CODE) {
+ /* Do nothing. */
+ }
+ else if (strstr(args[idx], "%[") != NULL) {
+ /*
+ * Log-format path: parse the single argument as a log-format
+ * string into the sample structure.
+ */
+ sample->lf_used = 1;
+
+ if (parse_logformat_string(args[idx], flt_otel_current_config->proxy, &(sample->lf_expr), LOG_OPT_HTTP, SMP_VAL_FE_LOG_END, err) == 0)
+ retval |= ERR_ABORT | ERR_ALERT;
+ else
+ OTELC_DBG(DEBUG, "sample '%s' -> log-format '%s' added", sample->key, sample->fmt_string);
+ }
+ else {
+ /*
+ * Bare sample expression path.
+ */
flt_otel_current_config->proxy->conf.args.ctx = ARGC_OTEL;
flt_otel_current_config->proxy->conf.args.file = file;
flt_otel_current_config->proxy->conf.args.line = line;
(void)memset(&value, 0, sizeof(value));
(void)memset(&buffer, 0, sizeof(buffer));
- list_for_each_entry(expr, &(sample->exprs), list) {
- FLT_OTEL_DBG_CONF_SAMPLE_EXPR("sample expression ", expr);
-
- (void)memset(&smp, 0, sizeof(smp));
+ /* Evaluate the sample: log-format path or expression list path. */
+ if (sample->lf_used) {
+ /*
+ * Log-format path: evaluate the log-format expression into a
+ * dynamically allocated buffer.
+ */
+ chunk_init(&buffer, OTELC_CALLOC(1, global.tune.bufsize), global.tune.bufsize);
+ if (buffer.area == NULL) {
+ FLT_OTEL_ERR("out of memory");
- if (sample_process(s->be, s->sess, s, dir | SMP_OPT_FINAL, expr->expr, &smp) != NULL) {
- OTELC_DBG(DEBUG, "data type %d: '%s'", smp.data.type, expr->fmt_expr);
+ retval = FLT_OTEL_RET_ERROR;
} else {
- OTELC_DBG(NOTICE, "WARNING: failed to fetch '%s' value", expr->fmt_expr);
+ buffer.data = build_logline(s, buffer.area, buffer.size, &(sample->lf_expr));
- /*
- * In case the fetch failed, we will set the result
- * (sample) to an empty static string.
- */
- (void)memset(&(smp.data), 0, sizeof(smp.data));
- smp.data.type = SMP_T_STR;
- smp.data.u.str.area = "";
+ value.u_type = OTELC_VALUE_DATA;
+ value.u.value_data = buffer.area;
}
+ } else {
+ list_for_each_entry(expr, &(sample->exprs), list) {
+ FLT_OTEL_DBG_CONF_SAMPLE_EXPR("sample expression ", expr);
- /*
- * If we have only one expression to process, then the data
- * type that is the result of the expression is converted to
- * an equivalent data type (if possible) that is written to
- * the tracer.
- *
- * If conversion is not possible, or if we have multiple
- * expressions to process, then the result is converted to
- * a string and as such sent to the tracer.
- */
- if ((sample->num_exprs == 1) && ((type == FLT_OTEL_EVENT_SAMPLE_ATTRIBUTE) || (type == FLT_OTEL_EVENT_SAMPLE_EVENT))) {
- if (flt_otel_sample_to_value(sample->key, &(smp.data), &value, err) == FLT_OTEL_RET_ERROR)
- retval = FLT_OTEL_RET_ERROR;
- } else {
- if (buffer.area == NULL) {
- chunk_init(&buffer, OTELC_CALLOC(1, global.tune.bufsize), global.tune.bufsize);
- if (buffer.area == NULL) {
- FLT_OTEL_ERR("out of memory");
+ (void)memset(&smp, 0, sizeof(smp));
+ if (sample_process(s->be, s->sess, s, dir | SMP_OPT_FINAL, expr->expr, &smp) != NULL) {
+ OTELC_DBG(DEBUG, "data type %d: '%s'", smp.data.type, expr->fmt_expr);
+ } else {
+ OTELC_DBG(NOTICE, "WARNING: failed to fetch '%s' value", expr->fmt_expr);
+
+ /*
+ * In case the fetch failed, we will set the result
+ * (sample) to an empty static string.
+ */
+ (void)memset(&(smp.data), 0, sizeof(smp.data));
+ smp.data.type = SMP_T_STR;
+ smp.data.u.str.area = "";
+ }
+
+ /*
+ * If we have only one expression to process, then the data
+ * type that is the result of the expression is converted to
+ * an equivalent data type (if possible) that is written to
+ * the tracer.
+ *
+ * If conversion is not possible, or if we have multiple
+ * expressions to process, then the result is converted to
+ * a string and as such sent to the tracer.
+ */
+ if ((sample->num_exprs == 1) && ((type == FLT_OTEL_EVENT_SAMPLE_ATTRIBUTE) || (type == FLT_OTEL_EVENT_SAMPLE_EVENT))) {
+ if (flt_otel_sample_to_value(sample->key, &(smp.data), &value, err) == FLT_OTEL_RET_ERROR)
retval = FLT_OTEL_RET_ERROR;
+ } else {
+ if (buffer.area == NULL) {
+ chunk_init(&buffer, OTELC_CALLOC(1, global.tune.bufsize), global.tune.bufsize);
+ if (buffer.area == NULL) {
+ FLT_OTEL_ERR("out of memory");
+
+ retval = FLT_OTEL_RET_ERROR;
- break;
+ break;
+ }
}
- }
- rc = flt_otel_sample_to_str(&(smp.data), buffer.area + buffer.data, buffer.size - buffer.data, err);
- if (rc == FLT_OTEL_RET_ERROR) {
- retval = FLT_OTEL_RET_ERROR;
- } else {
- buffer.data += rc;
+ rc = flt_otel_sample_to_str(&(smp.data), buffer.area + buffer.data, buffer.size - buffer.data, err);
+ if (rc == FLT_OTEL_RET_ERROR) {
+ retval = FLT_OTEL_RET_ERROR;
+ } else {
+ buffer.data += rc;
- if (sample->num_exprs == ++idx) {
- value.u_type = OTELC_VALUE_DATA;
- value.u.value_data = buffer.area;
+ if (sample->num_exprs == ++idx) {
+ value.u_type = OTELC_VALUE_DATA;
+ value.u.value_data = buffer.area;
+ }
}
}
}