git

Форк
0
/
tr2_tgt_event.c 
700 строк · 20.1 Кб
1
#include "git-compat-util.h"
2
#include "config.h"
3
#include "json-writer.h"
4
#include "repository.h"
5
#include "run-command.h"
6
#include "version.h"
7
#include "trace2/tr2_dst.h"
8
#include "trace2/tr2_tbuf.h"
9
#include "trace2/tr2_sid.h"
10
#include "trace2/tr2_sysenv.h"
11
#include "trace2/tr2_tgt.h"
12
#include "trace2/tr2_tls.h"
13
#include "trace2/tr2_tmr.h"
14

15
static struct tr2_dst tr2dst_event = {
16
	.sysenv_var = TR2_SYSENV_EVENT,
17
};
18

19
/*
20
 * The version number of the JSON data generated by the EVENT target in this
21
 * source file. The version should be incremented if new event types are added,
22
 * if existing fields are removed, or if there are significant changes in
23
 * interpretation of existing events or fields. Smaller changes, such as adding
24
 * a new field to an existing event, do not require an increment to the EVENT
25
 * format version.
26
 */
27
#define TR2_EVENT_VERSION "3"
28

29
/*
30
 * Region nesting limit for messages written to the event target.
31
 *
32
 * The "region_enter" and "region_leave" messages (especially recursive
33
 * messages such as those produced while diving the worktree or index)
34
 * are primarily intended for the performance target during debugging.
35
 *
36
 * Some of the outer-most messages, however, may be of interest to the
37
 * event target.  Use the TR2_SYSENV_EVENT_NESTING setting to increase
38
 * region details in the event target.
39
 */
40
static int tr2env_event_max_nesting_levels = 2;
41

42
/*
43
 * Use the TR2_SYSENV_EVENT_BRIEF to omit the <time>, <file>, and
44
 * <line> fields from most events.
45
 */
46
static int tr2env_event_be_brief;
47

48
static int fn_init(void)
49
{
50
	int want = tr2_dst_trace_want(&tr2dst_event);
51
	int max_nesting;
52
	int want_brief;
53
	const char *nesting;
54
	const char *brief;
55

56
	if (!want)
57
		return want;
58

59
	nesting = tr2_sysenv_get(TR2_SYSENV_EVENT_NESTING);
60
	if (nesting && *nesting && ((max_nesting = atoi(nesting)) > 0))
61
		tr2env_event_max_nesting_levels = max_nesting;
62

63
	brief = tr2_sysenv_get(TR2_SYSENV_EVENT_BRIEF);
64
	if (brief && *brief &&
65
	    ((want_brief = git_parse_maybe_bool(brief)) != -1))
66
		tr2env_event_be_brief = want_brief;
67

68
	return want;
69
}
70

71
static void fn_term(void)
72
{
73
	tr2_dst_trace_disable(&tr2dst_event);
74
}
75

76
/*
77
 * Append common key-value pairs to the currently open JSON object.
78
 *     "event:"<event_name>"
79
 *      "sid":"<sid>"
80
 *   "thread":"<thread_name>"
81
 *     "time":"<time>"
82
 *     "file":"<filename>"
83
 *     "line":<line_number>
84
 *     "repo":<repo_id>
85
 */
86
static void event_fmt_prepare(const char *event_name, const char *file,
87
			      int line, const struct repository *repo,
88
			      struct json_writer *jw)
89
{
90
	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
91
	struct tr2_tbuf tb_now;
92

93
	jw_object_string(jw, "event", event_name);
94
	jw_object_string(jw, "sid", tr2_sid_get());
95
	jw_object_string(jw, "thread", ctx->thread_name);
96

97
	/*
98
	 * In brief mode, only emit <time> on these 2 event types.
99
	 */
100
	if (!tr2env_event_be_brief || !strcmp(event_name, "version") ||
101
	    !strcmp(event_name, "atexit")) {
102
		tr2_tbuf_utc_datetime_extended(&tb_now);
103
		jw_object_string(jw, "time", tb_now.buf);
104
	}
105

106
	if (!tr2env_event_be_brief && file && *file) {
107
		jw_object_string(jw, "file", file);
108
		jw_object_intmax(jw, "line", line);
109
	}
110

111
	if (repo)
112
		jw_object_intmax(jw, "repo", repo->trace2_repo_id);
113
}
114

