mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-04-18 12:14:56 +02:00
MEDIUM: otel: added memory pool and runtime scope layer
Added the memory pool management and the runtime scope layer that track per-stream OTel spans and contexts during request processing. The pool layer in pool.c manages HAProxy memory pools for the runtime structures used by the filter: scope spans, scope contexts, runtime contexts, and span contexts. Each pool is conditionally compiled via USE_POOL_OTEL_* macros defined in config.h and registered with REGISTER_POOL(). The allocation functions (flt_otel_pool_alloc, flt_otel_pool_strndup, flt_otel_pool_free) transparently fall back to heap allocation when the corresponding pool is not enabled. Trash buffer helpers (flt_otel_trash_alloc, flt_otel_trash_free) provide scratch space using either HAProxy's trash chunk pool or direct heap allocation. The scope layer in scope.c implements the per-stream runtime state. The flt_otel_runtime_context structure is allocated when a stream starts and holds the stream and filter references, hard-error/disabled/logging flags copied from the instrumentation configuration, idle timeout state, a generated UUID, and lists of active scope spans and extracted scope contexts. Scope spans (flt_otel_scope_span) carry the operation name, fetch direction, the OTel span handle, and optional parent references resolved from other spans or extracted contexts. Scope contexts (flt_otel_scope_context) hold an extracted span context obtained from a carrier text map via the tracer. The scope data structures (flt_otel_scope_data) aggregate growable key-value arrays for attributes and baggage, a linked list of named events with their own attribute arrays, and a span status code with description, representing the telemetry collected during a single event execution.
This commit is contained in:
parent
c0fd39457f
commit
f05a6735b1
@ -55,6 +55,8 @@ OPTIONS_OBJS += \
|
||||
addons/otel/src/event.o \
|
||||
addons/otel/src/filter.o \
|
||||
addons/otel/src/parser.o \
|
||||
addons/otel/src/pool.o \
|
||||
addons/otel/src/scope.o \
|
||||
addons/otel/src/util.o
|
||||
|
||||
OTEL_CFLAGS := $(OTEL_CFLAGS) -Iaddons/otel/include $(OTEL_DEFINE)
|
||||
|
||||
@ -3,6 +3,14 @@
|
||||
#ifndef _OTEL_CONFIG_H_
|
||||
#define _OTEL_CONFIG_H_
|
||||
|
||||
/* Memory pool selection flags. */
|
||||
#define USE_POOL_BUFFER
|
||||
#define USE_POOL_OTEL_SPAN_CONTEXT
|
||||
#define USE_POOL_OTEL_SCOPE_SPAN
|
||||
#define USE_POOL_OTEL_SCOPE_CONTEXT
|
||||
#define USE_POOL_OTEL_RUNTIME_CONTEXT
|
||||
#define USE_TRASH_CHUNK
|
||||
|
||||
#define FLT_OTEL_ID_MAXLEN 64 /* Maximum identifier length. */
|
||||
#define FLT_OTEL_DEBUG_LEVEL 0b11101111111 /* Default debug bitmask. */
|
||||
|
||||
|
||||
@ -32,6 +32,8 @@
|
||||
#include "conf_funcs.h"
|
||||
#include "filter.h"
|
||||
#include "parser.h"
|
||||
#include "pool.h"
|
||||
#include "scope.h"
|
||||
#include "util.h"
|
||||
|
||||
#endif /* _OTEL_INCLUDE_H_ */
|
||||
|
||||
71
addons/otel/include/pool.h
Normal file
71
addons/otel/include/pool.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#ifndef _OTEL_POOL_H_
|
||||
#define _OTEL_POOL_H_
|
||||
|
||||
#define FLT_OTEL_POOL_INIT(p,n,s,r) \
|
||||
do { \
|
||||
if (((r) == FLT_OTEL_RET_OK) && ((p) == NULL)) { \
|
||||
(p) = create_pool(n, (s), MEM_F_SHARED); \
|
||||
if ((p) == NULL) \
|
||||
(r) = FLT_OTEL_RET_ERROR; \
|
||||
\
|
||||
OTELC_DBG(DEBUG, #p " %p %u", (p), FLT_OTEL_DEREF((p), size, 0)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FLT_OTEL_POOL_DESTROY(p) \
|
||||
do { \
|
||||
if ((p) != NULL) { \
|
||||
OTELC_DBG(DEBUG, #p " %p %u", (p), (p)->size); \
|
||||
\
|
||||
pool_destroy(p); \
|
||||
(p) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
extern struct pool_head *pool_head_otel_scope_span __read_mostly;
|
||||
extern struct pool_head *pool_head_otel_scope_context __read_mostly;
|
||||
extern struct pool_head *pool_head_otel_runtime_context __read_mostly;
|
||||
extern struct pool_head *pool_head_otel_span_context __read_mostly;
|
||||
|
||||
|
||||
/* Allocate memory from a pool with optional zeroing. */
|
||||
void *flt_otel_pool_alloc(struct pool_head *pool, size_t size, bool flag_clear, char **err);
|
||||
|
||||
/* Duplicate a string into pool-allocated memory. */
|
||||
void *flt_otel_pool_strndup(struct pool_head *pool, const char *s, size_t size, char **err);
|
||||
|
||||
/* Release pool-allocated memory and clear the pointer. */
|
||||
void flt_otel_pool_free(struct pool_head *pool, void **ptr);
|
||||
|
||||
/* Initialize OTel filter memory pools. */
|
||||
int flt_otel_pool_init(void);
|
||||
|
||||
/* Destroy OTel filter memory pools. */
|
||||
void flt_otel_pool_destroy(void);
|
||||
|
||||
/* Log debug information about OTel filter memory pools. */
|
||||
#ifndef DEBUG_OTEL
|
||||
# define flt_otel_pool_info() while (0)
|
||||
#else
|
||||
void flt_otel_pool_info(void);
|
||||
#endif
|
||||
|
||||
/* Allocate a trash buffer with optional zeroing. */
|
||||
struct buffer *flt_otel_trash_alloc(bool flag_clear, char **err);
|
||||
|
||||
/* Release a trash buffer and clear the pointer. */
|
||||
void flt_otel_trash_free(struct buffer **ptr);
|
||||
|
||||
#endif /* _OTEL_POOL_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*
|
||||
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||
*/
|
||||
158
addons/otel/include/scope.h
Normal file
158
addons/otel/include/scope.h
Normal file
@ -0,0 +1,158 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#ifndef _OTEL_SCOPE_H_
|
||||
#define _OTEL_SCOPE_H_
|
||||
|
||||
#define FLT_OTEL_SCOPE_SPAN_FINISH_REQ "*req*"
|
||||
#define FLT_OTEL_SCOPE_SPAN_FINISH_RES "*res*"
|
||||
#define FLT_OTEL_SCOPE_SPAN_FINISH_ALL "*"
|
||||
|
||||
#define FLT_OTEL_RT_CTX(p) ((struct flt_otel_runtime_context *)(p))
|
||||
|
||||
#define FLT_OTEL_DBG_SCOPE_SPAN(h,p) \
|
||||
OTELC_DBG(DEBUG, h "%p:{ '%s' %zu %u %hhu %p %p %p }", (p), \
|
||||
FLT_OTEL_STR_HDR_ARGS(p, id), (p)->smp_opt_dir, \
|
||||
(p)->flag_finish, (p)->span, (p)->ref_span, (p)->ref_ctx)
|
||||
|
||||
#define FLT_OTEL_DBG_SCOPE_CONTEXT(h,p) \
|
||||
OTELC_DBG(DEBUG, h "%p:{ '%s' %zu %u %hhu %p }", (p), \
|
||||
FLT_OTEL_STR_HDR_ARGS(p, id), (p)->smp_opt_dir, \
|
||||
(p)->flag_finish, (p)->context)
|
||||
|
||||
#define FLT_OTEL_DBG_SCOPE_DATA_EVENT(h,p) \
|
||||
OTELC_DBG(DEBUG, h "%p:{ '%s' %p %zu %zu %s }", &(p), \
|
||||
(p).name, (p).attr, (p).cnt, (p).size, \
|
||||
flt_otel_list_dump(&((p).list)))
|
||||
|
||||
#define FLT_OTEL_DBG_SCOPE_DATA_STATUS(h,p) \
|
||||
OTELC_DBG(DEBUG, h "%p:{ %d '%s' }", (p), (p)->code, OTELC_STR_ARG((p)->description))
|
||||
|
||||
#define FLT_OTEL_DBG_SCOPE_DATA_KV_FMT "%p:{ %p %zu %zu }"
|
||||
#define FLT_OTEL_DBG_SCOPE_DATA_KV_ARGS(p) &(p), (p).attr, (p).cnt, (p).size
|
||||
#define FLT_OTEL_DBG_SCOPE_DATA(h,p) \
|
||||
OTELC_DBG(DEBUG, h "%p:{ " FLT_OTEL_DBG_SCOPE_DATA_KV_FMT " " FLT_OTEL_DBG_SCOPE_DATA_KV_FMT " %s }", (p), \
|
||||
FLT_OTEL_DBG_SCOPE_DATA_KV_ARGS((p)->baggage), FLT_OTEL_DBG_SCOPE_DATA_KV_ARGS((p)->attributes), \
|
||||
flt_otel_list_dump(&((p)->events)))
|
||||
|
||||
#define FLT_OTEL_DBG_RUNTIME_CONTEXT(h,p) \
|
||||
OTELC_DBG(DEBUG, h "%p:{ %p %p '%s' %hhu %hhu 0x%02hhx 0x%08x %u %d %s %s }", (p), \
|
||||
(p)->stream, (p)->filter, (p)->uuid, (p)->flag_harderr, (p)->flag_disabled, \
|
||||
(p)->logging, (p)->analyzers, (p)->idle_timeout, (p)->idle_exp, \
|
||||
flt_otel_list_dump(&((p)->spans)), flt_otel_list_dump(&((p)->contexts)))
|
||||
|
||||
/* Anonymous struct containing a const string pointer and its length. */
|
||||
#define FLT_OTEL_CONST_STR_HDR(p) \
|
||||
struct { \
|
||||
const char *p; \
|
||||
size_t p##_len; \
|
||||
}
|
||||
|
||||
|
||||
/* Growable key-value array for span attributes or baggage. */
|
||||
struct flt_otel_scope_data_kv {
|
||||
struct otelc_kv *attr; /* Key-value array for storing attributes. */
|
||||
size_t cnt; /* Number of currently used array elements. */
|
||||
size_t size; /* Total number of array elements. */
|
||||
};
|
||||
|
||||
/* Named event with its own key-value attribute array. */
|
||||
struct flt_otel_scope_data_event {
|
||||
char *name; /* Event name, not used for other data types. */
|
||||
struct otelc_kv *attr; /* Key-value array for storing attributes. */
|
||||
size_t cnt; /* Number of currently used array elements. */
|
||||
size_t size; /* Total number of array elements. */
|
||||
struct list list; /* Used to chain this structure. */
|
||||
};
|
||||
|
||||
struct flt_otel_scope_data_status {
|
||||
int code; /* OTELC_SPAN_STATUS_* value. */
|
||||
char *description; /* Span status description string. */
|
||||
};
|
||||
|
||||
struct flt_otel_scope_data {
|
||||
struct flt_otel_scope_data_kv baggage; /* Defined scope baggage. */
|
||||
struct flt_otel_scope_data_kv attributes; /* Defined scope attributes. */
|
||||
struct list events; /* Defined scope events. */
|
||||
struct flt_otel_scope_data_status status; /* Defined scope status. */
|
||||
};
|
||||
|
||||
/* flt_otel_runtime_context->spans */
|
||||
struct flt_otel_scope_span {
|
||||
FLT_OTEL_CONST_STR_HDR(id); /* The span operation name/len. */
|
||||
uint smp_opt_dir; /* SMP_OPT_DIR_RE(Q|S) */
|
||||
bool flag_finish; /* Whether the span is marked for completion. */
|
||||
struct otelc_span *span; /* The current span. */
|
||||
struct otelc_span *ref_span; /* Span to which the current span refers. */
|
||||
struct otelc_span_context *ref_ctx; /* Span context to which the current span refers. */
|
||||
struct list list; /* Used to chain this structure. */
|
||||
};
|
||||
|
||||
/* flt_otel_runtime_context->contexts */
|
||||
struct flt_otel_scope_context {
|
||||
FLT_OTEL_CONST_STR_HDR(id); /* The span context name/len. */
|
||||
uint smp_opt_dir; /* SMP_OPT_DIR_RE(Q|S) */
|
||||
bool flag_finish; /* Whether the span context is marked for completion. */
|
||||
struct otelc_span_context *context; /* The current span context. */
|
||||
struct list list; /* Used to chain this structure. */
|
||||
};
|
||||
|
||||
/* The runtime filter context attached to a stream. */
|
||||
struct flt_otel_runtime_context {
|
||||
struct stream *stream; /* The stream to which the filter is attached. */
|
||||
struct filter *filter; /* The OpenTelemetry filter. */
|
||||
char uuid[40]; /* Randomly generated UUID. */
|
||||
bool flag_harderr; /* [0 1] */
|
||||
bool flag_disabled; /* [0 1] */
|
||||
uint8_t logging; /* [0 1 3] */
|
||||
uint analyzers; /* Executed channel analyzers. */
|
||||
uint idle_timeout; /* Idle timeout interval in milliseconds (0 = off). */
|
||||
int idle_exp; /* Tick at which the next idle timeout fires. */
|
||||
struct list spans; /* The scope spans. */
|
||||
struct list contexts; /* The scope contexts. */
|
||||
};
|
||||
|
||||
|
||||
#ifndef DEBUG_OTEL
|
||||
# define flt_otel_scope_data_dump(...) while (0)
|
||||
#else
|
||||
/* Dump scope data contents for debugging. */
|
||||
void flt_otel_scope_data_dump(const struct flt_otel_scope_data *data);
|
||||
#endif
|
||||
|
||||
/* Allocate and initialize a runtime context for a stream. */
|
||||
struct flt_otel_runtime_context *flt_otel_runtime_context_init(struct stream *s, struct filter *f, char **err);
|
||||
|
||||
/* Free the runtime context attached to a filter. */
|
||||
void flt_otel_runtime_context_free(struct filter *f);
|
||||
|
||||
/* Allocate and initialize a scope span in the runtime context. */
|
||||
struct flt_otel_scope_span *flt_otel_scope_span_init(struct flt_otel_runtime_context *rt_ctx, const char *id, size_t id_len, const char *ref_id, size_t ref_id_len, uint dir, char **err);
|
||||
|
||||
/* Free a scope span and remove it from the runtime context. */
|
||||
void flt_otel_scope_span_free(struct flt_otel_scope_span **ptr);
|
||||
|
||||
/* Allocate and initialize a scope context in the runtime context. */
|
||||
struct flt_otel_scope_context *flt_otel_scope_context_init(struct flt_otel_runtime_context *rt_ctx, struct otelc_tracer *tracer, const char *id, size_t id_len, const struct otelc_text_map *text_map, uint dir, char **err);
|
||||
|
||||
/* Free a scope context and remove it from the runtime context. */
|
||||
void flt_otel_scope_context_free(struct flt_otel_scope_context **ptr);
|
||||
|
||||
/* Initialize scope data arrays and lists. */
|
||||
void flt_otel_scope_data_init(struct flt_otel_scope_data *ptr);
|
||||
|
||||
/* Free all scope data contents. */
|
||||
void flt_otel_scope_data_free(struct flt_otel_scope_data *ptr);
|
||||
|
||||
/* Free scope spans and contexts no longer needed by a channel. */
|
||||
void flt_otel_scope_free_unused(struct flt_otel_runtime_context *rt_ctx, struct channel *chn);
|
||||
|
||||
#endif /* _OTEL_SCOPE_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*
|
||||
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||
*/
|
||||
385
addons/otel/src/pool.c
Normal file
385
addons/otel/src/pool.c
Normal file
@ -0,0 +1,385 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "../include/include.h"
|
||||
|
||||
|
||||
struct pool_head *pool_head_otel_scope_span __read_mostly = NULL;
|
||||
struct pool_head *pool_head_otel_scope_context __read_mostly = NULL;
|
||||
struct pool_head *pool_head_otel_runtime_context __read_mostly = NULL;
|
||||
struct pool_head *pool_head_otel_span_context __read_mostly = NULL;
|
||||
|
||||
#ifdef USE_POOL_OTEL_SCOPE_SPAN
|
||||
REGISTER_POOL(&pool_head_otel_scope_span, "otel_scope_span", sizeof(struct flt_otel_scope_span));
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SCOPE_CONTEXT
|
||||
REGISTER_POOL(&pool_head_otel_scope_context, "otel_scope_context", sizeof(struct flt_otel_scope_context));
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_RUNTIME_CONTEXT
|
||||
REGISTER_POOL(&pool_head_otel_runtime_context, "otel_runtime_context", sizeof(struct flt_otel_runtime_context));
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SPAN_CONTEXT
|
||||
REGISTER_POOL(&pool_head_otel_span_context, "otel_span_context", MAX(sizeof(struct otelc_span), sizeof(struct otelc_span_context)));
|
||||
#endif
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_pool_alloc - pool-aware memory allocation
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void *flt_otel_pool_alloc(struct pool_head *pool, size_t size, bool flag_clear, char **err)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* pool - HAProxy memory pool to allocate from (or NULL for heap)
|
||||
* size - number of bytes to allocate
|
||||
* flag_clear - whether to zero-fill the allocated memory
|
||||
* err - indirect pointer to error message string
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Allocates <size> bytes of memory from the HAProxy memory <pool>. If <pool>
|
||||
* is NULL, the allocation falls back to the heap via OTELC_MALLOC(). When
|
||||
* <flag_clear> is set, the allocated memory is zero-filled. On allocation
|
||||
* failure, an error message is stored via <err>.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns a pointer to the allocated memory, or NULL on failure.
|
||||
*/
|
||||
void *flt_otel_pool_alloc(struct pool_head *pool, size_t size, bool flag_clear, char **err)
|
||||
{
|
||||
void *retptr;
|
||||
|
||||
OTELC_FUNC("%p, %zu, %hhu, %p:%p", pool, size, flag_clear, OTELC_DPTR_ARGS(err));
|
||||
|
||||
if (pool != NULL) {
|
||||
retptr = pool_alloc(pool);
|
||||
if (retptr != NULL)
|
||||
OTELC_DBG(NOTICE, "POOL_ALLOC: %s:%d(%p %zu)", __func__, __LINE__, retptr, FLT_OTEL_DEREF(pool, size, size));
|
||||
} else {
|
||||
retptr = OTELC_MALLOC(size);
|
||||
}
|
||||
|
||||
if (retptr == NULL)
|
||||
FLT_OTEL_ERR("out of memory");
|
||||
else if (flag_clear)
|
||||
(void)memset(retptr, 0, size);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_pool_strndup - pool-aware string duplication
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void *flt_otel_pool_strndup(struct pool_head *pool, const char *s, size_t size, char **err)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* pool - HAProxy memory pool to allocate from (or NULL for heap)
|
||||
* s - source string to duplicate
|
||||
* size - maximum number of characters to copy
|
||||
* err - indirect pointer to error message string
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Duplicates up to <size> characters from the string <s> using the HAProxy
|
||||
* memory <pool>. If <pool> is NULL, the duplication falls back to
|
||||
* OTELC_STRNDUP(). When using a pool, the copy is truncated to <pool>->size-1
|
||||
* bytes and null-terminated.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns a pointer to the duplicated string, or NULL on failure.
|
||||
*/
|
||||
void *flt_otel_pool_strndup(struct pool_head *pool, const char *s, size_t size, char **err)
|
||||
{
|
||||
void *retptr;
|
||||
|
||||
OTELC_FUNC("%p, \"%.*s\", %zu, %p:%p", pool, (int)size, s, size, OTELC_DPTR_ARGS(err));
|
||||
|
||||
if (pool != NULL) {
|
||||
retptr = pool_alloc(pool);
|
||||
if (retptr != NULL) {
|
||||
(void)memcpy(retptr, s, MIN(pool->size - 1, size));
|
||||
|
||||
((uint8_t *)retptr)[MIN(pool->size - 1, size)] = '\0';
|
||||
}
|
||||
} else {
|
||||
retptr = OTELC_STRNDUP(s, size);
|
||||
}
|
||||
|
||||
if (retptr != NULL)
|
||||
OTELC_DBG(NOTICE, "POOL_STRNDUP: %s:%d(%p %zu)", __func__, __LINE__, retptr, FLT_OTEL_DEREF(pool, size, size));
|
||||
else
|
||||
FLT_OTEL_ERR("out of memory");
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_pool_free - pool-aware memory deallocation
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_pool_free(struct pool_head *pool, void **ptr)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* pool - HAProxy memory pool to return memory to (or NULL for heap)
|
||||
* ptr - indirect pointer to the memory to free
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Returns memory referenced by <*ptr> to the HAProxy memory <pool>. If
|
||||
* <pool> is NULL, the memory is freed via OTELC_SFREE(). The pointer <*ptr>
|
||||
* is set to NULL after freeing. If <ptr> is NULL or <*ptr> is already NULL,
|
||||
* the function returns immediately.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_pool_free(struct pool_head *pool, void **ptr)
|
||||
{
|
||||
OTELC_FUNC("%p, %p:%p", pool, OTELC_DPTR_ARGS(ptr));
|
||||
|
||||
if ((ptr == NULL) || (*ptr == NULL))
|
||||
OTELC_RETURN();
|
||||
|
||||
OTELC_DBG(NOTICE, "POOL_FREE: %s:%d(%p %u)", __func__, __LINE__, *ptr, FLT_OTEL_DEREF(pool, size, 0));
|
||||
|
||||
if (pool != NULL)
|
||||
pool_free(pool, *ptr);
|
||||
else
|
||||
OTELC_SFREE(*ptr);
|
||||
|
||||
*ptr = NULL;
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_pool_init - OTel filter memory pool initialization
|
||||
*
|
||||
* SYNOPSIS
|
||||
* int flt_otel_pool_init(void)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* This function takes no arguments.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initializes all memory pools used by the OTel filter. Each pool is
|
||||
* created only when the corresponding USE_POOL_OTEL_* macro is defined.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns FLT_OTEL_RET_OK on success, FLT_OTEL_RET_ERROR on failure.
|
||||
*/
|
||||
int flt_otel_pool_init(void)
|
||||
{
|
||||
int retval = FLT_OTEL_RET_OK;
|
||||
|
||||
OTELC_FUNC("");
|
||||
|
||||
#ifdef USE_POOL_OTEL_SCOPE_SPAN
|
||||
FLT_OTEL_POOL_INIT(pool_head_otel_scope_span, "otel_scope_span", sizeof(struct flt_otel_scope_span), retval);
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SCOPE_CONTEXT
|
||||
FLT_OTEL_POOL_INIT(pool_head_otel_scope_context, "otel_scope_context", sizeof(struct flt_otel_scope_context), retval);
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_RUNTIME_CONTEXT
|
||||
FLT_OTEL_POOL_INIT(pool_head_otel_runtime_context, "otel_runtime_context", sizeof(struct flt_otel_runtime_context), retval);
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SPAN_CONTEXT
|
||||
FLT_OTEL_POOL_INIT(pool_head_otel_span_context, "otel_span_context", OTELC_MAX(sizeof(struct otelc_span), sizeof(struct otelc_span_context)), retval);
|
||||
#endif
|
||||
|
||||
OTELC_RETURN_INT(retval);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_pool_destroy - OTel filter memory pool destruction
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_pool_destroy(void)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* This function takes no arguments.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destroys all memory pools used by the OTel filter. Each pool is
|
||||
* destroyed only when the corresponding USE_POOL_OTEL_* macro is defined.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_pool_destroy(void)
|
||||
{
|
||||
OTELC_FUNC("");
|
||||
|
||||
#ifdef USE_POOL_OTEL_SCOPE_SPAN
|
||||
FLT_OTEL_POOL_DESTROY(pool_head_otel_scope_span);
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SCOPE_CONTEXT
|
||||
FLT_OTEL_POOL_DESTROY(pool_head_otel_scope_context);
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_RUNTIME_CONTEXT
|
||||
FLT_OTEL_POOL_DESTROY(pool_head_otel_runtime_context);
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SPAN_CONTEXT
|
||||
FLT_OTEL_POOL_DESTROY(pool_head_otel_span_context);
|
||||
#endif
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_OTEL
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_pool_info - debug pool sizes logging
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_pool_info(void)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* This function takes no arguments.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Logs the sizes of all registered HAProxy memory pools used by the OTel
|
||||
* filter (buffer, trash, scope_span, scope_context, runtime_context).
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_pool_info(void)
|
||||
{
|
||||
OTELC_DBG(NOTICE, "--- pool info ----------");
|
||||
|
||||
/*
|
||||
* In case we have some error in the configuration file,
|
||||
* it is possible that this pool was not initialized.
|
||||
*/
|
||||
#ifdef USE_POOL_BUFFER
|
||||
OTELC_DBG(NOTICE, " buffer: %p %u", pool_head_buffer, FLT_OTEL_DEREF(pool_head_buffer, size, 0));
|
||||
#endif
|
||||
#ifdef USE_TRASH_CHUNK
|
||||
OTELC_DBG(NOTICE, " trash: %p %u", pool_head_trash, FLT_OTEL_DEREF(pool_head_trash, size, 0));
|
||||
#endif
|
||||
|
||||
#ifdef USE_POOL_OTEL_SCOPE_SPAN
|
||||
OTELC_DBG(NOTICE, " otel_scope_span: %p %u", pool_head_otel_scope_span, FLT_OTEL_DEREF(pool_head_otel_scope_span, size, 0));
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SCOPE_CONTEXT
|
||||
OTELC_DBG(NOTICE, " otel_scope_context: %p %u", pool_head_otel_scope_context, FLT_OTEL_DEREF(pool_head_otel_scope_context, size, 0));
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_RUNTIME_CONTEXT
|
||||
OTELC_DBG(NOTICE, " otel_runtime_context: %p %u", pool_head_otel_runtime_context, FLT_OTEL_DEREF(pool_head_otel_runtime_context, size, 0));
|
||||
#endif
|
||||
#ifdef USE_POOL_OTEL_SPAN_CONTEXT
|
||||
OTELC_DBG(NOTICE, " otel_span_context: %p %u", pool_head_otel_span_context, FLT_OTEL_DEREF(pool_head_otel_span_context, size, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* DEBUG_OTEL */
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_trash_alloc - trash buffer allocation
|
||||
*
|
||||
* SYNOPSIS
|
||||
* struct buffer *flt_otel_trash_alloc(bool flag_clear, char **err)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* flag_clear - whether to zero-fill the buffer area
|
||||
* err - indirect pointer to error message string
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Allocates a temporary buffer chunk for use as scratch space. When
|
||||
* USE_TRASH_CHUNK is defined, the buffer is obtained via alloc_trash_chunk();
|
||||
* otherwise, a buffer structure and its data area are allocated from the heap
|
||||
* using global.tune.bufsize as the buffer size. When <flag_clear> is set,
|
||||
* the buffer's data area is zero-filled.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns a pointer to the allocated buffer, or NULL on failure.
|
||||
*/
|
||||
struct buffer *flt_otel_trash_alloc(bool flag_clear, char **err)
|
||||
{
|
||||
struct buffer *retptr;
|
||||
|
||||
OTELC_FUNC("%hhu, %p:%p", flag_clear, OTELC_DPTR_ARGS(err));
|
||||
|
||||
#ifdef USE_TRASH_CHUNK
|
||||
retptr = alloc_trash_chunk();
|
||||
if (retptr != NULL)
|
||||
OTELC_DBG(NOTICE, "TRASH_ALLOC: %s:%d(%p %zu)", __func__, __LINE__, retptr, retptr->size);
|
||||
#else
|
||||
retptr = OTELC_MALLOC(sizeof(*retptr));
|
||||
if (retptr != NULL) {
|
||||
chunk_init(retptr, OTELC_MALLOC(global.tune.bufsize), global.tune.bufsize);
|
||||
if (retptr->area == NULL)
|
||||
OTELC_SFREE_CLEAR(retptr);
|
||||
else
|
||||
*(retptr->area) = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
if (retptr == NULL)
|
||||
FLT_OTEL_ERR("out of memory");
|
||||
else if (flag_clear)
|
||||
(void)memset(retptr->area, 0, retptr->size);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_trash_free - trash buffer deallocation
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_trash_free(struct buffer **ptr)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* ptr - indirect pointer to the buffer to free
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Frees a trash buffer chunk previously allocated by flt_otel_trash_alloc().
|
||||
* When USE_TRASH_CHUNK is defined, the buffer is freed via
|
||||
* free_trash_chunk(); otherwise, both the data area and the buffer structure
|
||||
* are freed individually. The pointer <*ptr> is set to NULL after freeing.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_trash_free(struct buffer **ptr)
|
||||
{
|
||||
OTELC_FUNC("%p:%p", OTELC_DPTR_ARGS(ptr));
|
||||
|
||||
if ((ptr == NULL) || (*ptr == NULL))
|
||||
OTELC_RETURN();
|
||||
|
||||
OTELC_DBG(NOTICE, "TRASH_FREE: %s:%d(%p %zu)", __func__, __LINE__, *ptr, (*ptr)->size);
|
||||
|
||||
#ifdef USE_TRASH_CHUNK
|
||||
free_trash_chunk(*ptr);
|
||||
#else
|
||||
OTELC_SFREE((*ptr)->area);
|
||||
OTELC_SFREE(*ptr);
|
||||
#endif
|
||||
|
||||
*ptr = NULL;
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*
|
||||
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||
*/
|
||||
525
addons/otel/src/scope.c
Normal file
525
addons/otel/src/scope.c
Normal file
@ -0,0 +1,525 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "../include/include.h"
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_runtime_context_init - per-stream runtime context allocation
|
||||
*
|
||||
* SYNOPSIS
|
||||
* struct flt_otel_runtime_context *flt_otel_runtime_context_init(struct stream *s, struct filter *f, char **err)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* s - the stream to which the context belongs
|
||||
* f - the filter instance
|
||||
* err - indirect pointer to error message string
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Allocates and initializes a per-stream runtime context from pool memory.
|
||||
* It copies the hard-error, disabled and logging flags from the filter
|
||||
* configuration, generates a UUID and stores it in the sess.otel.uuid
|
||||
* HAProxy variable.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns a pointer to the new runtime context, or NULL on failure.
|
||||
*/
|
||||
struct flt_otel_runtime_context *flt_otel_runtime_context_init(struct stream *s, struct filter *f, char **err)
|
||||
{
|
||||
const struct flt_otel_conf *conf = FLT_OTEL_CONF(f);
|
||||
struct buffer uuid;
|
||||
struct flt_otel_runtime_context *retptr = NULL;
|
||||
|
||||
OTELC_FUNC("%p, %p, %p:%p", s, f, OTELC_DPTR_ARGS(err));
|
||||
|
||||
retptr = flt_otel_pool_alloc(pool_head_otel_runtime_context, sizeof(*retptr), 1, err);
|
||||
if (retptr == NULL)
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
|
||||
/* Initialize runtime context fields and generate a session UUID. */
|
||||
retptr->stream = s;
|
||||
retptr->filter = f;
|
||||
retptr->flag_harderr = _HA_ATOMIC_LOAD(&(conf->instr->flag_harderr));
|
||||
retptr->flag_disabled = _HA_ATOMIC_LOAD(&(conf->instr->flag_disabled));
|
||||
retptr->logging = _HA_ATOMIC_LOAD(&(conf->instr->logging));
|
||||
retptr->idle_timeout = 0;
|
||||
retptr->idle_exp = TICK_ETERNITY;
|
||||
LIST_INIT(&(retptr->spans));
|
||||
LIST_INIT(&(retptr->contexts));
|
||||
|
||||
uuid = b_make(retptr->uuid, sizeof(retptr->uuid), 0, 0);
|
||||
ha_generate_uuid_v4(&uuid);
|
||||
|
||||
FLT_OTEL_DBG_RUNTIME_CONTEXT("session context: ", retptr);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_runtime_context_free - per-stream runtime context cleanup
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_runtime_context_free(struct filter *f)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* f - the filter instance whose runtime context is to be freed
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Frees the per-stream runtime context attached to <f>. It ends all active
|
||||
* spans with the current monotonic timestamp, destroys all extracted
|
||||
* contexts, and returns the pool memory.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_runtime_context_free(struct filter *f)
|
||||
{
|
||||
struct flt_otel_runtime_context *rt_ctx = f->ctx;
|
||||
|
||||
OTELC_FUNC("%p", f);
|
||||
|
||||
if (rt_ctx == NULL)
|
||||
OTELC_RETURN();
|
||||
|
||||
FLT_OTEL_DBG_RUNTIME_CONTEXT("session context: ", rt_ctx);
|
||||
|
||||
/* End all active spans with a common timestamp. */
|
||||
if (!LIST_ISEMPTY(&(rt_ctx->spans))) {
|
||||
struct flt_otel_scope_span *span, *span_back;
|
||||
|
||||
list_for_each_entry_safe(span, span_back, &(rt_ctx->spans), list)
|
||||
flt_otel_scope_span_free(&span);
|
||||
}
|
||||
|
||||
/* Destroy all extracted span contexts. */
|
||||
if (!LIST_ISEMPTY(&(rt_ctx->contexts))) {
|
||||
struct flt_otel_scope_context *ctx, *ctx_back;
|
||||
|
||||
list_for_each_entry_safe(ctx, ctx_back, &(rt_ctx->contexts), list)
|
||||
flt_otel_scope_context_free(&ctx);
|
||||
}
|
||||
|
||||
flt_otel_pool_free(pool_head_otel_runtime_context, &(f->ctx));
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_span_init - scope span lookup or creation
|
||||
*
|
||||
* SYNOPSIS
|
||||
* struct flt_otel_scope_span *flt_otel_scope_span_init(struct flt_otel_runtime_context *rt_ctx, const char *id, size_t id_len, const char *ref_id, size_t ref_id_len, uint dir, char **err)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* rt_ctx - the runtime context owning the span list
|
||||
* id - the span operation name
|
||||
* id_len - length of the <id> string
|
||||
* ref_id - the parent span or context name, or NULL
|
||||
* ref_id_len - length of the <ref_id> string
|
||||
* dir - the sample fetch direction (SMP_OPT_DIR_REQ/RES)
|
||||
* err - indirect pointer to error message string
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Finds an existing scope span by <id> in the runtime context or creates a
|
||||
* new one. If <ref_id> is set, it resolves the parent reference by searching
|
||||
* the span list first, then the extracted context list.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns the existing or new scope span, or NULL on failure.
|
||||
*/
|
||||
struct flt_otel_scope_span *flt_otel_scope_span_init(struct flt_otel_runtime_context *rt_ctx, const char *id, size_t id_len, const char *ref_id, size_t ref_id_len, uint dir, char **err)
|
||||
{
|
||||
struct otelc_span *ref_span = NULL;
|
||||
struct otelc_span_context *ref_ctx = NULL;
|
||||
struct flt_otel_scope_span *span, *retptr = NULL;
|
||||
struct flt_otel_scope_context *ctx;
|
||||
|
||||
OTELC_FUNC("%p, \"%s\", %zu, \"%s\", %zu, %u, %p:%p", rt_ctx, OTELC_STR_ARG(id), id_len, OTELC_STR_ARG(ref_id), ref_id_len, dir, OTELC_DPTR_ARGS(err));
|
||||
|
||||
if ((rt_ctx == NULL) || (id == NULL))
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
|
||||
/* Return the existing span if one matches this ID. */
|
||||
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||
if (FLT_OTEL_CONF_STR_CMP(span->id, id)) {
|
||||
OTELC_DBG(NOTICE, "found span %p", span);
|
||||
|
||||
OTELC_RETURN_PTR(span);
|
||||
}
|
||||
|
||||
/* Resolve the parent reference from spans or contexts. */
|
||||
if (ref_id != NULL) {
|
||||
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||
if (FLT_OTEL_CONF_STR_CMP(span->id, ref_id)) {
|
||||
ref_span = span->span;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ref_span != NULL) {
|
||||
OTELC_DBG(NOTICE, "found referenced span %p", span);
|
||||
} else {
|
||||
list_for_each_entry(ctx, &(rt_ctx->contexts), list)
|
||||
if (FLT_OTEL_CONF_STR_CMP(ctx->id, ref_id)) {
|
||||
ref_ctx = ctx->context;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ref_ctx != NULL) {
|
||||
OTELC_DBG(NOTICE, "found referenced context %p", ctx);
|
||||
} else {
|
||||
FLT_OTEL_ERR("cannot find referenced span/context '%s'", ref_id);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retptr = flt_otel_pool_alloc(pool_head_otel_scope_span, sizeof(*retptr), 1, err);
|
||||
if (retptr == NULL)
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
|
||||
/* Populate the new scope span and insert it into the list. */
|
||||
retptr->id = id;
|
||||
retptr->id_len = id_len;
|
||||
retptr->smp_opt_dir = dir;
|
||||
retptr->ref_span = ref_span;
|
||||
retptr->ref_ctx = ref_ctx;
|
||||
LIST_INSERT(&(rt_ctx->spans), &(retptr->list));
|
||||
|
||||
FLT_OTEL_DBG_SCOPE_SPAN("new span ", retptr);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_span_free - scope span cleanup
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_scope_span_free(struct flt_otel_scope_span **ptr)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* ptr - pointer to the scope span pointer to free
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Frees a scope span entry pointed to by <ptr> and removes it from its list.
|
||||
* If the OTel span is still active (non-NULL), the function refuses to free
|
||||
* it and returns immediately.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_scope_span_free(struct flt_otel_scope_span **ptr)
|
||||
{
|
||||
OTELC_FUNC("%p:%p", OTELC_DPTR_ARGS(ptr));
|
||||
|
||||
if ((ptr == NULL) || (*ptr == NULL))
|
||||
OTELC_RETURN();
|
||||
|
||||
FLT_OTEL_DBG_SCOPE_SPAN("", *ptr);
|
||||
|
||||
/* If the span is still active, do nothing. */
|
||||
if ((*ptr)->span != NULL) {
|
||||
OTELC_DBG(NOTICE, "cannot finish active span");
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
FLT_OTEL_LIST_DEL(&((*ptr)->list));
|
||||
flt_otel_pool_free(pool_head_otel_scope_span, (void **)ptr);
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_context_init - scope context extraction
|
||||
*
|
||||
* SYNOPSIS
|
||||
* struct flt_otel_scope_context *flt_otel_scope_context_init(struct flt_otel_runtime_context *rt_ctx, struct otelc_tracer *tracer, const char *id, size_t id_len, const struct otelc_text_map *text_map, uint dir, char **err)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* rt_ctx - the runtime context owning the context list
|
||||
* tracer - the OTel tracer used for context extraction
|
||||
* id - the context name
|
||||
* id_len - length of the <id> string
|
||||
* text_map - the carrier text map to extract from
|
||||
* dir - the sample fetch direction (SMP_OPT_DIR_REQ/RES)
|
||||
* err - indirect pointer to error message string
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Finds an existing scope context by <id> in the runtime context or creates
|
||||
* a new one by extracting the span context from the <text_map> carrier via
|
||||
* the <tracer>.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Returns the existing or new scope context, or NULL on failure.
|
||||
*/
|
||||
struct flt_otel_scope_context *flt_otel_scope_context_init(struct flt_otel_runtime_context *rt_ctx, struct otelc_tracer *tracer, const char *id, size_t id_len, const struct otelc_text_map *text_map, uint dir, char **err)
|
||||
{
|
||||
struct flt_otel_scope_context *retptr = NULL;
|
||||
|
||||
OTELC_FUNC("%p, %p, \"%s\", %zu, %p, %u, %p:%p", rt_ctx, tracer, OTELC_STR_ARG(id), id_len, text_map, dir, OTELC_DPTR_ARGS(err));
|
||||
|
||||
if ((rt_ctx == NULL) || (tracer == NULL) || (id == NULL) || (text_map == NULL))
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
|
||||
/* Return the existing context if one matches this ID. */
|
||||
list_for_each_entry(retptr, &(rt_ctx->contexts), list)
|
||||
if (FLT_OTEL_CONF_STR_CMP(retptr->id, id)) {
|
||||
OTELC_DBG(NOTICE, "found context %p", retptr);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
retptr = flt_otel_pool_alloc(pool_head_otel_scope_context, sizeof(*retptr), 1, err);
|
||||
if (retptr == NULL)
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
|
||||
/* Populate the new scope context and insert it into the list. */
|
||||
retptr->id = id;
|
||||
retptr->id_len = id_len;
|
||||
retptr->smp_opt_dir = dir;
|
||||
LIST_INSERT(&(rt_ctx->contexts), &(retptr->list));
|
||||
|
||||
FLT_OTEL_DBG_SCOPE_CONTEXT("new context ", retptr);
|
||||
|
||||
OTELC_RETURN_PTR(retptr);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_context_free - scope context cleanup
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_scope_context_free(struct flt_otel_scope_context **ptr)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* ptr - pointer to the scope context pointer to free
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Frees a scope context entry pointed to by <ptr>. It destroys the
|
||||
* underlying OTel span context, removes the entry from its list, and
|
||||
* returns the pool memory.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_scope_context_free(struct flt_otel_scope_context **ptr)
|
||||
{
|
||||
OTELC_FUNC("%p:%p", OTELC_DPTR_ARGS(ptr));
|
||||
|
||||
if ((ptr == NULL) || (*ptr == NULL))
|
||||
OTELC_RETURN();
|
||||
|
||||
FLT_OTEL_DBG_SCOPE_CONTEXT("", *ptr);
|
||||
|
||||
FLT_OTEL_LIST_DEL(&((*ptr)->list));
|
||||
flt_otel_pool_free(pool_head_otel_scope_context, (void **)ptr);
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_OTEL
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_data_dump - debug scope data dump
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_scope_data_dump(const struct flt_otel_scope_data *data)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* data - the scope data structure to dump
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Dumps the contents of a scope <data> structure for debugging: baggage
|
||||
* key-value pairs, attributes, events with their attributes, span links,
|
||||
* and the status code/description.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_scope_data_dump(const struct flt_otel_scope_data *data)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (data->baggage.attr == NULL) {
|
||||
OTELC_DBG(WORKER, "baggage %p:{ }", &(data->baggage));
|
||||
} else {
|
||||
OTELC_DBG(WORKER, "baggage %p:{", &(data->baggage));
|
||||
for (i = 0; i < data->baggage.cnt; i++)
|
||||
OTELC_DBG_KV(WORKER, " ", data->baggage.attr + i);
|
||||
OTELC_DBG(WORKER, "}");
|
||||
}
|
||||
|
||||
if (data->attributes.attr == NULL) {
|
||||
OTELC_DBG(WORKER, "attributes %p:{ }", &(data->attributes));
|
||||
} else {
|
||||
OTELC_DBG(WORKER, "attributes %p:{", &(data->attributes));
|
||||
for (i = 0; i < data->attributes.cnt; i++)
|
||||
OTELC_DBG_KV(WORKER, " ", data->attributes.attr + i);
|
||||
OTELC_DBG(WORKER, "}");
|
||||
}
|
||||
|
||||
if (LIST_ISEMPTY(&(data->events))) {
|
||||
OTELC_DBG(WORKER, "events %p:{ }", &(data->events));
|
||||
} else {
|
||||
struct flt_otel_scope_data_event *event;
|
||||
|
||||
OTELC_DBG(WORKER, "events %p:{", &(data->events));
|
||||
list_for_each_entry_rev(event, &(data->events), list) {
|
||||
OTELC_DBG(WORKER, " '%s' %zu/%zu", event->name, event->cnt, event->size);
|
||||
if (event->attr != NULL)
|
||||
for (i = 0; i < event->cnt; i++)
|
||||
OTELC_DBG_KV(WORKER, " ", event->attr + i);
|
||||
}
|
||||
OTELC_DBG(WORKER, "}");
|
||||
}
|
||||
|
||||
if ((data->status.code == 0) && (data->status.description == NULL))
|
||||
OTELC_DBG(WORKER, "status %p:{ }", &(data->status));
|
||||
else
|
||||
FLT_OTEL_DBG_SCOPE_DATA_STATUS("status ", &(data->status));
|
||||
}
|
||||
|
||||
#endif /* DEBUG_OTEL */
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_data_init - scope data zero-initialization
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_scope_data_init(struct flt_otel_scope_data *ptr)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* ptr - the scope data structure to initialize
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Zero-initializes the scope data structure pointed to by <ptr> and sets up
|
||||
* the event and link list heads.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_scope_data_init(struct flt_otel_scope_data *ptr)
|
||||
{
|
||||
OTELC_FUNC("%p", ptr);
|
||||
|
||||
if (ptr == NULL)
|
||||
OTELC_RETURN();
|
||||
|
||||
(void)memset(ptr, 0, sizeof(*ptr));
|
||||
LIST_INIT(&(ptr->events));
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_data_free - scope data cleanup
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_scope_data_free(struct flt_otel_scope_data *ptr)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* ptr - the scope data structure to free
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Frees all contents of the scope data structure pointed to by <ptr>: baggage
|
||||
* and attribute key-value arrays, event entries with their attributes, link
|
||||
* entries, and the status description string.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_scope_data_free(struct flt_otel_scope_data *ptr)
|
||||
{
|
||||
struct flt_otel_scope_data_event *event, *event_back;
|
||||
|
||||
OTELC_FUNC("%p", ptr);
|
||||
|
||||
if (ptr == NULL)
|
||||
OTELC_RETURN();
|
||||
|
||||
FLT_OTEL_DBG_SCOPE_DATA("", ptr);
|
||||
|
||||
/* Destroy all dynamic scope data contents. */
|
||||
otelc_kv_destroy(&(ptr->baggage.attr), ptr->baggage.cnt);
|
||||
otelc_kv_destroy(&(ptr->attributes.attr), ptr->attributes.cnt);
|
||||
list_for_each_entry_safe(event, event_back, &(ptr->events), list) {
|
||||
otelc_kv_destroy(&(event->attr), event->cnt);
|
||||
OTELC_SFREE(event->name);
|
||||
OTELC_SFREE(event);
|
||||
}
|
||||
OTELC_SFREE(ptr->status.description);
|
||||
|
||||
(void)memset(ptr, 0, sizeof(*ptr));
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* NAME
|
||||
* flt_otel_scope_free_unused - remove unused spans and contexts
|
||||
*
|
||||
* SYNOPSIS
|
||||
* void flt_otel_scope_free_unused(struct flt_otel_runtime_context *rt_ctx, struct channel *chn)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* rt_ctx - the runtime context to clean up
|
||||
* chn - the channel for HTTP header cleanup
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Removes scope spans with a NULL OTel span and scope contexts with a NULL
|
||||
* OTel context from the runtime context. For each removed context, the
|
||||
* associated HTTP headers are also cleaned up via <chn>.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* This function does not return a value.
|
||||
*/
|
||||
void flt_otel_scope_free_unused(struct flt_otel_runtime_context *rt_ctx, struct channel *chn)
|
||||
{
|
||||
OTELC_FUNC("%p, %p", rt_ctx, chn);
|
||||
|
||||
if (rt_ctx == NULL)
|
||||
OTELC_RETURN();
|
||||
|
||||
/* Remove spans that were never successfully created. */
|
||||
if (!LIST_ISEMPTY(&(rt_ctx->spans))) {
|
||||
struct flt_otel_scope_span *span, *span_back;
|
||||
|
||||
list_for_each_entry_safe(span, span_back, &(rt_ctx->spans), list)
|
||||
if (span->span == NULL)
|
||||
flt_otel_scope_span_free(&span);
|
||||
}
|
||||
|
||||
FLT_OTEL_DBG_RUNTIME_CONTEXT("session context: ", rt_ctx);
|
||||
|
||||
OTELC_RETURN();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*
|
||||
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||
*/
|
||||
Loading…
x
Reference in New Issue
Block a user