log: Add key/value support to the log context
Now that we have reference counting, it's useful to be able to push single key values onto the log context separately, so that we don't have to allocate new storage to join the separate string together into a single field which means we won't be able to reuse a context containing the same field.
This commit is contained in:
+45
-8
@@ -42,7 +42,7 @@
|
||||
#include "utf8.h"
|
||||
|
||||
#define SNDBUF_SIZE (8*1024*1024)
|
||||
#define IOVEC_MAX 128U
|
||||
#define IOVEC_MAX 256U
|
||||
|
||||
static log_syntax_callback_t log_syntax_callback = NULL;
|
||||
static void *log_syntax_callback_userdata = NULL;
|
||||
@@ -79,6 +79,8 @@ typedef struct LogContext {
|
||||
char **fields;
|
||||
struct iovec *input_iovec;
|
||||
size_t n_input_iovec;
|
||||
char *key;
|
||||
char *value;
|
||||
bool owned;
|
||||
LIST_FIELDS(struct LogContext, ll);
|
||||
} LogContext;
|
||||
@@ -632,6 +634,15 @@ static void log_do_context(struct iovec *iovec, size_t iovec_len, size_t *n) {
|
||||
iovec[(*n)++] = c->input_iovec[i];
|
||||
iovec[(*n)++] = IOVEC_MAKE_STRING("\n");
|
||||
}
|
||||
|
||||
if (c->key && c->value) {
|
||||
if (*n + 3 >= iovec_len)
|
||||
return;
|
||||
|
||||
iovec[(*n)++] = IOVEC_MAKE_STRING(c->key);
|
||||
iovec[(*n)++] = IOVEC_MAKE_STRING(c->value);
|
||||
iovec[(*n)++] = IOVEC_MAKE_STRING("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,6 +1579,7 @@ static LogContext* log_context_attach(LogContext *c) {
|
||||
|
||||
_log_context_num_fields += strv_length(c->fields);
|
||||
_log_context_num_fields += c->n_input_iovec;
|
||||
_log_context_num_fields += !!c->key;
|
||||
|
||||
return LIST_PREPEND(ll, _log_context, c);
|
||||
}
|
||||
@@ -1576,15 +1588,38 @@ static LogContext* log_context_detach(LogContext *c) {
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
assert(_log_context_num_fields >= strv_length(c->fields) + c->n_input_iovec);
|
||||
assert(_log_context_num_fields >= strv_length(c->fields) + c->n_input_iovec +!!c->key);
|
||||
_log_context_num_fields -= strv_length(c->fields);
|
||||
_log_context_num_fields -= c->n_input_iovec;
|
||||
_log_context_num_fields -= !!c->key;
|
||||
|
||||
LIST_REMOVE(ll, _log_context, c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LogContext* log_context_new(char **fields, bool owned) {
|
||||
LogContext* log_context_new(const char *key, const char *value) {
|
||||
assert(key);
|
||||
assert(endswith(key, "="));
|
||||
assert(value);
|
||||
|
||||
LIST_FOREACH(ll, i, _log_context)
|
||||
if (i->key == key && i->value == value)
|
||||
return log_context_ref(i);
|
||||
|
||||
LogContext *c = new(LogContext, 1);
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
*c = (LogContext) {
|
||||
.n_ref = 1,
|
||||
.key = (char *) key,
|
||||
.value = (char *) value,
|
||||
};
|
||||
|
||||
return log_context_attach(c);
|
||||
}
|
||||
|
||||
LogContext* log_context_new_strv(char **fields, bool owned) {
|
||||
if (!fields)
|
||||
return NULL;
|
||||
|
||||
@@ -1607,7 +1642,7 @@ LogContext* log_context_new(char **fields, bool owned) {
|
||||
return log_context_attach(c);
|
||||
}
|
||||
|
||||
LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned) {
|
||||
LogContext* log_context_new_iov(struct iovec *input_iovec, size_t n_input_iovec, bool owned) {
|
||||
if (!input_iovec || n_input_iovec == 0)
|
||||
return NULL;
|
||||
|
||||
@@ -1640,6 +1675,8 @@ static LogContext* log_context_free(LogContext *c) {
|
||||
if (c->owned) {
|
||||
strv_free(c->fields);
|
||||
iovec_array_free(c->input_iovec, c->n_input_iovec);
|
||||
free(c->key);
|
||||
free(c->value);
|
||||
}
|
||||
|
||||
return mfree(c);
|
||||
@@ -1647,16 +1684,16 @@ static LogContext* log_context_free(LogContext *c) {
|
||||
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(LogContext, log_context, log_context_free);
|
||||
|
||||
LogContext* log_context_new_consume(char **fields) {
|
||||
LogContext *c = log_context_new(fields, /*owned=*/ true);
|
||||
LogContext* log_context_new_strv_consume(char **fields) {
|
||||
LogContext *c = log_context_new_strv(fields, /*owned=*/ true);
|
||||
if (!c)
|
||||
strv_free(fields);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
LogContext* log_context_new_consumev(struct iovec *input_iovec, size_t n_input_iovec) {
|
||||
LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ true);
|
||||
LogContext* log_context_new_iov_consume(struct iovec *input_iovec, size_t n_input_iovec) {
|
||||
LogContext *c = log_context_new_iov(input_iovec, n_input_iovec, /*owned=*/ true);
|
||||
if (!c)
|
||||
iovec_array_free(input_iovec, n_input_iovec);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user