115
static void fn_too_many_files_fl(const char *file, int line)
116
{
117
	const char *event_name = "too_many_files";
118
	struct json_writer jw = JSON_WRITER_INIT;
119

120
	jw_object_begin(&jw, 0);
121
	event_fmt_prepare(event_name, file, line, NULL, &jw);
122
	jw_end(&jw);
123

124
	tr2_dst_write_line(&tr2dst_event, &jw.json);
125
	jw_release(&jw);
126
}
127

128
static void fn_version_fl(const char *file, int line)
129
{
130
	const char *event_name = "version";
131
	struct json_writer jw = JSON_WRITER_INIT;
132

133
	jw_object_begin(&jw, 0);
134
	event_fmt_prepare(event_name, file, line, NULL, &jw);
135
	jw_object_string(&jw, "evt", TR2_EVENT_VERSION);
136
	jw_object_string(&jw, "exe", git_version_string);
137
	jw_end(&jw);
138

139
	tr2_dst_write_line(&tr2dst_event, &jw.json);
140
	jw_release(&jw);
141

142
	if (tr2dst_event.too_many_files)
143
		fn_too_many_files_fl(file, line);
144
}
145

146
static void fn_start_fl(const char *file, int line,
147
			uint64_t us_elapsed_absolute, const char **argv)
148
{
149
	const char *event_name = "start";
150
	struct json_writer jw = JSON_WRITER_INIT;
151
	double t_abs = (double)us_elapsed_absolute / 1000000.0;
152

153
	jw_object_begin(&jw, 0);
154
	event_fmt_prepare(event_name, file, line, NULL, &jw);
155
	jw_object_double(&jw, "t_abs", 6, t_abs);
156
	jw_object_inline_begin_array(&jw, "argv");
157
	jw_array_argv(&jw, argv);
158
	jw_end(&jw);
159
	jw_end(&jw);
160

161
	tr2_dst_write_line(&tr2dst_event, &jw.json);
162
	jw_release(&jw);
163
}
164

165
static void fn_exit_fl(const char *file, int line, uint64_t us_elapsed_absolute,
166
		       int code)
167
{
168
	const char *event_name = "exit";
169
	struct json_writer jw = JSON_WRITER_INIT;
170
	double t_abs = (double)us_elapsed_absolute / 1000000.0;
171

172
	jw_object_begin(&jw, 0);
173
	event_fmt_prepare(event_name, file, line, NULL, &jw);
174
	jw_object_double(&jw, "t_abs", 6, t_abs);
175
	jw_object_intmax(&jw, "code", code);
176
	jw_end(&jw);
177

178
	tr2_dst_write_line(&tr2dst_event, &jw.json);
179
	jw_release(&jw);
180
}
181

182
static void fn_signal(uint64_t us_elapsed_absolute, int signo)
183
{
184
	const char *event_name = "signal";
185
	struct json_writer jw = JSON_WRITER_INIT;
186
	double t_abs = (double)us_elapsed_absolute / 1000000.0;
187

188
	jw_object_begin(&jw, 0);
189
	event_fmt_prepare(event_name, __FILE__, __LINE__, NULL, &jw);
190
	jw_object_double(&jw, "t_abs", 6, t_abs);
191
	jw_object_intmax(&jw, "signo", signo);
192
	jw_end(&jw);
193

194
	tr2_dst_write_line(&tr2dst_event, &jw.json);
195
	jw_release(&jw);
196
}
197

198
static void fn_atexit(uint64_t us_elapsed_absolute, int code)
199
{
200
	const char *event_name = "atexit";
201
	struct json_writer jw = JSON_WRITER_INIT;
202
	double t_abs = (double)us_elapsed_absolute / 1000000.0;
203

204
	jw_object_begin(&jw, 0);
205
	event_fmt_prepare(event_name, __FILE__, __LINE__, NULL, &jw);
206
	jw_object_double(&jw, "t_abs", 6, t_abs);
207
	jw_object_intmax(&jw, "code", code);
208
	jw_end(&jw);
209

210
	tr2_dst_write_line(&tr2dst_event, &jw.json);
211
	jw_release(&jw);
212
}
213

