@@ -83,6 +83,20 @@ struct child_data_array {
83
83
static struct child_data_array my__child_data ;
84
84
static void free_children (void );
85
85
86
+ struct config_data {
87
+ char * group ;
88
+ struct json_writer jw ;
89
+ };
90
+
91
+ struct config_data_array {
92
+ struct config_data * * array ;
93
+ size_t nr , alloc ;
94
+ };
95
+
96
+ static struct config_data_array my__config_data ;
97
+ static void format_config_data (struct json_writer * jw );
98
+ static void free_config_data (void );
99
+
86
100
static uint64_t my__start_time ;
87
101
static uint64_t my__exit_time ;
88
102
static int my__is_config_loaded ;
@@ -132,6 +146,15 @@ static int want_category(const struct category_filter *cf, const char *category)
132
146
return !!strstr (cf -> categories , category );
133
147
}
134
148
149
+ static void set_config_data_from_category (const struct category_filter * cf ,
150
+ const char * key )
151
+ {
152
+ if (cf -> want == 0 || cf -> want == 1 )
153
+ slog_set_config_data_intmax (key , cf -> want );
154
+ else
155
+ slog_set_config_data_string (key , cf -> categories );
156
+ }
157
+
135
158
/*
136
159
* Compute a new session id for the current process. Build string
137
160
* with the start time and PID of the current process and append
@@ -249,6 +272,18 @@ static void emit_exit_event(void)
249
272
struct json_writer jw = JSON_WRITER_INIT ;
250
273
uint64_t atexit_time = getnanotime () / 1000 ;
251
274
275
+ /*
276
+ * Copy important (and non-obvious) config settings into the
277
+ * "config" section of the "cmd_exit" event. The values of
278
+ * "slog.detail", "slog.timers", and "slog.aux" are used in
279
+ * category want filtering, so post-processors should know the
280
+ * filter settings so that they can tell if an event is missing
281
+ * because of filtering or an error.
282
+ */
283
+ set_config_data_from_category (& my__detail_categories , "slog.detail" );
284
+ set_config_data_from_category (& my__timer_categories , "slog.timers" );
285
+ set_config_data_from_category (& my__aux_categories , "slog.aux" );
286
+
252
287
/* close unterminated forms */
253
288
if (my__errors .json .len )
254
289
jw_end (& my__errors );
@@ -299,6 +334,12 @@ static void emit_exit_event(void)
299
334
}
300
335
jw_end (& jw );
301
336
337
+ if (my__config_data .nr ) {
338
+ jw_object_inline_begin_object (& jw , "config" );
339
+ format_config_data (& jw );
340
+ jw_end (& jw );
341
+ }
342
+
302
343
if (my__timers .nr ) {
303
344
jw_object_inline_begin_object (& jw , "timers" );
304
345
format_timers (& jw );
@@ -479,6 +520,7 @@ static void do_final_steps(int in_signal)
479
520
free_child_summary_data ();
480
521
free_timers ();
481
522
free_children ();
523
+ free_config_data ();
482
524
}
483
525
484
526
static void slog_atexit (void )
@@ -1084,4 +1126,94 @@ static void free_children(void)
1084
1126
my__child_data .alloc = 0 ;
1085
1127
}
1086
1128
1129
+ /*
1130
+ * Split <key> into <group>.<sub_key> (for example "slog.path" into "slog" and "path")
1131
+ * Find or insert <group> in config_data_array[].
1132
+ *
1133
+ * Return config_data_arary[<group>].
1134
+ */
1135
+ static struct config_data * find_config_data (const char * key , const char * * sub_key )
1136
+ {
1137
+ struct config_data * cd ;
1138
+ char * dot ;
1139
+ size_t group_len ;
1140
+ int k ;
1141
+
1142
+ dot = strchr (key , '.' );
1143
+ if (!dot )
1144
+ return NULL ;
1145
+
1146
+ * sub_key = dot + 1 ;
1147
+
1148
+ group_len = dot - key ;
1149
+
1150
+ for (k = 0 ; k < my__config_data .nr ; k ++ ) {
1151
+ cd = my__config_data .array [k ];
1152
+ if (!strncmp (key , cd -> group , group_len ))
1153
+ return cd ;
1154
+ }
1155
+
1156
+ cd = xcalloc (1 , sizeof (struct config_data ));
1157
+ cd -> group = xstrndup (key , group_len );
1158
+
1159
+ jw_object_begin (& cd -> jw , my__is_pretty );
1160
+ /* leave per-group object unterminated for now */
1161
+
1162
+ ALLOC_GROW (my__config_data .array , my__config_data .nr + 1 ,
1163
+ my__config_data .alloc );
1164
+ my__config_data .array [my__config_data .nr ++ ] = cd ;
1165
+
1166
+ return cd ;
1167
+ }
1168
+
1169
+ void slog_set_config_data_string (const char * key , const char * value )
1170
+ {
1171
+ const char * sub_key ;
1172
+ struct config_data * cd = find_config_data (key , & sub_key );
1173
+
1174
+ if (cd )
1175
+ jw_object_string (& cd -> jw , sub_key , value );
1176
+ }
1177
+
1178
+ void slog_set_config_data_intmax (const char * key , intmax_t value )
1179
+ {
1180
+ const char * sub_key ;
1181
+ struct config_data * cd = find_config_data (key , & sub_key );
1182
+
1183
+ if (cd )
1184
+ jw_object_intmax (& cd -> jw , sub_key , value );
1185
+ }
1186
+
1187
+ static void format_config_data (struct json_writer * jw )
1188
+ {
1189
+ int k ;
1190
+
1191
+ for (k = 0 ; k < my__config_data .nr ; k ++ ) {
1192
+ struct config_data * cd = my__config_data .array [k ];
1193
+
1194
+ /* termminate per-group form */
1195
+ jw_end (& cd -> jw );
1196
+
1197
+ /* insert per-category form into containing "config" form */
1198
+ jw_object_sub_jw (jw , cd -> group , & cd -> jw );
1199
+ }
1200
+ }
1201
+
1202
+ static void free_config_data (void )
1203
+ {
1204
+ int k ;
1205
+
1206
+ for (k = 0 ; k < my__config_data .nr ; k ++ ) {
1207
+ struct config_data * cd = my__config_data .array [k ];
1208
+
1209
+ jw_release (& cd -> jw );
1210
+ free (cd -> group );
1211
+ free (cd );
1212
+ }
1213
+
1214
+ FREE_AND_NULL (my__config_data .array );
1215
+ my__config_data .nr = 0 ;
1216
+ my__config_data .alloc = 0 ;
1217
+ }
1218
+
1087
1219
#endif
0 commit comments