To update an existing instrument (previously created in another scope), use
'update' followed by the name of the instrument. Optional attributes can be
- added using the 'attr' keyword followed by key-value pairs.
+ added using the 'attr' keyword followed by a key and a sample expression
+ evaluated at runtime.
Supported instrument types:
- cnt_int : counter (uint64)
instrument cnt_int "my_counter" desc "Counter" value int(1)
instrument hist_int "my_hist" aggr exp_histogram desc "Latency" value lat_ns_tot unit "ns"
instrument hist_int "my_hist2" desc "Latency" value lat_ns_tot unit "ns" bounds "100 1000 10000 100000"
- instrument update "my_counter" attr "key1" "val1"
+ instrument update "my_counter" attr "key1" str("val1")
Arguments :
type - the instrument type (see list above)
unit - optional unit string for the instrument
value - sample expression providing the measurement value
bounds - optional histogram bucket boundaries (hist_int only)
- attr - attribute key-value pairs (update form only)
+ attr - attribute key and sample expression (update form only)
log-record <severity> [id <integer>] [event <name>] [span <span-name>] [attr <key> <sample>] ... <sample> ...
samples Sample expressions for the value.
bounds Histogram bucket boundaries (create only).
bounds_num Number of histogram bucket boundaries.
- attr Instrument attributes (update only).
- attr_len Number of instrument attributes.
+ attributes Instrument attributes (update only, flt_otel_conf_sample).
ref Resolved create-form instrument (update only).
Instruments come in two forms: create-form (defines a new metric with type,
description, unit, and optional histogram bounds) and update-form (references
-an existing instrument via the ref pointer).
+an existing instrument via the ref pointer). Update-form attributes are stored
+as flt_otel_conf_sample entries and evaluated at runtime.
4.7 flt_otel_conf_log_record
instrument <type> <name> [aggr <aggregation>] [desc <description>] [unit <unit>] value <sample> [bounds <bounds>]
- instrument update <name> [attr <key> <value> ...]
+ instrument update <name> [attr <key> <sample> ...]
Create or update a metric instrument.
Supported types:
instrument cnt_int "name_cnt_int" desc "Integer Counter" value int(1),add(2) unit "unit"
instrument hist_int "name_hist" aggr exp_histogram desc "Latency" value lat_ns_tot unit "ns"
instrument hist_int "name_hist2" desc "Latency" value lat_ns_tot unit "ns" bounds "100 1000 10000"
- instrument update "name_cnt_int" attr "attr_1_key" "attr_1_value"
+ instrument update "name_cnt_int" attr "attr_1_key" str("attr_1_value")
log-record <severity> [id <integer>] [event <name>] [span <span-name>] [attr <key> <sample>] ... <sample> ...
Event dispatching, metrics recording and scope/span execution engine.
flt_otel_scope_run_instrument_record
- Records a measurement for a synchronous metric instrument. Evaluates the
- sample expression from the create-form instrument (instr_ref) and submits
- the value to the meter via update_instrument_kv_n(), using per-scope
- attributes from the update-form instrument (instr).
+ Records a measurement for a synchronous metric instrument. Evaluates
+ update-form attributes via flt_otel_sample_eval() and
+ flt_otel_sample_add_kv(), evaluates the sample expression from the
+ create-form instrument (instr_ref), and submits the value to the meter
+ via update_instrument_kv_n().
flt_otel_scope_run_instrument
Processes all metric instruments for a scope. Runs in two passes: the
samples List of sample expressions for the instrument value.
bounds Histogram bucket boundaries array (create-form only).
bounds_num Number of histogram bucket boundaries.
- attr Key-value attribute array (update-form only).
- attr_len Number of attributes.
+ attributes List of flt_otel_conf_sample entries (update-form only).
ref Pointer to the create-form instrument (update-form only).
18.5.3 Meter Initialization and Startup
flt_otel_list_dump(&((p)->ph_scopes)))
#define FLT_OTEL_DBG_CONF_INSTRUMENT(h,p) \
- OTELC_DBG_STRUCT(DEBUG, h, h FLT_OTEL_CONF_HDR_FMT "%" PRId64 " %d %d '%s' '%s' %s %p %zu %p %zu %p }", (p), \
+ OTELC_DBG_STRUCT(DEBUG, h, h FLT_OTEL_CONF_HDR_FMT "%" PRId64 " %d %d '%s' '%s' %s %s %p %zu %p }", (p), \
FLT_OTEL_CONF_HDR_ARGS(p, id), (p)->idx, (p)->type, (p)->aggr_type, OTELC_STR_ARG((p)->description), \
- OTELC_STR_ARG((p)->unit), flt_otel_list_dump(&((p)->samples)), (p)->attr, (p)->attr_len, (p)->ref, \
- (p)->bounds_num, (p)->bounds)
+ OTELC_STR_ARG((p)->unit), flt_otel_list_dump(&((p)->samples)), flt_otel_list_dump(&((p)->attributes)), \
+ (p)->ref, (p)->bounds_num, (p)->bounds)
#define FLT_OTEL_DBG_CONF_LOG_RECORD(h,p) \
OTELC_DBG_STRUCT(DEBUG, h, h FLT_OTEL_CONF_HDR_FMT "%d %" PRId64 " '%s' '%s' %s %s }", (p), \
struct list samples; /* Sample expressions for the value. */
double *bounds; /* Histogram bucket boundaries (create only). */
size_t bounds_num; /* Number of histogram bucket boundaries. */
- struct otelc_kv *attr; /* Instrument attributes (update only). */
- size_t attr_len; /* Number of instrument attributes. */
+ struct list attributes; /* Instrument attributes (update only, flt_otel_conf_sample). */
struct flt_otel_conf_instrument *ref; /* Resolved create-form instrument (update only). */
};
* DESCRIPTION
* Allocates and initializes a conf_instrument structure. Sets the instrument
* type and meter index to OTELC_METRIC_INSTRUMENT_UNSET and initializes the
- * samples list. The <id> string is duplicated and stored as the instrument
- * name. If <head> is non-NULL, the structure is appended to the list.
+ * samples and attributes lists. The <id> string is duplicated and stored as
+ * the instrument name. If <head> is non-NULL, the structure is appended to
+ * the list.
*
* RETURN VALUE
* Returns a pointer to the initialized structure, or NULL on failure.
retptr->type = OTELC_METRIC_INSTRUMENT_UNSET;
retptr->aggr_type = OTELC_METRIC_AGGREGATION_UNSET;
LIST_INIT(&(retptr->samples));
+ LIST_INIT(&(retptr->attributes));
)
OTELC_SFREE((*ptr)->unit);
FLT_OTEL_LIST_DESTROY(sample, &((*ptr)->samples));
OTELC_SFREE((*ptr)->bounds);
- otelc_kv_destroy(&((*ptr)->attr), (*ptr)->attr_len);
+ FLT_OTEL_LIST_DESTROY(sample, &((*ptr)->attributes));
)
struct flt_otel_conf_sample_expr *expr;
struct sample smp;
struct otelc_value value;
+ struct flt_otel_scope_data_kv instr_attr;
int retval = FLT_OTEL_RET_OK;
OTELC_FUNC("%p, %u, %p, %p, %p, %p:%p", s, dir, meter, instr_ref, instr, OTELC_DPTR_ARGS(err));
+ /* Evaluate instrument attributes from sample expressions. */
+ (void)memset(&instr_attr, 0, sizeof(instr_attr));
+
+ list_for_each_entry(sample, &(instr->attributes), list) {
+ struct otelc_value attr_value;
+
+ OTELC_DBG(DEBUG, "adding instrument attribute '%s' -> '%s'", sample->key, sample->fmt_string);
+
+ if (flt_otel_sample_eval(s, dir, sample, true, &attr_value, err) == FLT_OTEL_RET_ERROR) {
+ retval = FLT_OTEL_RET_ERROR;
+
+ continue;
+ }
+
+ if (flt_otel_sample_add_kv(&instr_attr, sample->key, &attr_value) == FLT_OTEL_RET_ERROR) {
+ if (attr_value.u_type == OTELC_VALUE_DATA)
+ OTELC_SFREE(attr_value.u.value_data);
+
+ retval = FLT_OTEL_RET_ERROR;
+ }
+ }
+
/* The samples list always contains exactly one entry. */
sample = LIST_NEXT(&(instr_ref->samples), struct flt_otel_conf_sample *, list);
if (smp.data.u.str.area == NULL) {
FLT_OTEL_ERR("out of memory");
+ otelc_kv_destroy(&(instr_attr.attr), instr_attr.cnt);
+
OTELC_RETURN_INT(FLT_OTEL_RET_ERROR);
}
}
if (retval != FLT_OTEL_RET_ERROR)
- if (OTELC_OPS(meter, update_instrument_kv_n, HA_ATOMIC_LOAD(&(instr_ref->idx)), &value, instr->attr, instr->attr_len) == OTELC_RET_ERROR)
+ if (OTELC_OPS(meter, update_instrument_kv_n, HA_ATOMIC_LOAD(&(instr_ref->idx)), &value, instr_attr.attr, instr_attr.cnt) == OTELC_RET_ERROR)
retval = FLT_OTEL_RET_ERROR;
}
+ otelc_kv_destroy(&(instr_attr.attr), instr_attr.cnt);
+
if (sample->lf_used)
OTELC_SFREE(smp.data.u.str.area);
if (flag_add_attr) {
if (!FLT_OTEL_ARG_ISVALID(i) || !FLT_OTEL_ARG_ISVALID(i + 1))
FLT_OTEL_PARSE_ERR(err, "'%s' : too few arguments (use '%s%s')", args[i], pdata->name, pdata->usage);
- else if (otelc_kv_add(&(instr->attr), &(instr->attr_len), args[i], args[i + 1], strlen(args[i + 1])) == OTELC_RET_ERROR)
- FLT_OTEL_PARSE_ERR(err, "'%s' : out of memory", args[0]);
- else
- i++;
+ else {
+ retval = flt_otel_parse_cfg_sample(file, line, args, i + 1, 1, NULL, &(instr->attributes), err);
+ if (!(retval & ERR_CODE))
+ i++;
+ }
}
else if (FLT_OTEL_PARSE_KEYWORD(i, FLT_OTEL_PARSE_INSTRUMENT_ATTR)) {
flag_add_attr = true;
}
}
- if (flag_add_attr && (instr->attr_len == 0))
+ if (flag_add_attr && LIST_ISEMPTY(&(instr->attributes)))
FLT_OTEL_PARSE_ERR(err, "'%s' : too few arguments (use '%s%s')", args[i], pdata->name, pdata->usage);
}
else {
otel-scope frontend_http_request
instrument cnt_int "haproxy.http.requests" desc "HTTP request count" value int(1) unit "{request}"
instrument hist_int "haproxy.http.latency" desc "HTTP request latency" value lat_ns_tot unit "ns" aggr "histogram" bounds "1000 1000000 1000000000"
- instrument update "haproxy.http.latency" attr "phase" "request"
+ instrument update "haproxy.http.latency" attr "phase" str("request")
instrument update "haproxy.tcp.request.fe"
span "Frontend HTTP request" parent "HTTP body request" link "HAProxy session"
attribute "http.method" method
otel-event on-process-store-rules-response
otel-scope http_response
- instrument update "haproxy.http.requests" attr "phase" "response"
- instrument update "haproxy.http.latency" attr "phase" "response"
+ instrument update "haproxy.http.requests" attr "phase" str("response")
+ instrument update "haproxy.http.latency" attr "phase" str("response")
instrument update "haproxy.fe.connections"
span "HTTP response" parent "Process store rules response"
attribute "http.status_code" status
otel-scope frontend_http_request
instrument cnt_int "haproxy.http.requests" desc "HTTP request count" value int(1) unit "{request}"
instrument hist_int "haproxy.http.latency" desc "HTTP request latency" value lat_ns_tot unit "ns"
- instrument update "haproxy.http.latency" attr "phase" "request"
+ instrument update "haproxy.http.latency" attr "phase" str("request")
span "Frontend HTTP request" parent "HTTP body request" link "HAProxy session"
attribute "http.method" method
attribute "http.url" url
otel-event on-process-store-rules-response
otel-scope http_response
- instrument update "haproxy.http.requests" attr "phase" "response"
- instrument update "haproxy.http.latency" attr "phase" "response"
+ instrument update "haproxy.http.requests" attr "phase" str("response")
+ instrument update "haproxy.http.latency" attr "phase" str("response")
instrument update "haproxy.fe.connections"
span "HTTP response" parent "Process store rules response"
attribute "http.status_code" status