214
static void maybe_add_string_va(struct json_writer *jw, const char *field_name,
215
				const char *fmt, va_list ap)
216
{
217
	if (fmt && *fmt) {
218
		va_list copy_ap;
219
		struct strbuf buf = STRBUF_INIT;
220

221
		va_copy(copy_ap, ap);
222
		strbuf_vaddf(&buf, fmt, copy_ap);
223
		va_end(copy_ap);
224

225
		jw_object_string(jw, field_name, buf.buf);
226
		strbuf_release(&buf);
227
		return;
228
	}
229
}
230

231
static void fn_error_va_fl(const char *file, int line, const char *fmt,
232
			   va_list ap)
233
{
234
	const char *event_name = "error";
235
	struct json_writer jw = JSON_WRITER_INIT;
236

237
	jw_object_begin(&jw, 0);
238
	event_fmt_prepare(event_name, file, line, NULL, &jw);
239
	maybe_add_string_va(&jw, "msg", fmt, ap);
240
	/*
241
	 * Also emit the format string as a field in case
242
	 * post-processors want to aggregate common error
243
	 * messages by type without argument fields (such
244
	 * as pathnames or branch names) cluttering it up.
245
	 */
246
	if (fmt && *fmt)
247
		jw_object_string(&jw, "fmt", fmt);
248
	jw_end(&jw);
249

250
	tr2_dst_write_line(&tr2dst_event, &jw.json);
251
	jw_release(&jw);
252
}
253

254
static void fn_command_path_fl(const char *file, int line, const char *pathname)
255
{
256
	const char *event_name = "cmd_path";
257
	struct json_writer jw = JSON_WRITER_INIT;
258

259
	jw_object_begin(&jw, 0);
260
	event_fmt_prepare(event_name, file, line, NULL, &jw);
261
	jw_object_string(&jw, "path", pathname);
262
	jw_end(&jw);
263

264
	tr2_dst_write_line(&tr2dst_event, &jw.json);
265
	jw_release(&jw);
266
}
267

268
static void fn_command_ancestry_fl(const char *file, int line, const char **parent_names)
269
{
270
	const char *event_name = "cmd_ancestry";
271
	const char *parent_name = NULL;
272
	struct json_writer jw = JSON_WRITER_INIT;
273

274
	jw_object_begin(&jw, 0);
275
	event_fmt_prepare(event_name, file, line, NULL, &jw);
276
	jw_object_inline_begin_array(&jw, "ancestry");
277

278
	while ((parent_name = *parent_names++))
279
		jw_array_string(&jw, parent_name);
280

281
	jw_end(&jw); /* 'ancestry' array */
282
	jw_end(&jw); /* event object */
283

284
	tr2_dst_write_line(&tr2dst_event, &jw.json);
285
	jw_release(&jw);
286
}
287

288
static void fn_command_name_fl(const char *file, int line, const char *name,
289
			       const char *hierarchy)
290
{
291
	const char *event_name = "cmd_name";
292
	struct json_writer jw = JSON_WRITER_INIT;
293

294
	jw_object_begin(&jw, 0);
295
	event_fmt_prepare(event_name, file, line, NULL, &jw);
296
	jw_object_string(&jw, "name", name);
297
	if (hierarchy && *hierarchy)
298
		jw_object_string(&jw, "hierarchy", hierarchy);
299
	jw_end(&jw);
300

301
	tr2_dst_write_line(&tr2dst_event, &jw.json);
302
	jw_release(&jw);
303
}
304

305
static void fn_command_mode_fl(const char *file, int line, const char *mode)
306
{
307
	const char *event_name = "cmd_mode";
308
	struct json_writer jw = JSON_WRITER_INIT;
309

310
	jw_object_begin(&jw, 0);
311
	event_fmt_prepare(event_name, file, line, NULL, &jw);
312
	jw_object_string(&jw, "name", mode);
313
	jw_end(&jw);
314

315
	tr2_dst_write_line(&tr2dst_event, &jw.json);
316
	jw_release(&jw);
317
}
318

319
static void fn_alias_fl(const char *file, int line, const char *alias,
320
			const char **argv)
