|
1 | | -# Care and Feeding of Your New Tracing Library |
| 1 | +# Datadog C++ Tracer Design |
2 | 2 |
|
3 | | -Congratulations! You are now the proud owner of a distributed tracing library. |
4 | | - |
5 | | -The primary purpose of this guide is to describe salient features of the library's design. |
6 | | -`dd-trace-cpp` differs considerably from its [older |
| 3 | +The primary purpose of this guide is to describe salient features of the Datadog C++ Tracer's |
| 4 | +design. It differs considerably from its [older |
7 | 5 | sibling](https://github.com/DataDog/dd-opentracing-cpp) and |
8 | 6 | [peers](https://github.com/open-telemetry/opentelemetry-cpp). |
9 | 7 |
|
10 | 8 | This guide will also cover operations performed by maintainers of the library, such as scooping the |
11 | 9 | box, applying flea medication, and regular trips to the vet. |
12 | 10 |
|
13 | | -## Design |
| 11 | +## Architecture |
14 | 12 |
|
15 | 13 | ### Span |
16 | 14 |
|
@@ -278,7 +276,55 @@ uses a different implementation, [class AgentHTTPClient : public HTTPClient, |
278 | 276 | ...](https://github.com/envoyproxy/envoy/blob/main/source/extensions/tracers/datadog/agent_http_client.h), |
279 | 277 | which uses Envoy's built-in HTTP facilities. libcurl is not involved at all. |
280 | 278 |
|
281 | | -### EventScheduler |
| 279 | +### Logical Component Relationships |
| 280 | + |
| 281 | +- Vertices are components. |
| 282 | +- Edges are ownership relationships between components. Each edge is labeled by the kind of pointer |
| 283 | + that is used to implement the relationship. |
| 284 | +- Components with a padlock are protected by a mutex. |
| 285 | + |
| 286 | +```mermaid |
| 287 | +--- |
| 288 | +title: Components Relationships |
| 289 | +config: |
| 290 | + layout: elk |
| 291 | +--- |
| 292 | +graph LR; |
| 293 | + Tracer(Tracer) & TraceSegment("TraceSegment 🔒")-- shared -->Collector("Collector 🔒") & SpanSampler("SpanSampler 🔒") & TraceSampler("TraceSampler 🔒") |
| 294 | + TraceSegment-- "`**unique**`" -->SpanData(SpanData) |
| 295 | + Span(Span)-- shared -->TraceSegment |
| 296 | + Span-- "`**raw**`" -->SpanData |
| 297 | +``` |
| 298 | + |
| 299 | +Objects: |
| 300 | + |
| 301 | +- `Span` has a beginning, end, and tags. It is associated with a `TraceSegment`. |
| 302 | +- `TraceSegment` is part of a trace. It makes sampling decisions, detects when it is finished, and |
| 303 | + sends itself to the `Collector`. |
| 304 | +- `Collector` receives trace segments. It provides a callback to deliver sampler modifications, if |
| 305 | + applicable. |
| 306 | +- `Tracer` is responsible for creating trace segments. It contains the instances of, and |
| 307 | + configuration for, the `Collector`, `TraceSampler`, and `SpanSampler`. A tracer is created from a |
| 308 | + `TracerConfig`. |
| 309 | +- `TraceSampler` is used by trace segments to decide when to keep or drop themselves. |
| 310 | +- `SpanSampler` is used by trace segments to decide which spans to keep when the segment is dropped. |
| 311 | +- `TracerConfig` contains all of the information needed to configure the collector, trace sampler, |
| 312 | + and span sampler, as well as defaults for span properties. |
| 313 | + |
| 314 | +Intended usage is: |
| 315 | + |
| 316 | +1. Create a `TracerConfig`. |
| 317 | +2. Use the `TracerConfig` to create a `Tracer`. |
| 318 | +3. Use the `Tracer` to create and/or extract local root `Span`s. |
| 319 | +4. Use `Span` to create children and/or inject context. |
| 320 | +5. Use a `Span`'s `TraceSegment` to perform trace-wide operations. |
| 321 | +6. When all `Span`s in `TraceSegment` are finished, the segment is sent to the |
| 322 | + `Collector`. |
| 323 | + |
| 324 | +Different instances of `Tracer` are independent of each other. If an application wishes to |
| 325 | +reconfigure tracing at runtime, it can create another `Tracer` using the new configuration. |
| 326 | + |
| 327 | +## EventScheduler |
282 | 328 |
|
283 | 329 | As of this writing, `class DatadogAgent` flushes batches of finished trace segments to the Datadog |
284 | 330 | Agent once every two second [by |
@@ -314,7 +360,7 @@ also uses a different implementation, [class EventScheduler : public |
314 | 360 | EventScheduler](https://github.com/envoyproxy/envoy/blob/main/source/extensions/tracers/datadog/event_scheduler.h), |
315 | 361 | which uses Envoy's built-in event dispatch facilities. |
316 | 362 |
|
317 | | -### Configuration |
| 363 | +## Configuration |
318 | 364 |
|
319 | 365 | There's a good [blog post](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) by |
320 | 366 | [Alexis King](https://lexi-lambda.github.io/about.html) where she makes the case for encoding |
@@ -362,7 +408,7 @@ is to prevent eventual intermixing between the "configuration representation" an |
362 | 408 | representation." In part, `finalize_config` already mitigates the problem. Abstaining from storing |
363 | 409 | the finalized config as a data member is a step further. |
364 | 410 |
|
365 | | -### Error Handling |
| 411 | +## Error Handling |
366 | 412 |
|
367 | 413 | Most error scenarios within this library are individually enumerated by `enum Error::Code`, defined |
368 | 414 | in [error.h](../include/datadog/error.h). |
@@ -514,7 +560,7 @@ operator bool` has the opposite meaning as it does in `Expected<T>`. I wanted er |
514 | 560 | be the same in the two cases, and so I specialized `Expected<void>`. `Expected<void>` is implemented |
515 | 561 | in terms of `std::optional<Error>`, but inverts the value of `explicit operator bool`. |
516 | 562 |
|
517 | | -### Logging |
| 563 | +## Logging |
518 | 564 |
|
519 | 565 | Can we write a tracing library that does not do any logging by itself? The previous section |
520 | 566 | describes how errors are reported by the library, and no logging is involved there. Why not leave it |
|
0 commit comments