static const struct connection_settings stats_client_set = {
.service_name_in = "stats-server",
.service_name_out = "stats-client",
- .major_version = 3,
+ .major_version = 4,
.minor_version = 0,
.input_max_size = SIZE_MAX,
};
static void
-stats_event_write(struct event *event, const struct failure_context *ctx,
- string_t *str, bool begin)
+stats_event_write(struct event *event, struct event *global_event,
+ const struct failure_context *ctx, string_t *str, bool begin)
{
struct event *merged_event;
struct event *parent_event;
if (parent_event != NULL) {
if (parent_event->sent_to_stats_id !=
parent_event->change_id)
- stats_event_write(parent_event, ctx, str, TRUE);
+ stats_event_write(parent_event, NULL, ctx, str, TRUE);
i_assert(parent_event->sent_to_stats_id != 0);
}
if (begin) {
str_printfa(str, "%s\t%"PRIu64"\t", cmd, event->id);
event->sent_to_stats_id = event->change_id;
} else {
- str_append(str, "EVENT\t");
+ str_printfa(str, "EVENT\t%"PRIu64"\t",
+ global_event == NULL ? 0 : global_event->id);
}
str_printfa(str, "%"PRIu64"\t",
parent_event == NULL ? 0 : parent_event->id);
return;
/* Need to send the event for stats and/or export */
-
string_t *str = t_str_new(256);
- stats_event_write(event, ctx, str, FALSE);
+
+ struct event *global_event = event_get_global();
+ if (global_event != NULL)
+ stats_event_write(global_event, NULL, ctx, str, TRUE);
+
+ stats_event_write(event, global_event, ctx, str, FALSE);
o_stream_nsend(client->conn.output, str_data(str), str_len(str));
}
int fd;
struct ostream *stats_data_out;
struct server_connection *conn = (struct server_connection *)_conn;
- const char *handshake = "VERSION\tstats-server\t3\t0\n"
+ const char *handshake = "VERSION\tstats-server\t4\t0\n"
"FILTER\tcategory=test1 OR category=test2 OR category=test3 OR "
"category=test4 OR category=test5\n";
const char *line = NULL;
event_unref(&single_ev);
test_assert(
compare_test_stats_to(
- "EVENT 0 1 0 0"
+ "EVENT 0 0 1 0 0"
" s"__FILE__" %d"
" l0 0 ctest1 Skey1 str1\n", l));
test_end();
event_unref(&child_ev);
test_assert(
compare_test_stats_to(
- "EVENT %"PRIu64" 1 0 0"
+ "EVENT 0 %"PRIu64" 1 0 0"
" s"__FILE__" %d"
" l0 0 ctest2\n"
"END 9\n", id, l));
compare_test_stats_to(
"BEGIN %"PRIu64" 0 1 0 0"
" s"__FILE__" %d ctest1\n"
- "EVENT %"PRIu64" 1 1 0"
+ "EVENT 0 %"PRIu64" 1 1 0"
" s"__FILE__" %d"
" l1 0 ctest2\n"
"END\t%"PRIu64"\n", idp, lp, idp, l, idp));
event_unref(&merge_ev2);
test_assert(
compare_test_stats_to(
- "EVENT 0 1 0 0"
+ "EVENT 0 0 1 0 0"
" s"__FILE__" %d l0 0"
" ctest3 ctest2 ctest1 Tkey3"
" 10 0 Ikey2 20"
event_unref(&merge_ev2);
test_assert(
compare_test_stats_to(
- "EVENT %"PRIu64" 1 0 0"
+ "EVENT 0 %"PRIu64" 1 0 0"
" s"__FILE__" %d l0 0"
" ctest3 ctest2 ctest1 Tkey3"
" 10 0 Ikey2 20"
compare_test_stats_to(
"BEGIN %"PRIu64" 0 1 0 0"
" s"__FILE__" %d ctest1\n"
- "EVENT %"PRIu64" 1 3 0 "
+ "EVENT 0 %"PRIu64" 1 3 0 "
"s"__FILE__" %d l3 0"
" ctest2\nEND\t%"PRIu64"\n", id, lp, id, l, id));
test_end();
compare_test_stats_to(
"BEGIN %"PRIu64" 0 1 0 0"
" s"__FILE__" %d ctest1\n"
- "EVENT %"PRIu64" 1 3 0 "
+ "EVENT 0 %"PRIu64" 1 3 0 "
"s"__FILE__" %d l3 0 "
"ctest4 ctest5 Tkey3 10 0 Skey4"
" str4\nEND\t%"PRIu64"\n", id, lp, id, l, id));
"BEGIN %"PRIu64" 0 1 0 0"
" s"__FILE__" %d ctest1"
" Ia 1\n"
- "EVENT %"PRIu64" 1 1 0"
+ "EVENT 0 %"PRIu64" 1 1 0"
" s"__FILE__" %d"
" l1 0 ctest2" " Ib 2\n"
/* second e_info() */
"BEGIN %"PRIu64" %"PRIu64" 1 0 0"
" s"__FILE__" %d"
" l0 0 ctest2 Ib 2\n"
- "EVENT %"PRIu64" 1 1 0"
+ "EVENT 0 %"PRIu64" 1 1 0"
" s"__FILE__" %d"
" l1 0 ctest3"
" Ic 3\n"
test_assert(
compare_test_stats_to(
/* first e_info() */
- "EVENT %"PRIu64" 1 1 0"
+ "EVENT 0 %"PRIu64" 1 1 0"
" s"__FILE__" %d"
" l1 0 ctest1\n"
"BEGIN %"PRIu64" 0 1 0 0"
" s"__FILE__" %d"
" l0 0 ctest1\n"
- "EVENT %"PRIu64" 1 1 0"
+ "EVENT 0 %"PRIu64" 1 1 0"
" s"__FILE__" %d"
" l1 0 ctest2\n"
"UPDATE %"PRIu64" 0 1 0"
" s"__FILE__" %d"
" l1 0 ctest1 Itest1 1\n"
- "EVENT %"PRIu64" 1 1 0"
+ "EVENT 0 %"PRIu64" 1 1 0"
" s"__FILE__" %d"
" l1 0 ctest2\n"
"END %"PRIu64"\n",
test_end();
}
+static void test_global_event(void)
+{
+ TST_BEGIN("merge events global");
+ struct event *merge_ev1 = event_create(NULL);
+ event_add_category(merge_ev1, &test_cats[0]);
+ event_add_str(merge_ev1,test_fields[0].key, test_fields[0].value.str);
+ struct event *merge_ev2 = event_create(merge_ev1);
+ event_add_int(merge_ev2,test_fields[1].key, test_fields[1].value.intmax);
+
+ struct event *global_event = event_create(NULL);
+ int global_event_line = __LINE__ - 1;
+ uint64_t global_event_id = global_event->id;
+ event_add_str(global_event, "global", "value");
+ event_push_global(global_event);
+
+ struct timeval tv;
+ event_get_create_time(merge_ev1, &tv);
+
+ e_info(merge_ev2, "info message");
+ int log_line = __LINE__ - 1;
+
+ event_pop_global(global_event);
+ event_unref(&merge_ev1);
+ event_unref(&merge_ev2);
+ event_unref(&global_event);
+
+ test_assert(
+ compare_test_stats_to(
+ "BEGIN\t%"PRIu64"\t0\t1\t0\t0"
+ "\ts"__FILE__"\t%d"
+ "\tSglobal\tvalue\n"
+ "EVENT\t%"PRIu64"\t0\t1\t0\t0"
+ "\ts"__FILE__"\t%d\tl0\t0"
+ "\tctest1\tIkey2\t20\tSkey1\tstr1\n"
+ "END\t%"PRIu64"\n",
+ global_event_id, global_event_line,
+ global_event_id, log_line,
+ global_event_id));
+ test_end();
+}
+
static int run_tests(void)
{
int ret;
test_merge_events_skip_parents,
test_parent_update_post_send,
test_large_event_id,
+ test_global_event,
NULL
};
struct ioloop *ioloop = io_loop_create();
writer_client_input_event(struct writer_client *client,
const char *const *args, const char **error_r)
{
- struct event *event;
- uint64_t parent_event_id;
+ struct event *event, *global_event = NULL;
+ uint64_t parent_event_id, global_event_id;
+ bool ret;
- if (args[0] == NULL || str_to_uint64(args[0], &parent_event_id) < 0) {
+ if (args[1] == NULL || str_to_uint64(args[0], &global_event_id) < 0) {
+ *error_r = "Invalid global event ID";
+ return FALSE;
+ }
+ if (args[1] == NULL || str_to_uint64(args[1], &parent_event_id) < 0) {
*error_r = "Invalid parent ID";
return FALSE;
}
- if (!writer_client_run_event(client, parent_event_id, args+1, &event, error_r))
+
+ if (global_event_id != 0) {
+ struct stats_event *stats_global_event =
+ writer_client_find_event(client, global_event_id);
+ if (stats_global_event == NULL) {
+ *error_r = "Unknown global event ID";
+ return FALSE;
+ }
+ global_event = stats_global_event->event;
+ event_push_global(global_event);
+ }
+
+ ret = writer_client_run_event(client, parent_event_id, args+2,
+ &event, error_r);
+ if (global_event != NULL)
+ event_pop_global(global_event);
+ if (!ret)
return FALSE;
event_unref(&event);
return TRUE;
static struct connection_settings client_set = {
.service_name_in = "stats-client",
.service_name_out = "stats-server",
- .major_version = 3,
+ .major_version = 4,
.minor_version = 0,
.input_max_size = 1024*128, /* "big enough" */