321
{
322
	const char *event_name = "alias";
323
	struct json_writer jw = JSON_WRITER_INIT;
324

325
	jw_object_begin(&jw, 0);
326
	event_fmt_prepare(event_name, file, line, NULL, &jw);
327
	jw_object_string(&jw, "alias", alias);
328
	jw_object_inline_begin_array(&jw, "argv");
329
	jw_array_argv(&jw, argv);
330
	jw_end(&jw);
331
	jw_end(&jw);
332

333
	tr2_dst_write_line(&tr2dst_event, &jw.json);
334
	jw_release(&jw);
335
}
336

337
static void fn_child_start_fl(const char *file, int line,
338
			      uint64_t us_elapsed_absolute UNUSED,
339
			      const struct child_process *cmd)
340
{
341
	const char *event_name = "child_start";
342
	struct json_writer jw = JSON_WRITER_INIT;
343

344
	jw_object_begin(&jw, 0);
345
	event_fmt_prepare(event_name, file, line, NULL, &jw);
346
	jw_object_intmax(&jw, "child_id", cmd->trace2_child_id);
347
	if (cmd->trace2_hook_name) {
348
		jw_object_string(&jw, "child_class", "hook");
349
		jw_object_string(&jw, "hook_name", cmd->trace2_hook_name);
350
	} else {
351
		const char *child_class =
352
			cmd->trace2_child_class ? cmd->trace2_child_class : "?";
353
		jw_object_string(&jw, "child_class", child_class);
354
	}
355
	if (cmd->dir)
356
		jw_object_string(&jw, "cd", cmd->dir);
357
	jw_object_bool(&jw, "use_shell", cmd->use_shell);
358
	jw_object_inline_begin_array(&jw, "argv");
359
	if (cmd->git_cmd)
360
		jw_array_string(&jw, "git");
361
	jw_array_argv(&jw, cmd->args.v);
362
	jw_end(&jw);
363
	jw_end(&jw);
364

365
	tr2_dst_write_line(&tr2dst_event, &jw.json);
366
	jw_release(&jw);
367
}
368

369
static void fn_child_exit_fl(const char *file, int line,
370
			     uint64_t us_elapsed_absolute UNUSED,
371
			     int cid, int pid,
372
			     int code, uint64_t us_elapsed_child)
373
{
374
	const char *event_name = "child_exit";
375
	struct json_writer jw = JSON_WRITER_INIT;
376
	double t_rel = (double)us_elapsed_child / 1000000.0;
377

378
	jw_object_begin(&jw, 0);
379
	event_fmt_prepare(event_name, file, line, NULL, &jw);
380
	jw_object_intmax(&jw, "child_id", cid);
381
	jw_object_intmax(&jw, "pid", pid);
382
	jw_object_intmax(&jw, "code", code);
383
	jw_object_double(&jw, "t_rel", 6, t_rel);
384
	jw_end(&jw);
385

386
	tr2_dst_write_line(&tr2dst_event, &jw.json);
387

388
	jw_release(&jw);
389
}
390

391
static void fn_child_ready_fl(const char *file, int line,
392
			      uint64_t us_elapsed_absolute UNUSED,
393
			      int cid, int pid,
394
			      const char *ready, uint64_t us_elapsed_child)
395
{
396
	const char *event_name = "child_ready";
397
	struct json_writer jw = JSON_WRITER_INIT;
398
	double t_rel = (double)us_elapsed_child / 1000000.0;
399

400
	jw_object_begin(&jw, 0);
401
	event_fmt_prepare(event_name, file, line, NULL, &jw);
402
	jw_object_intmax(&jw, "child_id", cid);
403
	jw_object_intmax(&jw, "pid", pid);
404
	jw_object_string(&jw, "ready", ready);
405
	jw_object_double(&jw, "t_rel", 6, t_rel);
406
	jw_end(&jw);
407

408
	tr2_dst_write_line(&tr2dst_event, &jw.json);
409

410
	jw_release(&jw);
411
}
412

413
static void fn_thread_start_fl(const char *file, int line,
414
			       uint64_t us_elapsed_absolute UNUSED)
