1 /***
2  * Copyright 2020 HAProxy Technologies
3  *
4  * This file is part of the HAProxy OpenTracing filter.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 #include "include.h"
21 
22 
23 static struct pool_head *pool_head_ot_span_context __read_mostly = NULL;
24 
25 #ifdef USE_POOL_OT_SPAN_CONTEXT
26 REGISTER_POOL(&pool_head_ot_span_context, "ot_span_context", MAX(sizeof(struct otc_span), sizeof(struct otc_span_context)));
27 #endif
28 
29 
30 #ifdef DEBUG_OT
31 
32 /***
33  * NAME
34  *   ot_text_map_show -
35  *
36  * ARGUMENTS
37  *   text_map -
38  *
39  * DESCRIPTION
40  *   -
41  *
42  * RETURN VALUE
43  *   This function does not return a value.
44  */
ot_text_map_show(const struct otc_text_map * text_map)45 void ot_text_map_show(const struct otc_text_map *text_map)
46 {
47 	FLT_OT_FUNC("%p", text_map);
48 
49 	if (text_map == NULL)
50 		FLT_OT_RETURN();
51 
52 	FLT_OT_DBG_TEXT_MAP(text_map);
53 
54 	if ((text_map->key != NULL) && (text_map->value != NULL) && (text_map->count > 0)) {
55 		size_t i;
56 
57 		for (i = 0; i < text_map->count; i++)
58 			FLT_OT_DBG(3, "  \"%s\" -> \"%s\"", text_map->key[i], text_map->value[i]);
59 	}
60 
61 	FLT_OT_RETURN();
62 }
63 
64 
65 /***
66  * NAME
67  *   ot_debug -
68  *
69  * ARGUMENTS
70  *   This function takes no arguments.
71  *
72  * DESCRIPTION
73  *   -
74  *
75  * RETURN VALUE
76  *   This function does not return a value.
77  */
ot_debug(void)78 void ot_debug(void)
79 {
80 	char buffer[BUFSIZ];
81 
82 	FLT_OT_FUNC("");
83 
84 	otc_statistics(buffer, sizeof(buffer));
85 	FLT_OT_DBG(0, "%s", buffer);
86 
87 	FLT_OT_RETURN();
88 }
89 
90 #endif /* DEBUG_OT */
91 
92 
93 /***
94  * NAME
95  *   ot_mem_malloc -
96  *
97  * ARGUMENTS
98  *   func -
99  *   line -
100  *   size -
101  *
102  * DESCRIPTION
103  *   -
104  *
105  * RETURN VALUE
106  *   -
107  */
ot_mem_malloc(FLT_OT_DBG_ARGS (const char * func,int line,)size_t size)108 static void *ot_mem_malloc(FLT_OT_DBG_ARGS(const char *func, int line, ) size_t size)
109 {
110 	return flt_ot_pool_alloc(pool_head_ot_span_context, size, 1, NULL);
111 }
112 
113 
114 /***
115  * NAME
116  *   ot_mem_free -
117  *
118  * ARGUMENTS
119  *   func -
120  *   line -
121  *   ptr  -
122  *
123  * DESCRIPTION
124  *   -
125  *
126  * RETURN VALUE
127  *   This function does not return a value.
128  */
ot_mem_free(FLT_OT_DBG_ARGS (const char * func,int line,)void * ptr)129 static void ot_mem_free(FLT_OT_DBG_ARGS(const char *func, int line, ) void *ptr)
130 {
131 	flt_ot_pool_free(pool_head_ot_span_context, &ptr);
132 }
133 
134 
135 /***
136  * NAME
137  *   ot_init -
138  *
139  * ARGUMENTS
140  *   tracer -
141  *   plugin -
142  *   err    -
143  *
144  * DESCRIPTION
145  *   -
146  *
147  * RETURN VALUE
148  *   -
149  */
ot_init(struct otc_tracer ** tracer,const char * plugin,char ** err)150 int ot_init(struct otc_tracer **tracer, const char *plugin, char **err)
151 {
152 	char cwd[PATH_MAX], path[PATH_MAX], errbuf[BUFSIZ] = "";
153 	int  rc, retval = -1;
154 
155 	FLT_OT_FUNC("%p:%p, \"%s\", %p:%p", FLT_OT_DPTR_ARGS(tracer), plugin, FLT_OT_DPTR_ARGS(err));
156 
157 	flt_ot_pools_info();
158 #ifdef USE_POOL_OT_SPAN_CONTEXT
159 	FLT_OT_DBG(2, "sizeof_pool(ot_span_context) = %u", pool_head_ot_span_context->size);
160 #endif
161 
162 	if (getcwd(cwd, sizeof(cwd)) == NULL) {
163 		FLT_OT_ERR("failed to get current working directory");
164 
165 		FLT_OT_RETURN(retval);
166 	}
167 	rc = snprintf(path, sizeof(path), "%s/%s", cwd, plugin);
168 	if ((rc == -1) || (rc >= sizeof(path))) {
169 		FLT_OT_ERR("failed to construct the OpenTracing plugin path");
170 
171 		FLT_OT_RETURN(retval);
172 	}
173 
174 	*tracer = otc_tracer_load(path, errbuf, sizeof(errbuf));
175 	if (*tracer == NULL) {
176 		FLT_OT_ERR("%s", (*errbuf == '\0') ? "failed to initialize tracing library" : errbuf);
177 	} else {
178 		otc_ext_init(ot_mem_malloc, ot_mem_free);
179 
180 		retval = 0;
181 	}
182 
183 	FLT_OT_RETURN(retval);
184 }
185 
186 
187 /***
188  * NAME
189  *   ot_start -
190  *
191  * ARGUMENTS
192  *   tracer -
193  *   cfgbuf -
194  *   err    -
195  *
196  * DESCRIPTION
197  *   -
198  *
199  * RETURN VALUE
200  *   This function does not return a value.
201  */
ot_start(struct otc_tracer * tracer,const char * cfgbuf,char ** err)202 int ot_start(struct otc_tracer *tracer, const char *cfgbuf, char **err)
203 {
204 	char errbuf[BUFSIZ] = "";
205 	int  retval = -1;
206 
207 	FLT_OT_FUNC("%p, %p, %p:%p", tracer, cfgbuf, FLT_OT_DPTR_ARGS(err));
208 
209 	if (cfgbuf == NULL)
210 		FLT_OT_RETURN(retval);
211 
212 	retval = otc_tracer_start(NULL, cfgbuf, errbuf, sizeof(errbuf));
213 	if (retval == -1)
214 		FLT_OT_ERR("%s", (*errbuf == '\0') ? "failed to start tracer" : errbuf);
215 
216 	FLT_OT_RETURN(retval);
217 }
218 
219 
220 /***
221  * NAME
222  *   ot_close -
223  *
224  * ARGUMENTS
225  *   tracer -
226  *
227  * DESCRIPTION
228  *   -
229  *
230  * RETURN VALUE
231  *   This function does not return a value.
232  */
ot_close(struct otc_tracer ** tracer)233 void ot_close(struct otc_tracer **tracer)
234 {
235 	FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(tracer));
236 
237 	if ((tracer == NULL) || (*tracer == NULL))
238 		FLT_OT_RETURN();
239 
240 	(*tracer)->close(*tracer);
241 
242 	*tracer = NULL;
243 
244 	FLT_OT_RETURN();
245 }
246 
247 
248 /***
249  * NAME
250  *   ot_span_init -
251  *
252  * ARGUMENTS
253  *   tracer         -
254  *   operation_name -
255  *   ts_steady      -
256  *   ts_system      -
257  *   ref_type       -
258  *   ref_ctx_idx    -
259  *   ref_span       -
260  *   tags           -
261  *   num_tags       -
262  *   err            -
263  *
264  * DESCRIPTION
265  *   -
266  *
267  * RETURN VALUE
268  *   -
269  */
ot_span_init(struct otc_tracer * tracer,const char * operation_name,const struct timespec * ts_steady,const struct timespec * ts_system,int ref_type,int ref_ctx_idx,const struct otc_span * ref_span,const struct otc_tag * tags,int num_tags,char ** err)270 struct otc_span *ot_span_init(struct otc_tracer *tracer, const char *operation_name, const struct timespec *ts_steady, const struct timespec *ts_system, int ref_type, int ref_ctx_idx, const struct otc_span *ref_span, const struct otc_tag *tags, int num_tags, char **err)
271 {
272 	struct otc_start_span_options  options;
273 	struct otc_span_context        context = { .idx = ref_ctx_idx, .span = ref_span };
274 	struct otc_span_reference      references = { ref_type, &context };
275 	struct otc_span               *retptr = NULL;
276 
277 	FLT_OT_FUNC("%p, \"%s\", %p, %p, %d, %d, %p, %p, %d, %p:%p", tracer, operation_name, ts_steady, ts_system, ref_type, ref_ctx_idx, ref_span, tags, num_tags, FLT_OT_DPTR_ARGS(err));
278 
279 	if (operation_name == NULL)
280 		FLT_OT_RETURN(retptr);
281 	else if (tracer == NULL)
282 		FLT_OT_RETURN(retptr);
283 
284 	(void)memset(&options, 0, sizeof(options));
285 
286 	if (ts_steady != NULL)
287 		(void)memcpy(&(options.start_time_steady.value), ts_steady, sizeof(options.start_time_steady.value));
288 
289 	if (ts_system != NULL)
290 		(void)memcpy(&(options.start_time_system.value), ts_system, sizeof(options.start_time_system.value));
291 
292 	if (FLT_OT_IN_RANGE(ref_type, otc_span_reference_child_of, otc_span_reference_follows_from)) {
293 		options.references     = &references;
294 		options.num_references = 1;
295 	}
296 
297 	options.tags     = tags;
298 	options.num_tags = num_tags;
299 
300 	retptr = tracer->start_span_with_options(tracer, operation_name, &options);
301 	if (retptr == NULL)
302 		FLT_OT_ERR("failed to init new span");
303 	else
304 		FLT_OT_DBG(2, "span %p:%zd initialized", retptr, retptr->idx);
305 
306 	FLT_OT_RETURN(retptr);
307 }
308 
309 
310 /***
311  * NAME
312  *   ot_span_init_va -
313  *
314  * ARGUMENTS
315  *   tracer         -
316  *   operation_name -
317  *   ts_steady      -
318  *   ts_system      -
319  *   ref_type       -
320  *   ref_ctx_idx    -
321  *   ref_span       -
322  *   err            -
323  *   tag_key        -
324  *   tag_value      -
325  *
326  * DESCRIPTION
327  *   -
328  *
329  * RETURN VALUE
330  *   -
331  */
ot_span_init_va(struct otc_tracer * tracer,const char * operation_name,const struct timespec * ts_steady,const struct timespec * ts_system,int ref_type,int ref_ctx_idx,const struct otc_span * ref_span,char ** err,const char * tag_key,const char * tag_value,...)332 struct otc_span *ot_span_init_va(struct otc_tracer *tracer, const char *operation_name, const struct timespec *ts_steady, const struct timespec *ts_system, int ref_type, int ref_ctx_idx, const struct otc_span *ref_span, char **err, const char *tag_key, const char *tag_value, ...)
333 {
334 	struct otc_tag   tags[FLT_OT_MAXTAGS];
335 	int              num_tags = 0;
336 	struct otc_span *retptr;
337 
338 	FLT_OT_FUNC("%p, \"%s\", %p, %p, %d, %d, %p, %p:%p, \"%s\", \"%s\", ...", tracer, operation_name, ts_steady, ts_system, ref_type, ref_ctx_idx, ref_span, FLT_OT_DPTR_ARGS(err), tag_key, tag_value);
339 
340 	if (tag_key != NULL) {
341 		va_list ap;
342 
343 		va_start(ap, tag_value);
344 		for (num_tags = 0; (num_tags < FLT_OT_TABLESIZE(tags)) && (tag_key != NULL) && (tag_value != NULL); num_tags++) {
345 			tags[num_tags].key = (char *)tag_key;
346 			FLT_OT_VSET(&(tags[num_tags].value), string, tag_value);
347 
348 			tag_key = va_arg(ap, typeof(tag_key));
349 			if (tag_key != NULL)
350 				tag_value = va_arg(ap, typeof(tag_value));
351 		}
352 		va_end(ap);
353 	}
354 
355 	retptr = ot_span_init(tracer, operation_name, ts_steady, ts_system, ref_type, ref_ctx_idx, ref_span, tags, num_tags, err);
356 
357 	FLT_OT_RETURN(retptr);
358 }
359 
360 
361 /***
362  * NAME
363  *   ot_span_tag -
364  *
365  * ARGUMENTS
366  *   span     -
367  *   tags     -
368  *   num_tags -
369  *
370  * DESCRIPTION
371  *   -
372  *
373  * RETURN VALUE
374  *   -
375  */
ot_span_tag(struct otc_span * span,const struct otc_tag * tags,int num_tags)376 int ot_span_tag(struct otc_span *span, const struct otc_tag *tags, int num_tags)
377 {
378 	int retval = -1;
379 
380 	FLT_OT_FUNC("%p, %p, %d", span, tags, num_tags);
381 
382 	if ((span == NULL) || (tags == NULL))
383 		FLT_OT_RETURN(retval);
384 
385 	for (retval = 0; retval < num_tags; retval++)
386 		span->set_tag(span, tags[retval].key, &(tags[retval].value));
387 
388 	FLT_OT_RETURN(retval);
389 }
390 
391 
392 /***
393  * NAME
394  *   ot_span_tag_va -
395  *
396  * ARGUMENTS
397  *   span  -
398  *   key   -
399  *   type  -
400  *   value -
401  *
402  * DESCRIPTION
403  *   -
404  *
405  * RETURN VALUE
406  *   -
407  */
ot_span_tag_va(struct otc_span * span,const char * key,int type,...)408 int ot_span_tag_va(struct otc_span *span, const char *key, int type, ...)
409 {
410 	va_list          ap;
411 	struct otc_value ot_value;
412 	int              retval = -1;
413 
414 	FLT_OT_FUNC("%p, \"%s\", %d, ...", span, key, type);
415 
416 	if ((span == NULL) || (key == NULL))
417 		FLT_OT_RETURN(retval);
418 
419 	va_start(ap, type);
420 	for (retval = 0; (key != NULL) && FLT_OT_IN_RANGE(type, otc_value_bool, otc_value_null); retval++) {
421 		ot_value.type = type;
422 		if (type == otc_value_bool)
423 			ot_value.value.bool_value = va_arg(ap, typeof(ot_value.value.bool_value));
424 		else if (type == otc_value_double)
425 			ot_value.value.double_value = va_arg(ap, typeof(ot_value.value.double_value));
426 		else if (type == otc_value_int64)
427 			ot_value.value.int64_value = va_arg(ap, typeof(ot_value.value.int64_value));
428 		else if (type == otc_value_uint64)
429 			ot_value.value.uint64_value = va_arg(ap, typeof(ot_value.value.uint64_value));
430 		else if (type == otc_value_string)
431 			ot_value.value.string_value = va_arg(ap, typeof(ot_value.value.string_value));
432 		else if (type == otc_value_null)
433 			ot_value.value.string_value = va_arg(ap, typeof(ot_value.value.string_value));
434 		span->set_tag(span, key, &ot_value);
435 
436 		key = va_arg(ap, typeof(key));
437 		if (key != NULL)
438 			type = va_arg(ap, typeof(type));
439 	}
440 	va_end(ap);
441 
442 	FLT_OT_RETURN(retval);
443 }
444 
445 
446 /***
447  * NAME
448  *   ot_span_log -
449  *
450  * ARGUMENTS
451  *   span       -
452  *   log_fields -
453  *   num_fields -
454  *
455  * DESCRIPTION
456  *   -
457  *
458  * RETURN VALUE
459  *   -
460  */
ot_span_log(struct otc_span * span,const struct otc_log_field * log_fields,int num_fields)461 int ot_span_log(struct otc_span *span, const struct otc_log_field *log_fields, int num_fields)
462 {
463 	int retval = -1;
464 
465 	FLT_OT_FUNC("%p, %p, %d", span, log_fields, num_fields);
466 
467 	if ((span == NULL) || (log_fields == NULL))
468 		FLT_OT_RETURN(retval);
469 
470 	retval = MIN(OTC_MAXLOGFIELDS, num_fields);
471 
472 	span->log_fields(span, log_fields, retval);
473 
474 	FLT_OT_RETURN(retval);
475 }
476 
477 
478 /***
479  * NAME
480  *   ot_span_log_va -
481  *
482  * ARGUMENTS
483  *   span  -
484  *   key   -
485  *   value -
486  *
487  * DESCRIPTION
488  *   -
489  *
490  * RETURN VALUE
491  *   -
492  */
ot_span_log_va(struct otc_span * span,const char * key,const char * value,...)493 int ot_span_log_va(struct otc_span *span, const char *key, const char *value, ...)
494 {
495 	va_list              ap;
496 	struct otc_log_field log_field[OTC_MAXLOGFIELDS];
497 	int                  retval = -1;
498 
499 	FLT_OT_FUNC("%p, \"%s\", \"%s\", ...", span, key, value);
500 
501 	if ((span == NULL) || (key == NULL) || (value == NULL))
502 		FLT_OT_RETURN(retval);
503 
504 	va_start(ap, value);
505 	for (retval = 0; (retval < FLT_OT_TABLESIZE(log_field)) && (key != NULL); retval++) {
506 		log_field[retval].key                      = key;
507 		log_field[retval].value.type               = otc_value_string;
508 		log_field[retval].value.value.string_value = value;
509 
510 		key = va_arg(ap, typeof(key));
511 		if (key != NULL)
512 			value = va_arg(ap, typeof(value));
513 	}
514 	va_end(ap);
515 
516 	span->log_fields(span, log_field, retval);
517 
518 	FLT_OT_RETURN(retval);
519 }
520 
521 
522 /***
523  * NAME
524  *   ot_span_log_fmt -
525  *
526  * ARGUMENTS
527  *   span   -
528  *   key    -
529  *   format -
530  *
531  * DESCRIPTION
532  *   -
533  *
534  * RETURN VALUE
535  *   -
536  */
ot_span_log_fmt(struct otc_span * span,const char * key,const char * format,...)537 int ot_span_log_fmt(struct otc_span *span, const char *key, const char *format, ...)
538 {
539 	va_list ap;
540 	char    value[BUFSIZ];
541 	int     n;
542 
543 	FLT_OT_FUNC("%p, \"%s\", \"%s\", ...", span, key, format);
544 
545 	if ((span == NULL) || (key == NULL) || (format == NULL))
546 		FLT_OT_RETURN(-1);
547 
548 	va_start(ap, format);
549 	n = vsnprintf(value, sizeof(value), format, ap);
550 	if (!FLT_OT_IN_RANGE(n, 0, sizeof(value) - 1)) {
551 		FLT_OT_DBG(2, "WARNING: log buffer too small (%d > %zu)", n, sizeof(value));
552 
553 		FLT_OT_STR_ELLIPSIS(value, sizeof(value));
554 	}
555 	va_end(ap);
556 
557 	FLT_OT_RETURN(ot_span_log_va(span, key, value, NULL));
558 }
559 
560 
561 /***
562  * NAME
563  *   ot_span_set_baggage -
564  *
565  * ARGUMENTS
566  *   span    -
567  *   baggage -
568  *
569  * DESCRIPTION
570  *   -
571  *
572  * RETURN VALUE
573  *   -
574  */
ot_span_set_baggage(struct otc_span * span,const struct otc_text_map * baggage)575 int ot_span_set_baggage(struct otc_span *span, const struct otc_text_map *baggage)
576 {
577 	size_t i;
578 	int    retval = -1;
579 
580 	FLT_OT_FUNC("%p, %p", span, baggage);
581 
582 	if ((span == NULL) || (baggage == NULL))
583 		FLT_OT_RETURN(retval);
584 
585 	if ((baggage->key == NULL) || (baggage->value == NULL))
586 		FLT_OT_RETURN(retval);
587 
588 	for (retval = i = 0; i < baggage->count; i++) {
589 		FLT_OT_DBG(3, "set baggage: \"%s\" -> \"%s\"", baggage->key[i], baggage->value[i]);
590 
591 		if ((baggage->key[i] != NULL) && (baggage->value[i] != NULL)) {
592 			span->set_baggage_item(span, baggage->key[i], baggage->value[i]);
593 
594 			retval++;
595 		}
596 	}
597 
598 	FLT_OT_RETURN(retval);
599 }
600 
601 
602 /***
603  * NAME
604  *   ot_span_set_baggage_va -
605  *
606  * ARGUMENTS
607  *   span  -
608  *   key   -
609  *   value -
610  *
611  * DESCRIPTION
612  *   -
613  *
614  * RETURN VALUE
615  *   -
616  */
ot_span_set_baggage_va(struct otc_span * span,const char * key,const char * value,...)617 int ot_span_set_baggage_va(struct otc_span *span, const char *key, const char *value, ...)
618 {
619 	va_list ap;
620 	int     retval = -1;
621 
622 	FLT_OT_FUNC("%p, \"%s\", \"%s\", ...", span, key, value);
623 
624 	if ((span == NULL) || (key == NULL) || (value == NULL))
625 		FLT_OT_RETURN(retval);
626 
627 	va_start(ap, value);
628 	for (retval = 0; (key != NULL); retval++) {
629 		FLT_OT_DBG(3, "set baggage: \"%s\" -> \"%s\"", key, value);
630 
631 		span->set_baggage_item(span, key, value);
632 
633 		key = va_arg(ap, typeof(key));
634 		if (key != NULL)
635 			value = va_arg(ap, typeof(value));
636 	}
637 	va_end(ap);
638 
639 	FLT_OT_RETURN(retval);
640 }
641 
642 
643 /***
644  * NAME
645  *   ot_span_baggage_va -
646  *
647  * ARGUMENTS
648  *   span -
649  *   key  -
650  *
651  * DESCRIPTION
652  *   -
653  *
654  * RETURN VALUE
655  *   -
656  */
ot_span_baggage_va(const struct otc_span * span,const char * key,...)657 struct otc_text_map *ot_span_baggage_va(const struct otc_span *span, const char *key, ...)
658 {
659 	va_list              ap;
660 	struct otc_text_map *retptr = NULL;
661 	int                  i, n;
662 
663 	FLT_OT_FUNC("%p, \"%s\", ...", span, key);
664 
665 	if ((span == NULL) || (key == NULL))
666 		FLT_OT_RETURN(retptr);
667 
668 	va_start(ap, key);
669 	for (n = 1; va_arg(ap, typeof(key)) != NULL; n++);
670 	va_end(ap);
671 
672 	retptr = otc_text_map_new(NULL, n);
673 	if (retptr == NULL)
674 		FLT_OT_RETURN(retptr);
675 
676 	va_start(ap, key);
677 	for (i = 0; (i < n) && (key != NULL); i++) {
678 		char *value = (char *)span->baggage_item(span, key);
679 
680 		if (value != NULL) {
681 			(void)otc_text_map_add(retptr, key, 0, value, 0, OTC_TEXT_MAP_DUP_KEY | OTC_TEXT_MAP_DUP_VALUE);
682 
683 			FLT_OT_DBG(3, "get baggage[%d]: \"%s\" -> \"%s\"", i, retptr->key[i], retptr->value[i]);
684 		} else {
685 			FLT_OT_DBG(3, "get baggage[%d]: \"%s\" -> invalid key", i, key);
686 		}
687 
688 		key = va_arg(ap, typeof(key));
689 	}
690 	va_end(ap);
691 
692 	FLT_OT_RETURN(retptr);
693 }
694 
695 
696 /***
697  * NAME
698  *   ot_inject_text_map -
699  *
700  * ARGUMENTS
701  *   tracer  -
702  *   span    -
703  *   carrier -
704  *
705  * DESCRIPTION
706  *   -
707  *
708  * RETURN VALUE
709  *   -
710  */
ot_inject_text_map(struct otc_tracer * tracer,const struct otc_span * span,struct otc_text_map_writer * carrier)711 struct otc_span_context *ot_inject_text_map(struct otc_tracer *tracer, const struct otc_span *span, struct otc_text_map_writer *carrier)
712 {
713 	struct otc_span_context *retptr = NULL;
714 	int                      rc;
715 
716 	FLT_OT_FUNC("%p, %p, %p", tracer, span, carrier);
717 
718 	if ((span == NULL) || (carrier == NULL))
719 		FLT_OT_RETURN(retptr);
720 	else if (tracer == NULL)
721 		FLT_OT_RETURN(retptr);
722 
723 	retptr = span->span_context((struct otc_span *)span);
724 	if (retptr == NULL)
725 		FLT_OT_RETURN(retptr);
726 
727 	(void)memset(carrier, 0, sizeof(*carrier));
728 
729 	rc = tracer->inject_text_map(tracer, carrier, retptr);
730 	if (rc != otc_propagation_error_code_success) {
731 		FLT_OT_FREE_CLEAR(retptr);
732 	} else {
733 #ifdef DEBUG_OT
734 		FLT_OT_DBG_TEXT_CARRIER(carrier, set);
735 		ot_text_map_show(&(carrier->text_map));
736 		FLT_OT_DBG_SPAN_CONTEXT(retptr);
737 #endif
738 	}
739 
740 	FLT_OT_RETURN(retptr);
741 }
742 
743 
744 /***
745  * NAME
746  *   ot_inject_http_headers -
747  *
748  * ARGUMENTS
749  *   tracer  -
750  *   span    -
751  *   carrier -
752  *   err     -
753  *
754  * DESCRIPTION
755  *   -
756  *
757  * RETURN VALUE
758  *   -
759  */
ot_inject_http_headers(struct otc_tracer * tracer,const struct otc_span * span,struct otc_http_headers_writer * carrier,char ** err)760 struct otc_span_context *ot_inject_http_headers(struct otc_tracer *tracer, const struct otc_span *span, struct otc_http_headers_writer *carrier, char **err)
761 {
762 	struct otc_span_context *retptr = NULL;
763 	int                      rc;
764 
765 	FLT_OT_FUNC("%p, %p, %p, %p:%p", tracer, span, carrier, FLT_OT_DPTR_ARGS(err));
766 
767 	if ((span == NULL) || (carrier == NULL))
768 		FLT_OT_RETURN(retptr);
769 	else if (tracer == NULL)
770 		FLT_OT_RETURN(retptr);
771 
772 	retptr = span->span_context((struct otc_span *)span);
773 	if (retptr == NULL) {
774 		FLT_OT_ERR("failed to create span context");
775 
776 		FLT_OT_RETURN(retptr);
777 	}
778 
779 	(void)memset(carrier, 0, sizeof(*carrier));
780 
781 	rc = tracer->inject_http_headers(tracer, carrier, retptr);
782 	if (rc != otc_propagation_error_code_success) {
783 		FLT_OT_ERR("failed to inject HTTP headers data");
784 
785 		FLT_OT_FREE_CLEAR(retptr);
786 	} else {
787 #ifdef DEBUG_OT
788 		FLT_OT_DBG_TEXT_CARRIER(carrier, set);
789 		ot_text_map_show(&(carrier->text_map));
790 		FLT_OT_DBG_SPAN_CONTEXT(retptr);
791 #endif
792 	}
793 
794 	FLT_OT_RETURN(retptr);
795 }
796 
797 
798 /***
799  * NAME
800  *   ot_inject_binary -
801  *
802  * ARGUMENTS
803  *   tracer  -
804  *   span    -
805  *   carrier -
806  *
807  * DESCRIPTION
808  *   -
809  *
810  * RETURN VALUE
811  *   -
812  */
ot_inject_binary(struct otc_tracer * tracer,const struct otc_span * span,struct otc_custom_carrier_writer * carrier)813 struct otc_span_context *ot_inject_binary(struct otc_tracer *tracer, const struct otc_span *span, struct otc_custom_carrier_writer *carrier)
814 {
815 	struct otc_span_context *retptr = NULL;
816 	int                      rc;
817 
818 	FLT_OT_FUNC("%p, %p, %p", tracer, span, carrier);
819 
820 	if ((span == NULL) || (carrier == NULL))
821 		FLT_OT_RETURN(retptr);
822 	else if (tracer == NULL)
823 		FLT_OT_RETURN(retptr);
824 
825 	retptr = span->span_context((struct otc_span *)span);
826 	if (retptr == NULL)
827 		FLT_OT_RETURN(retptr);
828 
829 	(void)memset(carrier, 0, sizeof(*carrier));
830 
831 	rc = tracer->inject_binary(tracer, carrier, retptr);
832 	if (rc != otc_propagation_error_code_success) {
833 		FLT_OT_FREE_CLEAR(retptr);
834 	} else {
835 #ifdef DEBUG_OT
836 		struct otc_jaeger_trace_context *ctx = carrier->binary_data.data;
837 
838 		FLT_OT_DBG_CUSTOM_CARRIER(carrier, inject);
839 		FLT_OT_DBG(3, "trace context: %016" PRIx64 "%016" PRIx64 ":%016" PRIx64 ":%016" PRIx64 ":%02hhx <%s> <%s>",
840 		           ctx->trace_id[0], ctx->trace_id[1], ctx->span_id, ctx->parent_span_id, ctx->flags,
841 		           flt_ot_str_hex(ctx->baggage, carrier->binary_data.size - sizeof(*ctx)),
842 		           flt_ot_str_ctrl(ctx->baggage, carrier->binary_data.size - sizeof(*ctx)));
843 		FLT_OT_DBG_SPAN_CONTEXT(retptr);
844 #endif
845 	}
846 
847 	FLT_OT_RETURN(retptr);
848 }
849 
850 
851 /***
852  * NAME
853  *   ot_extract_text_map -
854  *
855  * ARGUMENTS
856  *   tracer   -
857  *   carrier  -
858  *   text_map -
859  *
860  * DESCRIPTION
861  *   -
862  *
863  * RETURN VALUE
864  *   -
865  */
ot_extract_text_map(struct otc_tracer * tracer,struct otc_text_map_reader * carrier,const struct otc_text_map * text_map)866 struct otc_span_context *ot_extract_text_map(struct otc_tracer *tracer, struct otc_text_map_reader *carrier, const struct otc_text_map *text_map)
867 {
868 	struct otc_span_context *retptr = NULL;
869 	int                      rc;
870 
871 	FLT_OT_FUNC("%p, %p, %p", tracer, carrier, text_map);
872 
873 	if (carrier == NULL)
874 		FLT_OT_RETURN(retptr);
875 	else if (tracer == NULL)
876 		FLT_OT_RETURN(retptr);
877 
878 	if (text_map != NULL) {
879 		(void)memset(carrier, 0, sizeof(*carrier));
880 		(void)memcpy(&(carrier->text_map), text_map, sizeof(carrier->text_map));
881 
882 		FLT_OT_DBG_TEXT_CARRIER(carrier, foreach_key);
883 	}
884 
885 	rc = tracer->extract_text_map(tracer, carrier, &retptr);
886 	if (rc != otc_propagation_error_code_success)
887 		FLT_OT_FREE_CLEAR(retptr);
888 	else if (retptr != NULL)
889 		FLT_OT_DBG_SPAN_CONTEXT(retptr);
890 
891 	FLT_OT_RETURN(retptr);
892 }
893 
894 
895 /***
896  * NAME
897  *   ot_extract_http_headers -
898  *
899  * ARGUMENTS
900  *   tracer   -
901  *   carrier  -
902  *   text_map -
903  *   err      -
904  *
905  * DESCRIPTION
906  *   -
907  *
908  * RETURN VALUE
909  *   -
910  */
ot_extract_http_headers(struct otc_tracer * tracer,struct otc_http_headers_reader * carrier,const struct otc_text_map * text_map,char ** err)911 struct otc_span_context *ot_extract_http_headers(struct otc_tracer *tracer, struct otc_http_headers_reader *carrier, const struct otc_text_map *text_map, char **err)
912 {
913 	struct otc_span_context *retptr = NULL;
914 	int                      rc;
915 
916 	FLT_OT_FUNC("%p, %p, %p, %p:%p", tracer, carrier, text_map, FLT_OT_DPTR_ARGS(err));
917 
918 	if (carrier == NULL)
919 		FLT_OT_RETURN(retptr);
920 	else if (tracer == NULL)
921 		FLT_OT_RETURN(retptr);
922 
923 	if (text_map != NULL) {
924 		(void)memset(carrier, 0, sizeof(*carrier));
925 		(void)memcpy(&(carrier->text_map), text_map, sizeof(carrier->text_map));
926 
927 		FLT_OT_DBG_TEXT_CARRIER(carrier, foreach_key);
928 	}
929 
930 	rc = tracer->extract_http_headers(tracer, carrier, &retptr);
931 	if (rc != otc_propagation_error_code_success) {
932 		FLT_OT_ERR("failed to extract HTTP headers data");
933 
934 		FLT_OT_FREE_CLEAR(retptr);
935 	}
936 	else if (retptr != NULL)
937 		FLT_OT_DBG_SPAN_CONTEXT(retptr);
938 
939 	FLT_OT_RETURN(retptr);
940 }
941 
942 
943 /***
944  * NAME
945  *   ot_extract_binary -
946  *
947  * ARGUMENTS
948  *   tracer      -
949  *   carrier     -
950  *   binary_data -
951  *
952  * DESCRIPTION
953  *   -
954  *
955  * RETURN VALUE
956  *   -
957  */
ot_extract_binary(struct otc_tracer * tracer,struct otc_custom_carrier_reader * carrier,const struct otc_binary_data * binary_data)958 struct otc_span_context *ot_extract_binary(struct otc_tracer *tracer, struct otc_custom_carrier_reader *carrier, const struct otc_binary_data *binary_data)
959 {
960 	struct otc_span_context *retptr = NULL;
961 	int                      rc;
962 
963 	FLT_OT_FUNC("%p, %p, %p", tracer, carrier, binary_data);
964 
965 	if (carrier == NULL)
966 		FLT_OT_RETURN(retptr);
967 	else if (tracer == NULL)
968 		FLT_OT_RETURN(retptr);
969 
970 	if ((FLT_OT_DEREF(binary_data, data, NULL) != NULL) && (binary_data->size > 0)) {
971 		(void)memset(carrier, 0, sizeof(*carrier));
972 		(void)memcpy(&(carrier->binary_data), binary_data, sizeof(carrier->binary_data));
973 
974 		FLT_OT_DBG_CUSTOM_CARRIER(carrier, extract);
975 	}
976 
977 	rc = tracer->extract_binary(tracer, carrier, &retptr);
978 	if (rc != otc_propagation_error_code_success)
979 		FLT_OT_FREE_CLEAR(retptr);
980 	else if (retptr != NULL)
981 		FLT_OT_DBG_SPAN_CONTEXT(retptr);
982 
983 	FLT_OT_RETURN(retptr);
984 }
985 
986 
987 /***
988  * NAME
989  *   ot_span_finish -
990  *
991  * ARGUMENTS
992  *   span      -
993  *   ts_finish -
994  *   log_ts    -
995  *   log_key   -
996  *   log_value -
997  *
998  * DESCRIPTION
999  *   -
1000  *
1001  * RETURN VALUE
1002  *   This function does not return a value.
1003  */
ot_span_finish(struct otc_span ** span,const struct timespec * ts_finish,const struct timespec * log_ts,const char * log_key,const char * log_value,...)1004 void ot_span_finish(struct otc_span **span, const struct timespec *ts_finish, const struct timespec *log_ts, const char *log_key, const char *log_value, ...)
1005 {
1006 	struct otc_finish_span_options options;
1007 	struct otc_log_field           log_field[OTC_MAXLOGFIELDS];
1008 	struct otc_log_record          log_records = { .fields = log_field, .num_fields = 0 };
1009 #ifdef DEBUG_OT
1010 	typeof((*span)->idx)           idx = FLT_OT_DDEREF(span, idx, 0);
1011 #endif
1012 
1013 	FLT_OT_FUNC("%p:%p, %p, %p, \"%s\", \"%s\", ...", FLT_OT_DPTR_ARGS(span), ts_finish, log_ts, log_key, log_value);
1014 
1015 	if ((span == NULL) || (*span == NULL))
1016 		FLT_OT_RETURN();
1017 
1018 	(void)memset(&options, 0, sizeof(options));
1019 
1020 	if (ts_finish != NULL)
1021 		(void)memcpy(&(options.finish_time.value), ts_finish, sizeof(options.finish_time.value));
1022 
1023 	if (log_key != NULL) {
1024 		va_list ap;
1025 		int     i;
1026 
1027 		if (log_ts != NULL)
1028 			(void)memcpy(&(log_records.timestamp.value), log_ts, sizeof(log_records.timestamp.value));
1029 
1030 		va_start(ap, log_value);
1031 		for (i = 0; (i < FLT_OT_TABLESIZE(log_field)) && (log_key != NULL); i++) {
1032 			log_field[i].key                      = log_key;
1033 			log_field[i].value.type               = otc_value_string;
1034 			log_field[i].value.value.string_value = log_value;
1035 
1036 			log_key = va_arg(ap, typeof(log_key));
1037 			if (log_key != NULL)
1038 				log_value = va_arg(ap, typeof(log_value));
1039 		}
1040 		va_end(ap);
1041 
1042 		log_records.num_fields  = i;
1043 		options.log_records     = &log_records;
1044 		options.num_log_records = 1;
1045 	}
1046 
1047 	/*
1048 	 * Caution: memory allocated for the span is released
1049 	 *          in the function finish_with_options().
1050 	 */
1051 	(*span)->finish_with_options(*span, &options);
1052 
1053 	FLT_OT_DBG(2, "span %p:%zu finished", *span, idx);
1054 
1055 	*span = NULL;
1056 
1057 	FLT_OT_RETURN();
1058 }
1059 
1060 /*
1061  * Local variables:
1062  *  c-indent-level: 8
1063  *  c-basic-offset: 8
1064  * End:
1065  *
1066  * vi: noexpandtab shiftwidth=8 tabstop=8
1067  */
1068