Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#43] Adds in process context propagation. #45

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 116 additions & 95 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,134 +26,156 @@ composer require opentracing/opentracing
## Usage

When consuming this library one really only need to worry about a couple of key
abstractions: the `Tracer::startSpan` method, the `Span` interface, and binding
a `Tracer` at bootstrap time. Here are code snippets demonstrating some important
use cases:
abstractions: the `Tracer::startActiveSpan` and `Tracer::startSpan` method,
the `Span` 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;
use AnOpenTracingImplementation\MyTracer;

GlobalTracer::set(new MyTracer());
use OpenTracing\GlobalTracer;

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

### Creating a Span given an existing Request

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

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

...
...

$spanContext = GlobalTracer::get()->extract(
Formats\HTTP_HEADERS,
$request->getHeaders()
);
$spanContext = GlobalTracer::get()->extract(
Formats\HTTP_HEADERS,
getallheaders()
);

function doSomething() {
...

function doSomething(SpanContext $spanContext, ...) {
...

$span = GlobalTracer::get()->startSpan('my_span', [
'child_of' => $spanContext,
]);

...

$span->log([
'event' => 'soft error',
'type' => 'cache timeout',
'waiter.millis' => 1500,
])

$span->finish();
}
$span = GlobalTracer::get()->startActiveSpan('my_span', ['child_of' => $spanContext]);

...

$span->log([
'event' => 'soft error',
'type' => 'cache timeout',
'waiter.millis' => 1500,
])

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

### Starting an empty trace by creating a "root span"

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

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

### Creating a (child) Span given an existing (parent) Span
#### Creating a child span assigning parent manually

```php
function xyz(Span $parentSpan, ...) {
...
$span = GlobalTracer::get()->startSpan(
'my_span',
[
'child_of' => $parentSpan,
]
);

$span->finish();
...
}
$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->finish();

...

$parent->finish();
```

### Serializing to the wire

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

...
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;

$tracer = GlobalTracer::get();
$headers = [];

$spanContext = $tracer->extract(
$tracer->inject(
$span->getContext(),
Formats\HTTP_HEADERS,
$request->getHeaders()
$headers
);

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

$client = new GuzzleHttp\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) {
...
}
...
$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:
When using http header for context propagation you can use either the `Request` or the `$_SERVER`
variable:

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

$request = Request::createFromGlobals();
$tracer = GlobalTracer::get();
$spanContext = $tracer->extract(Formats\HTTP_HEADERS, $request->getHeaders());
$tracer->startSpan('my_span', [
'child_of' => $spanContext,
]);
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
Expand All @@ -167,19 +189,18 @@ cause problems for Tracer implementations. This is why the PHP API contains a
```php
use OpenTracing\GlobalTracer;

// Do application work, buffer spans in memory
$application->run();

fastcgi_finish_request();

$tracer = GlobalTracer::get();
$tracer->flush(); // release buffer to backend
register_shutdown_function(function() use ($tracer) {
/* 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 Span Options

Passing options to the pass can be done using either an array or the
Expand All @@ -191,7 +212,7 @@ SpanOptions wrapper object. The following keys are valid:
- `tags` is an array with string keys and scalar values that represent OpenTracing tags.

```php
$span = $tracer->createSpan('my_span', [
$span = $tracer->startActiveSpan('my_span', [
'child_of' => $spanContext,
'tags' => ['foo' => 'bar'],
'start_time' => time(),
Expand All @@ -217,5 +238,5 @@ Tracers will throw an exception if the requested format is not handled by 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)
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.
6 changes: 3 additions & 3 deletions src/OpenTracing/GlobalTracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ final class GlobalTracer
/**
* @var Tracer
*/
private static $instance = null;
private static $instance;

/**
* GlobalTracer::set sets the [singleton] Tracer returned by get().
* Those who use GlobalTracer (rather than directly manage a Tracer instance)
* should call GlobalTracer::set as early as possible in bootstrap, prior to
* start a new span. Prior to calling GlobalTracer::set, any Spans started
* via the `Tracer::startSpan` (etc) globals are noops.
* via the `Tracer::startActiveSpan` (etc) globals are noops.
*
* @param Tracer $tracer
*/
Expand All @@ -33,7 +33,7 @@ public static function set(Tracer $tracer)
public static function get()
{
if (self::$instance === null) {
self::$instance = NoopTracer::create();
self::$instance = Tracer::create();
}

return self::$instance;
Expand Down
26 changes: 26 additions & 0 deletions src/OpenTracing/NoopScopeManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace OpenTracing;

final class NoopScopeManager implements ScopeManager
{
public static function create()
{
return new self();
}

/**
* {@inheritdoc}
*/
public function activate(Span $span, $finishSpanOnClose)
{
}

/**
* {@inheritdoc}
*/
public function getActiveSpan()
{
return NoopSpan::create();
}
}
3 changes: 3 additions & 0 deletions src/OpenTracing/NoopSpan.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public function finish($finishTime = null, array $logRecords = [])
{
}

/**
* {@inheritdoc}
*/
public function overwriteOperationName($newOperationName)
{
}
Expand Down
24 changes: 24 additions & 0 deletions src/OpenTracing/NoopTracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@

final class NoopTracer implements Tracer
{
/**
* {@inheritdoc}
*/
public function getActiveSpan()
{
return NoopSpan::create();
}

/**
* {@inheritdoc}
*/
public function getScopeManager()
{
return new NoopScopeManager();
}

public static function create()
{
return new self();
Expand All @@ -14,6 +30,14 @@ public static function create()
*/
public function startSpan($operationName, $options = [])
{
}

/**
* {@inheritdoc}
*/
public function startActiveSpan($operationName, $finishSpanOnClose = true, $options = [])
{

return NoopSpan::create();
}

Expand Down
Loading