415
{
416
	const char *event_name = "thread_start";
417
	struct json_writer jw = JSON_WRITER_INIT;
418

419
	jw_object_begin(&jw, 0);
420
	event_fmt_prepare(event_name, file, line, NULL, &jw);
421
	jw_end(&jw);
422

423
	tr2_dst_write_line(&tr2dst_event, &jw.json);
424
	jw_release(&jw);
425
}
426

427
static void fn_thread_exit_fl(const char *file, int line,
428
			      uint64_t us_elapsed_absolute UNUSED,
429
			      uint64_t us_elapsed_thread)
430
{
431
	const char *event_name = "thread_exit";
432
	struct json_writer jw = JSON_WRITER_INIT;
433
	double t_rel = (double)us_elapsed_thread / 1000000.0;
434

435
	jw_object_begin(&jw, 0);
436
	event_fmt_prepare(event_name, file, line, NULL, &jw);
437
	jw_object_double(&jw, "t_rel", 6, t_rel);
438
	jw_end(&jw);
439

440
	tr2_dst_write_line(&tr2dst_event, &jw.json);
441
	jw_release(&jw);
442
}
443

444
static void fn_exec_fl(const char *file, int line,
445
		       uint64_t us_elapsed_absolute UNUSED,
446
		       int exec_id, const char *exe, const char **argv)
447
{
448
	const char *event_name = "exec";
449
	struct json_writer jw = JSON_WRITER_INIT;
450

451
	jw_object_begin(&jw, 0);
452
	event_fmt_prepare(event_name, file, line, NULL, &jw);
453
	jw_object_intmax(&jw, "exec_id", exec_id);
454
	if (exe)
455
		jw_object_string(&jw, "exe", exe);
456
	jw_object_inline_begin_array(&jw, "argv");
457
	jw_array_argv(&jw, argv);
458
	jw_end(&jw);
459
	jw_end(&jw);
460

461
	tr2_dst_write_line(&tr2dst_event, &jw.json);
462
	jw_release(&jw);
463
}
464

465
static void fn_exec_result_fl(const char *file, int line,
466
			      uint64_t us_elapsed_absolute UNUSED,
467
			      int exec_id, int code)
468
{
469
	const char *event_name = "exec_result";
470
	struct json_writer jw = JSON_WRITER_INIT;
471

472
	jw_object_begin(&jw, 0);
473
	event_fmt_prepare(event_name, file, line, NULL, &jw);
474
	jw_object_intmax(&jw, "exec_id", exec_id);
475
	jw_object_intmax(&jw, "code", code);
476
	jw_end(&jw);
477

478
	tr2_dst_write_line(&tr2dst_event, &jw.json);
479
	jw_release(&jw);
480
}
481

482
static void fn_param_fl(const char *file, int line, const char *param,
483
			const char *value, const struct key_value_info *kvi)
484
{
485
	const char *event_name = "def_param";
486
	struct json_writer jw = JSON_WRITER_INIT;
487
	enum config_scope scope = kvi->scope;
488
	const char *scope_name = config_scope_name(scope);
489

490
	jw_object_begin(&jw, 0);
491
	event_fmt_prepare(event_name, file, line, NULL, &jw);
492
	jw_object_string(&jw, "scope", scope_name);
493
	jw_object_string(&jw, "param", param);
494
	jw_object_string(&jw, "value", value);
495
	jw_end(&jw);
496

497
	tr2_dst_write_line(&tr2dst_event, &jw.json);
498
	jw_release(&jw);
499
}
500

501
static void fn_repo_fl(const char *file, int line,
502
		       const struct repository *repo)
503
{
504
	const char *event_name = "def_repo";
505
	struct json_writer jw = JSON_WRITER_INIT;
506

507
	jw_object_begin(&jw, 0);
508
	event_fmt_prepare(event_name, file, line, repo, &jw);
509
	jw_object_string(&jw, "worktree", repo->worktree);
510
	jw_end(&jw);
511

512
	tr2_dst_write_line(&tr2dst_event, &jw.json);
513
	jw_release(&jw);
514
}
515

516
static void fn_region_enter_printf_va_fl(const char *file, int line,
517
					 uint64_t us_elapsed_absolute UNUSED,
518
					 const char *category,
519
					 const char *label,
520
					 const struct repository *repo,
521
					 const char *fmt, va_list ap)
