| 264 | #define MAX_BUF_SIZE 2048 |
| 265 | |
| 266 | static void trace_emit(struct span *s) |
| 267 | { |
| 268 | char span_id[hex_str_size(sizeof(s->id))]; |
| 269 | char buffer[MAX_BUF_SIZE + 1]; |
| 270 | size_t len; |
| 271 | |
| 272 | snprintf(span_id, sizeof(span_id), "%016" PRIx64, s->id); |
| 273 | len = snprintf(buffer, MAX_BUF_SIZE, |
| 274 | "[{\"id\":\"%s\",\"name\":\"%s\"," |
| 275 | "\"timestamp\":%" PRIu64 ",\"duration\":%" PRIu64 "," |
| 276 | "\"localEndpoint\":{\"serviceName\":\"%s\"},", |
| 277 | span_id, s->name, s->start_time, |
| 278 | s->end_time - s->start_time, trace_service_name); |
| 279 | |
| 280 | if (s->parent != NULL) { |
| 281 | len += |
| 282 | snprintf(buffer + len, MAX_BUF_SIZE - len, |
| 283 | "\"parentId\":\"%016" PRIx64 "\",", s->parent->id); |
| 284 | if (len > MAX_BUF_SIZE) |
| 285 | len = MAX_BUF_SIZE; |
| 286 | } |
| 287 | |
| 288 | len += snprintf(buffer + len, MAX_BUF_SIZE - len, "\"tags\":{"); |
| 289 | if (len > MAX_BUF_SIZE) |
| 290 | len = MAX_BUF_SIZE; |
| 291 | for (size_t i = 0; i < SPAN_MAX_TAGS; i++) { |
| 292 | if (!s->tags[i].name) |
| 293 | continue; |
| 294 | len += snprintf(buffer + len, MAX_BUF_SIZE - len, |
| 295 | "%s\"%s\":\"%.*s\"", i == 0 ? "" : ", ", |
| 296 | s->tags[i].name, s->tags[i].valuelen, |
| 297 | s->tags[i].valuestr); |
| 298 | if (len > MAX_BUF_SIZE) |
| 299 | len = MAX_BUF_SIZE; |
| 300 | } |
| 301 | |
| 302 | len += snprintf(buffer + len, MAX_BUF_SIZE - len, |
| 303 | "},\"traceId\":\"%016" PRIx64 "%016" PRIx64 "\"}]", |
| 304 | s->trace_id_hi, s->trace_id_lo); |
| 305 | if (len > MAX_BUF_SIZE) |
| 306 | len = MAX_BUF_SIZE; |
| 307 | buffer[len] = '\0'; |
| 308 | /* FIXME: span_id here is in hex, could be u64? */ |
| 309 | DTRACE_PROBE2(lightningd, span_emit, span_id, buffer); |
| 310 | if (trace_to_file) { |
| 311 | fprintf(trace_to_file, "span_emit %s %s\n", span_id, buffer); |
| 312 | fflush(trace_to_file); |
| 313 | } |
| 314 | if (trace_socket_fd >= 0) { |
| 315 | /* Fire-and-forget: silently ignore all sendto errors. */ |
| 316 | sendto(trace_socket_fd, buffer, len, MSG_DONTWAIT, |
| 317 | (struct sockaddr *)&trace_socket_addr, |
| 318 | trace_socket_addrlen); |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | /** |
| 323 | * Release the span back into the pool of available spans. |
no test coverage detected