From 307a5fa9a43b3cb00aba525c05fb8e3b21ae8c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Thu, 15 Jun 2017 23:17:17 +0200 Subject: [PATCH 1/2] Adds activeSpanSource interface and include it as a dependency on tracer. --- README.md | 55 +++++++++++++---------- src/OpenTracing/ActiveSpanSource.php | 40 +++++++++++++++++ src/OpenTracing/GlobalTracer.php | 2 +- src/OpenTracing/NoopActiveSpanSource.php | 24 ++++++++++ src/OpenTracing/NoopSpan.php | 3 ++ src/OpenTracing/NoopTracer.php | 25 +++++++---- src/OpenTracing/Span.php | 4 +- src/OpenTracing/SpanContext.php | 2 +- src/OpenTracing/SpanOptions.php | 6 ++- src/OpenTracing/SpanReference/ChildOf.php | 6 +++ src/OpenTracing/Tracer.php | 48 +++++++++++++++----- 11 files changed, 168 insertions(+), 47 deletions(-) create mode 100644 src/OpenTracing/ActiveSpanSource.php create mode 100644 src/OpenTracing/NoopActiveSpanSource.php diff --git a/README.md b/README.md index 7400a78..f9e1c50 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ In order to understand the library, one must first be familiar with the OpenTracing-PHP can be installed via Composer: -```php +```bash composer require jcchavezs/opentracing-php ``` @@ -38,7 +38,7 @@ The simplest starting point is to set the global tracer. As early as possible, d ### 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 Psr\Http\Message\RequestInterface; @@ -53,7 +53,7 @@ To start a new `Span`, you can use the `StartSpanFromContext` method. function doSomething(SpanContext $spanContext, ...) { ... - $span = GlobalTracer::getGlobalTracer()->startSpan('my_span', ChildOf::withContext($spanContext)); + $span = GlobalTracer::getGlobalTracer()->startManualSpan('my_span', ['child_of' => $spanContext]); ... @@ -69,30 +69,41 @@ To start a new `Span`, you can use the `StartSpanFromContext` method. ### 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 = $tracer->startActiveSpan('my_first_span'); ... $span->finish(); ``` -### Creating a (child) Span given an existing (parent) Span +#### Creating a child span assigning parent manually ```php - use OpenTracing\SpanReference\ChildOf; + use OpenTracing\SpanReference\ChildOf; + + $parent = GlobalTracer::getGlobalTracer()->startManualSpan('parent'); $child = GlobalTracer::getGlobalTracer()->startManualSpan('child', [ + 'child_of' => $parent + ]); + ... + $child->finish(); + ... + $parent->finish(); +``` - function xyz(Span $parentSpan, ...) { - ... - $span = GlobalTracer::getGlobalTracer()->startSpan( - 'my_span', - ChildOf::withContext($span->context()) - ); - - $span->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::getGlobalTracer()->startManualSpan('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::getGlobalTracer()->startActiveSpan('my_second_span'); + ... + $child->finish(); + ... + $parent->finish(); ``` ### Serializing to the wire @@ -112,7 +123,7 @@ reference. ); try { - $span = $tracer->startSpanWithOptions('my_span', ['child_of' => $spanContext]); + $span = $tracer->startManualSpan('my_span', ['child_of' => $spanContext]); $client = new GuzzleHttp\Client; @@ -134,7 +145,7 @@ reference. ### 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 the `Request` for example: ```php use OpenTracing\Carriers\HttpHeaders; @@ -160,19 +171,17 @@ cause problems for Tracer implementations. This is why the PHP API contains a use OpenTracing\GlobalTracer; -// Do application work, buffer spans in memory $application->run(); fastcgi_finish_request(); $tracer = GlobalTracer::getGlobalTracer(); -$tracer->flush(); // release buffer to backend +$tracer->flush(); // sends span's data to the backend ``` 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 diff --git a/src/OpenTracing/ActiveSpanSource.php b/src/OpenTracing/ActiveSpanSource.php new file mode 100644 index 0000000..494524d --- /dev/null +++ b/src/OpenTracing/ActiveSpanSource.php @@ -0,0 +1,40 @@ +deactivate() -> the span is not active but still "running" + * - $span->finish() -> the span is finished and deactivated + * + * @param Span $span + */ + public function deactivate(Span $span); +} diff --git a/src/OpenTracing/GlobalTracer.php b/src/OpenTracing/GlobalTracer.php index 27ca578..37cd96f 100644 --- a/src/OpenTracing/GlobalTracer.php +++ b/src/OpenTracing/GlobalTracer.php @@ -14,7 +14,7 @@ final class GlobalTracer * Those who use GlobalTracer (rather than directly manage a Tracer instance) * should call setGlobalTracer as early as possible in bootstrap, prior to * start a new span. Prior to calling `setGlobalTracer`, any Spans started - * via the `StartSpan` (etc) globals are noops. + * via the `startActiveSpan` (etc) globals are noops. * * @param Tracer $tracer */ diff --git a/src/OpenTracing/NoopActiveSpanSource.php b/src/OpenTracing/NoopActiveSpanSource.php new file mode 100644 index 0000000..f3a9070 --- /dev/null +++ b/src/OpenTracing/NoopActiveSpanSource.php @@ -0,0 +1,24 @@ +getContext()); } elseif ($value instanceof SpanContext) { return ChildOf::fromContext($value); + } elseif ($value instanceof ChildOf) { + return $value; } throw InvalidSpanOption::invalidChildOf($value); @@ -123,7 +125,7 @@ public function getTags() } /** - * @return int|float|\DateTime if returning float or int it should represent + * @return int|float|\DateTimeInterface if returning float or int it should represent * the timestamp (including as many decimal places as you need) */ public function getStartTime() diff --git a/src/OpenTracing/SpanReference/ChildOf.php b/src/OpenTracing/SpanReference/ChildOf.php index 1b0ecfa..b55b118 100644 --- a/src/OpenTracing/SpanReference/ChildOf.php +++ b/src/OpenTracing/SpanReference/ChildOf.php @@ -46,4 +46,10 @@ public function referencedContext() { return $this->spanContext; } + + public function isEqual(SpanReference $spanReference) + { + return ($spanReference instanceof ChildOf) + && $this->spanContext->isEqual($spanReference->referencedContext()); + } } diff --git a/src/OpenTracing/Tracer.php b/src/OpenTracing/Tracer.php index e246a0c..b759f00 100644 --- a/src/OpenTracing/Tracer.php +++ b/src/OpenTracing/Tracer.php @@ -25,28 +25,54 @@ interface Tracer const FORMAT_HTTP_HEADERS = 3; /** + * Starts and returns a new `Span` representing a unit of work. + * + * This method differs from `startManualSpan` because it uses in-process + * context propagation to keep track of the current active `Span` (if + * available). + * + * Starting a root `Span` with no casual references and a child `Span` + * in a different function, is possible without passing the parent + * reference around: + * + * function handleRequest(Request $request, $userId) + * { + * $rootSpan = $this->tracer->startActiveSpan('request.handler'); + * $user = $this->repository->getUser($userId); + * } + * + * function getUser($userId) + * { + * // `$childSpan` has `$rootSpan` as parent. + * $childSpan = $this->tracer->startActiveSpan('db.query'); + * } + * * @param string $operationName - * @param SpanReference|null $parentReference - * @param float|int|\DateTimeInterface|null $startTimestamp if passing float or int - * it should represent the timestamp (including as many decimal places as you need) - * @param array $tags + * @param array|SpanOptions $options * @return Span * @throws InvalidSpanOption for invalid option */ - public function startSpan( - $operationName, - SpanReference $parentReference = null, - $startTimestamp = null, - array $tags = [] - ); + public function startActiveSpan($operationName, $options = []); /** + * Starts and returns a new Span representing a unit of work. + * * @param string $operationName * @param array|SpanOptions $options * @return Span * @throws InvalidSpanOption for invalid option */ - public function startSpanWithOptions($operationName, $options); + public function startManualSpan($operationName, $options = []); + + /** + * @return ActiveSpanSource + */ + public function activeSpanSource(); + + /** + * @return Span + */ + public function activeSpan(); /** * @param SpanContext $spanContext From acd73b0a3011dc6107f8911692d4f18da506f47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Wed, 12 Jul 2017 09:48:53 +0200 Subject: [PATCH 2/2] Renames activeSpan into getActiveSpan on SpanSource. --- src/OpenTracing/ActiveSpanSource.php | 2 +- src/OpenTracing/NoopActiveSpanSource.php | 2 +- src/OpenTracing/Tracer.php | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/OpenTracing/ActiveSpanSource.php b/src/OpenTracing/ActiveSpanSource.php index 494524d..0ea3eff 100644 --- a/src/OpenTracing/ActiveSpanSource.php +++ b/src/OpenTracing/ActiveSpanSource.php @@ -21,7 +21,7 @@ public function activate(Span $span); * * @return Span */ - public function activeSpan(); + public function getActiveSpan(); /** * Deactivate the given `Span`, restoring the previous active one. diff --git a/src/OpenTracing/NoopActiveSpanSource.php b/src/OpenTracing/NoopActiveSpanSource.php index f3a9070..5a02671 100644 --- a/src/OpenTracing/NoopActiveSpanSource.php +++ b/src/OpenTracing/NoopActiveSpanSource.php @@ -13,7 +13,7 @@ public function activate(Span $span) { } - public function activeSpan() + public function getActiveSpan() { return NoopSpan::create(); } diff --git a/src/OpenTracing/Tracer.php b/src/OpenTracing/Tracer.php index b759f00..2868245 100644 --- a/src/OpenTracing/Tracer.php +++ b/src/OpenTracing/Tracer.php @@ -24,6 +24,13 @@ interface Tracer */ const FORMAT_HTTP_HEADERS = 3; + /** + * @deprecated use either startActiveSpan or startManualSpan instead. + * As implementor consider this as a backward compatibility alias for + * startActiveSpan + */ + public function startSpan($operationName, $options = []); + /** * Starts and returns a new `Span` representing a unit of work. *