522
{
523
	const char *event_name = "region_enter";
524
	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
525
	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
526
		struct json_writer jw = JSON_WRITER_INIT;
527

528
		jw_object_begin(&jw, 0);
529
		event_fmt_prepare(event_name, file, line, repo, &jw);
530
		jw_object_intmax(&jw, "nesting", ctx->nr_open_regions);
531
		if (category)
532
			jw_object_string(&jw, "category", category);
533
		if (label)
534
			jw_object_string(&jw, "label", label);
535
		maybe_add_string_va(&jw, "msg", fmt, ap);
536
		jw_end(&jw);
537

538
		tr2_dst_write_line(&tr2dst_event, &jw.json);
539
		jw_release(&jw);
540
	}
541
}
542

543
static void fn_region_leave_printf_va_fl(
544
	const char *file, int line, uint64_t us_elapsed_absolute UNUSED,
545
	uint64_t us_elapsed_region, const char *category, const char *label,
546
	const struct repository *repo, const char *fmt, va_list ap)
547
{
548
	const char *event_name = "region_leave";
549
	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
550
	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
551
		struct json_writer jw = JSON_WRITER_INIT;
552
		double t_rel = (double)us_elapsed_region / 1000000.0;
553

554
		jw_object_begin(&jw, 0);
555
		event_fmt_prepare(event_name, file, line, repo, &jw);
556
		jw_object_double(&jw, "t_rel", 6, t_rel);
557
		jw_object_intmax(&jw, "nesting", ctx->nr_open_regions);
558
		if (category)
559
			jw_object_string(&jw, "category", category);
560
		if (label)
561
			jw_object_string(&jw, "label", label);
562
		maybe_add_string_va(&jw, "msg", fmt, ap);
563
		jw_end(&jw);
564

565
		tr2_dst_write_line(&tr2dst_event, &jw.json);
566
		jw_release(&jw);
567
	}
568
}
569

570
static void fn_data_fl(const char *file, int line, uint64_t us_elapsed_absolute,
571
		       uint64_t us_elapsed_region, const char *category,
572
		       const struct repository *repo, const char *key,
573
		       const char *value)
574
{
575
	const char *event_name = "data";
576
	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
577
	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
578
		struct json_writer jw = JSON_WRITER_INIT;
579
		double t_abs = (double)us_elapsed_absolute / 1000000.0;
580
		double t_rel = (double)us_elapsed_region / 1000000.0;
581

582
		jw_object_begin(&jw, 0);
583
		event_fmt_prepare(event_name, file, line, repo, &jw);
584
		jw_object_double(&jw, "t_abs", 6, t_abs);
585
		jw_object_double(&jw, "t_rel", 6, t_rel);
586
		jw_object_intmax(&jw, "nesting", ctx->nr_open_regions);
587
		jw_object_string(&jw, "category", category);
588
		jw_object_string(&jw, "key", key);
589
		jw_object_string(&jw, "value", value);
590
		jw_end(&jw);
591

592
		tr2_dst_write_line(&tr2dst_event, &jw.json);
593
		jw_release(&jw);
594
	}
595
}
596

597
static void fn_data_json_fl(const char *file, int line,
598
			    uint64_t us_elapsed_absolute,
599
			    uint64_t us_elapsed_region, const char *category,
600
			    const struct repository *repo, const char *key,
601
			    const struct json_writer *value)
602
{
603
	const char *event_name = "data_json";
604
	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
605
	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
606
		struct json_writer jw = JSON_WRITER_INIT;
607
		double t_abs = (double)us_elapsed_absolute / 1000000.0;
608
		double t_rel = (double)us_elapsed_region / 1000000.0;
609

610
		jw_object_begin(&jw, 0);
611
		event_fmt_prepare(event_name, file, line, repo, &jw);
612
		jw_object_double(&jw, "t_abs", 6, t_abs);
613
		jw_object_double(&jw, "t_rel", 6, t_rel);
614
		jw_object_intmax(&jw, "nesting", ctx->nr_open_regions);
615
		jw_object_string(&jw, "category", category);
616
		jw_object_string(&jw, "key", key);
617
		jw_object_sub_jw(&jw, "value", value);
618
		jw_end(&jw);
619

620
		tr2_dst_write_line(&tr2dst_event, &jw.json);
621
		jw_release(&jw);
622
	}
