• Stars
    star
    507
  • Rank 87,068 (Top 2 %)
  • Language
    PHP
  • License
    Apache License 2.0
  • Created over 7 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

OpenTracing API for PHP

OpenTracing API for PHP

Build OpenTracing Badge Total Downloads Minimum PHP Version License Join the chat at https://gitter.im/opentracing/opentracing-php

PHP library for the OpenTracing's API.

Required Reading

In order to understand the library, one must first be familiar with the OpenTracing project and specification more specifically.

Installation

OpenTracing-PHP can be installed via Composer:

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:

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.

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.

$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:

// At dispatcher level
$scope = $tracer->startActiveSpan('request');
...
$scope->close();
// At controller level
$scope = $tracer->startActiveSpan('controller');
...
$scope->close();
// 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

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

$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

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:

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.

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.
$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 coding standard and the PSR-4 autoloading standard.

License

All the open source contributions are under the terms of the Apache-2.0 License.

More Repositories

1

opentracing-go

OpenTracing API for Go. ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Go
3,493
star
2

opentracing-java

OpenTracing API for Java. ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Java
1,684
star
3

specification

A place to document (and discuss) the OpenTracing specification. ๐Ÿ›‘ This project is DEPRECATED! https://github.com/opentracing/specification/issues/163
1,173
star
4

opentracing-javascript

OpenTracing API for Javascript (both Node and browser). ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
TypeScript
1,091
star
5

opentracing-python

OpenTracing API for Python. ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Python
755
star
6

opentracing-csharp

OpenTracing API for C# (.NET). ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
C#
517
star
7

opentracing-cpp

OpenTracing API for C++. ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
C++
320
star
8

opentracing-ruby

OpenTracing API for Ruby
Ruby
173
star
9

opentracing.io

OpenTracing website
SCSS
116
star
10

basictracer-go

Basic implementation of the OpenTracing API for Go. ๐Ÿ›‘ This library is DEPRECATED!
Go
81
star
11

opentracing-rust

OpenTracing API for Rust
Rust
76
star
12

opentracing-c

ANSI C API for OpenTracing
C
33
star
13

opentracing-lua

OpenTracing API for Lua
Lua
29
star
14

opentracing-objc

OpenTracing API for Objective-C. ๐Ÿ›‘ This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Objective-C
28
star
15

basictracer-python

The Python implementation of the "BasicTracer" reference implementation. ๐Ÿ›‘ This library is DEPRECATED!
Python
26
star
16

opentracing-swift

This is a prototype OpenTracing API for the Swift language. This is intended to explore and validate decisions about implementing the OpenTracing API in Swift.
Swift
17
star
17

lua-bridge-tracer

Provides an implementation of the Lua OpenTracing API on top of the C++ API
C++
14
star
18

basictracer-csharp

Reference implementation of OpenTracing API in C#
12
star
19

documentation

Please see opentracing.io repo instead
7
star
20

basictracer-javascript

JavaScript
7
star
21

contrib

A place (or, really, a pointer) for community contributions to OpenTracing
5
star
22

opentracing-java-v030

Backwards compatibility layer for Java v0.30
Java
3
star
23

c-bridge-tracer

Experimental C binding for C++ tracers
1
star