summaryrefslogtreecommitdiff
path: root/vendor/opentracing/opentracing/README.md
blob: ce03bc95186250f7b9655e196b771b03e9178c42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# OpenTracing API for PHP

[![Build](https://github.com/opentracing/opentracing-php/actions/workflows/ci.yml/badge.svg)](https://github.com/opentracing/opentracing-php/actions/workflows/ci.yml)
[![OpenTracing Badge](https://img.shields.io/badge/OpenTracing-enabled-blue.svg)](http://opentracing.io)
[![Total Downloads](https://poser.pugx.org/opentracing/opentracing/downloads)](https://packagist.org/packages/opentracing/opentracing)
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg)](https://php.net/)
[![License](https://img.shields.io/github/license/opentracing/opentracing-php.svg)](https://github.com/opentracing/opentracing-php/blob/master/LICENSE)
[![Join the chat at https://gitter.im/opentracing/opentracing-php](https://badges.gitter.im/opentracing/opentracing-php.svg)](https://gitter.im/opentracing/opentracing-php?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

PHP library for the OpenTracing's API.

## Required Reading

In order to understand the library, one must first be familiar with the
[OpenTracing project](http://opentracing.io) and
[specification](http://opentracing.io/documentation/pages/spec.html) more specifically.

## Installation

OpenTracing-PHP can be installed via Composer:

```bash
composer require opentracing/opentracing
```

## Usage

When consuming this library one really only need to worry about a couple of key
abstractions: the `Tracer::startActiveSpan` and `Tracer::startSpan` method,
the `Span` interface, the `Scope` interface and binding a `Tracer` at bootstrap time. Here are code snippets
demonstrating some important use cases:

### Singleton initialization

The simplest starting point is to set the global tracer. As early as possible, do:

```php
use OpenTracing\GlobalTracer;

GlobalTracer::set(new MyTracerImplementation());
```

### Creating a Span given an existing Request

To start a new `Span`, you can use the `startSpan` method.

```php
use OpenTracing\Formats;
use OpenTracing\GlobalTracer;

...

// extract the span context
$spanContext = GlobalTracer::get()->extract(
    Formats\HTTP_HEADERS,
    getallheaders()
);

function doSomething() {
    ...

    // start a new span called 'my_span' and make it a child of the $spanContext
    $span = GlobalTracer::get()->startSpan('my_span', ['child_of' => $spanContext]);

    ...
    
    // add some logs to the span
    $span->log([
        'event' => 'soft error',
        'type' => 'cache timeout',
        'waiter.millis' => 1500,
    ])

    // finish the the span
    $span->finish();
}
```

### Starting a new trace by creating a "root span"

It's always possible to create a "root" `Span` with no parent or other causal reference.

```php
$span = $tracer->startSpan('my_first_span');
...
$span->finish();
```

### Active Spans and Scope Manager

For most use cases, it is recommended that you use the `Tracer::startActiveSpan` function for
creating new spans.

An example of a linear, two level deep span tree using active spans looks like
this in PHP code:
```php
// At dispatcher level
$scope = $tracer->startActiveSpan('request');
...
$scope->close();
```
```php
// At controller level
$scope = $tracer->startActiveSpan('controller');
...
$scope->close();
```

```php
// At RPC calls level
$scope = $tracer->startActiveSpan('http');
file_get_contents('http://php.net');
$scope->close();
```
 
When using the `Tracer::startActiveSpan` function the underlying tracer uses an
abstraction called scope manager to keep track of the currently active span.

Starting an active span will always use the currently active span as a parent.
If no parent is available, then the newly created span is considered to be the
root span of the trace.

Unless you are using asynchronous code that tracks multiple spans at the same
time, such as when using cURL Multi Exec or MySQLi Polling it is recommended that you 
use `Tracer::startActiveSpan` everywhere in your application.

The currently active span gets automatically finished when you call `$scope->close()`
as you can see in the previous examples.

If you don't want a span to automatically close when `$scope->close()` is called
then you must specify `'finish_span_on_close'=> false,` in the `$options`
argument of `startActiveSpan`.

#### Creating a child span assigning parent manually

```php
$parent = GlobalTracer::get()->startSpan('parent');

$child = GlobalTracer::get()->startSpan('child', [
    'child_of' => $parent
]);

...

$child->finish();

...

$parent->finish();
```

#### Creating a child span using automatic active span management

Every new span will take the active span as parent and it will take its spot.

```php
$parent = GlobalTracer::get()->startActiveSpan('parent');

...

/*
 * Since the parent span has been created by using startActiveSpan we don't need
 * to pass a reference for this child span
 */
$child = GlobalTracer::get()->startActiveSpan('my_second_span');

...

$child->close();

...

$parent->close();
```

### Serializing to the wire

```php
use GuzzleHttp\Client;
use OpenTracing\Formats;

...

$tracer = GlobalTracer::get();

$spanContext = $tracer->extract(
    Formats\HTTP_HEADERS,
    getallheaders()
);

try {
    $span = $tracer->startSpan('my_span', ['child_of' => $spanContext]);

    $client = new Client;

    $headers = [];

    $tracer->inject(
        $span->getContext(),
        Formats\HTTP_HEADERS,
        $headers
    );

    $request = new \GuzzleHttp\Psr7\Request('GET', 'http://myservice', $headers);
    $client->send($request);
    ...

} catch (\Exception $e) {
    ...
}
...
```

### Deserializing from the wire

When using http header for context propagation you can use either the `Request` or the `$_SERVER`
variable:

```php
use OpenTracing\GlobalTracer;
use OpenTracing\Formats;

$tracer = GlobalTracer::get();
$spanContext = $tracer->extract(Formats\HTTP_HEADERS, getallheaders());
$tracer->startSpan('my_span', [
    'child_of' => $spanContext,
]);
```

### Flushing Spans

PHP as a request scoped language has no simple means to pass the collected spans
data to a background process without blocking the main request thread/process.
The OpenTracing API makes no assumptions about this, but for PHP that might
cause problems for Tracer implementations. This is why the PHP API contains a
`flush` method that allows to trigger a span sending out of process.

```php
use OpenTracing\GlobalTracer;

$application->run();

register_shutdown_function(function() {
    /* Flush the tracer to the backend */
    $tracer = GlobalTracer::get();
    $tracer->flush();
});
```

This is optional, tracers can decide to immediately send finished spans to a
backend. The flush call can be implemented as a NO-OP for these tracers.

### Using `StartSpanOptions`

Passing options to the pass can be done using either an array or the
SpanOptions wrapper object. The following keys are valid:

- `start_time` is a float, int or `\DateTime` representing a timestamp with arbitrary precision.
- `child_of` is an object of type `OpenTracing\SpanContext` or `OpenTracing\Span`.
- `references` is an array of `OpenTracing\Reference`.
- `tags` is an array with string keys and scalar values that represent OpenTracing tags.
- `finish_span_on_close` is a boolean that determines whether a span should be finished or not when the
scope is closed.

```php
$span = $tracer->startActiveSpan('my_span', [
    'child_of' => $spanContext,
    'tags' => ['foo' => 'bar'],
    'start_time' => time(),
]);
```

### Propagation Formats

The propagation formats should be implemented consistently across all tracers.
If you want to implement your own format, then don't reuse the existing constants.
Tracers will throw an exception if the requested format is not handled by them.

- `Tracer::FORMAT_TEXT_MAP` should represent the span context as a key value map. There is no
  assumption about the semantics where the context is coming from and sent to.

- `Tracer::FORMAT_HTTP_HEADERS` should represent the span context as HTTP header lines
  in an array list. For two context details "Span-Id" and "Trace-Id", the
  result would be `['Span-Id: abc123', 'Trace-Id: def456']`. This definition can be
  passed directly to `curl` and `file_get_contents`.

- `Tracer::FORMAT_BINARY` makes no assumptions about the data format other than it is
  proprietary and each Tracer can handle it as it wants.

## Mock implementation

OpenTracing PHP comes with a mock implementation, it has three purposes:

1. Helps to iron the API.
2. Works as a reference implementation.
3. Enhances vendor agnostic unit testing as it allows developers to inspect the tracing objects
in order to do assertions about them.

## Coding Style

OpenTracing PHP follows the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
coding standard and the [PSR-4](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md) autoloading standard.

## License

All the open source contributions are under the terms of the [Apache-2.0 License](https://opensource.org/licenses/Apache-2.0).