623
}
624

625
static void fn_timer(const struct tr2_timer_metadata *meta,
626
		     const struct tr2_timer *timer,
627
		     int is_final_data)
628
{
629
	const char *event_name = is_final_data ? "timer" : "th_timer";
630
	struct json_writer jw = JSON_WRITER_INIT;
631
	double t_total = NS_TO_SEC(timer->total_ns);
632
	double t_min = NS_TO_SEC(timer->min_ns);
633
	double t_max = NS_TO_SEC(timer->max_ns);
634

635
	jw_object_begin(&jw, 0);
636
	event_fmt_prepare(event_name, __FILE__, __LINE__, NULL, &jw);
637
	jw_object_string(&jw, "category", meta->category);
638
	jw_object_string(&jw, "name", meta->name);
639
	jw_object_intmax(&jw, "intervals", timer->interval_count);
640
	jw_object_double(&jw, "t_total", 6, t_total);
641
	jw_object_double(&jw, "t_min", 6, t_min);
642
	jw_object_double(&jw, "t_max", 6, t_max);
643
	jw_end(&jw);
644

645
	tr2_dst_write_line(&tr2dst_event, &jw.json);
646
	jw_release(&jw);
647
}
648

649
static void fn_counter(const struct tr2_counter_metadata *meta,
650
		       const struct tr2_counter *counter,
651
		       int is_final_data)
652
{
653
	const char *event_name = is_final_data ? "counter" : "th_counter";
654
	struct json_writer jw = JSON_WRITER_INIT;
655

656
	jw_object_begin(&jw, 0);
657
	event_fmt_prepare(event_name, __FILE__, __LINE__, NULL, &jw);
658
	jw_object_string(&jw, "category", meta->category);
659
	jw_object_string(&jw, "name", meta->name);
660
	jw_object_intmax(&jw, "count", counter->value);
661
	jw_end(&jw);
662

663
	tr2_dst_write_line(&tr2dst_event, &jw.json);
664
	jw_release(&jw);
665
}
666

667
struct tr2_tgt tr2_tgt_event = {
668
	.pdst = &tr2dst_event,
669

670
	.pfn_init = fn_init,
671
	.pfn_term = fn_term,
672

673
	.pfn_version_fl = fn_version_fl,
674
	.pfn_start_fl = fn_start_fl,
675
	.pfn_exit_fl = fn_exit_fl,
676
	.pfn_signal = fn_signal,
677
	.pfn_atexit = fn_atexit,
678
	.pfn_error_va_fl = fn_error_va_fl,
679
	.pfn_command_path_fl = fn_command_path_fl,
680
	.pfn_command_ancestry_fl = fn_command_ancestry_fl,
681
	.pfn_command_name_fl = fn_command_name_fl,
682
	.pfn_command_mode_fl = fn_command_mode_fl,
683
	.pfn_alias_fl = fn_alias_fl,
684
	.pfn_child_start_fl = fn_child_start_fl,
685
	.pfn_child_exit_fl = fn_child_exit_fl,
686
	.pfn_child_ready_fl = fn_child_ready_fl,
687
	.pfn_thread_start_fl = fn_thread_start_fl,
688
	.pfn_thread_exit_fl = fn_thread_exit_fl,
689
	.pfn_exec_fl = fn_exec_fl,
690
	.pfn_exec_result_fl = fn_exec_result_fl,
691
	.pfn_param_fl = fn_param_fl,
692
	.pfn_repo_fl = fn_repo_fl,
693
	.pfn_region_enter_printf_va_fl = fn_region_enter_printf_va_fl,
694
	.pfn_region_leave_printf_va_fl = fn_region_leave_printf_va_fl,
695
	.pfn_data_fl = fn_data_fl,
696
	.pfn_data_json_fl = fn_data_json_fl,
697
	.pfn_printf_va_fl = NULL,
698
	.pfn_timer = fn_timer,
699
	.pfn_counter = fn_counter,
700
};
701

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.