-
Notifications
You must be signed in to change notification settings - Fork 149
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
Adds opentracing compatibility. #7
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,46 +4,25 @@ | |
|
||
use Exception; | ||
use InvalidArgumentException; | ||
use OpenTracing\SpanContext as OpenTracingContext; | ||
use Throwable; | ||
use OpenTracing\Span as OpenTracingSpan; | ||
|
||
final class Span | ||
final class Span implements OpenTracingSpan | ||
{ | ||
/** | ||
* @var Tracer | ||
*/ | ||
private $tracer; | ||
|
||
/** | ||
* The unique integer (64-bit unsigned) ID of the trace containing this span. | ||
* It is stored in hexadecimal representation. | ||
* | ||
* @var string | ||
*/ | ||
private $traceId; | ||
|
||
/** | ||
* The span integer ID of the parent span. | ||
* | ||
* @var string | ||
*/ | ||
private $parentId; | ||
|
||
/** | ||
* The span integer (64-bit unsigned) ID. | ||
* It is stored in hexadecimal representation. | ||
* | ||
* @var string | ||
*/ | ||
private $spanId; | ||
|
||
/** | ||
* Name is the name of the operation being measured. Some examples | ||
* might be "http.handler", "fileserver.upload" or "video.decompress". | ||
* Name should be set on every span. | ||
* | ||
* @var string | ||
*/ | ||
private $name; | ||
private $operationName; | ||
|
||
/** | ||
* @var OpenTracingContext | ||
*/ | ||
private $context; | ||
|
||
/** | ||
* Resource is a query to a service. A web application might use | ||
|
@@ -72,14 +51,14 @@ final class Span | |
/** | ||
* Protocol associated with the span | ||
* | ||
* @var string | ||
* @var string|null | ||
*/ | ||
private $type; | ||
|
||
/** | ||
* @var int | ||
*/ | ||
private $start; | ||
private $startTime; | ||
|
||
/** | ||
* @var int|null | ||
|
@@ -89,72 +68,66 @@ final class Span | |
/** | ||
* @var array | ||
*/ | ||
private $meta = []; | ||
private $tags = []; | ||
|
||
/** | ||
* @var bool | ||
*/ | ||
private $hasError = false; | ||
|
||
|
||
/** | ||
* Span constructor. | ||
* @param string $operationName | ||
* @param SpanContext $context | ||
* @param string $service | ||
* @param string $resource | ||
* @param int|null $start | ||
*/ | ||
public function __construct( | ||
Tracer $tracer, | ||
$name, | ||
$operationName, | ||
SpanContext $context, | ||
$service, | ||
$resource, | ||
$traceId, | ||
$spanId, | ||
$parentId = null, | ||
$start = null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
) { | ||
$this->tracer = $tracer; | ||
$this->name = (string) $name; | ||
$this->service = $service; | ||
$this->context = $context; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To my understanding, since this constructor is part of the publicly exposed API, we have no guarantee There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah cool then 👍 |
||
$this->operationName = (string) $operationName; | ||
$this->service = (string) $service; | ||
$this->resource = (string) $resource; | ||
$this->start = $start ?: Time\now(); | ||
$this->traceId = $traceId; | ||
$this->spanId = $spanId; | ||
$this->parentId = $parentId; | ||
$this->startTime = $start ?: Time\now(); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getTraceId() | ||
{ | ||
return $this->traceId; | ||
return $this->context->getTraceId(); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getSpanId() | ||
{ | ||
return $this->spanId; | ||
return $this->context->getSpanId(); | ||
} | ||
|
||
/** | ||
* @return null|string | ||
*/ | ||
public function getParentId() | ||
{ | ||
return $this->parentId; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getName() | ||
{ | ||
return $this->name; | ||
return $this->context->getParentId(); | ||
} | ||
|
||
/** | ||
* @param string $name | ||
* @return void | ||
* {@inheritdoc} | ||
*/ | ||
public function setName($name) | ||
public function overwriteOperationName($operationName) | ||
{ | ||
$this->name = $name; | ||
$this->operationName = $operationName; | ||
} | ||
|
||
/** | ||
|
@@ -174,7 +147,7 @@ public function getService() | |
} | ||
|
||
/** | ||
* @return string | ||
* @return string|null | ||
*/ | ||
public function getType() | ||
{ | ||
|
@@ -184,9 +157,9 @@ public function getType() | |
/** | ||
* @return int | ||
*/ | ||
public function getStart() | ||
public function getStartTime() | ||
{ | ||
return $this->start; | ||
return $this->startTime; | ||
} | ||
|
||
/** | ||
|
@@ -198,41 +171,61 @@ public function getDuration() | |
} | ||
|
||
/** | ||
* Adds an arbitrary meta field to the current Span. | ||
* If the Span has been finished, it will not be modified by the method. | ||
* | ||
* @param string $key | ||
* @param string $value | ||
* @throws InvalidArgumentException | ||
* {@inheritdoc} | ||
*/ | ||
public function setMeta($key, $value) | ||
public function setTags(array $tags) | ||
{ | ||
if ($this->isFinished()) { | ||
return; | ||
} | ||
|
||
if ($key !== (string) $key) { | ||
throw new InvalidArgumentException( | ||
sprintf('First argument expected to be string, got %s', gettype($key)) | ||
); | ||
foreach ($tags as $key => $value) { | ||
if ($key !== (string) $key) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know but this way is more performant and observability should have the least overhead possible. |
||
throw new InvalidArgumentException( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you should start to scope exceptions to the context of this library. A lot of client code tend to use catch all exceptions and you have this opportunity to introduce semantic exceptions too. |
||
sprintf('First argument expected to be string, got %s', gettype($key)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can re-word this exception to better reflect the function's new signature. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I am not a native so do you have any advice on how the reword would be better? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uhm, something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Totally. The message I wrote is silly. |
||
); | ||
} | ||
|
||
if ($key === Tags\SERVICE_NAME) { | ||
$this->service = $value; | ||
continue; | ||
} | ||
|
||
if ($key === Tags\RESOURCE_NAME) { | ||
$this->resource = $value; | ||
continue; | ||
} | ||
|
||
if ($key === Tags\SPAN_TYPE) { | ||
$this->type = $value; | ||
continue; | ||
} | ||
|
||
$this->tags[$key] = (string) $value; | ||
} | ||
|
||
$this->meta[$key] = (string) $value; | ||
} | ||
|
||
/** | ||
* @param string $key | ||
* @return string|null | ||
*/ | ||
public function getMeta($key) | ||
public function getTag($key) | ||
{ | ||
if (array_key_exists($key, $this->meta)) { | ||
return $this->meta[$key]; | ||
if (array_key_exists($key, $this->tags)) { | ||
return $this->tags[$key]; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function getAllTags() | ||
{ | ||
return $this->tags; | ||
} | ||
|
||
/** | ||
* Stores a Throwable object within the span meta. The error status is | ||
* updated and the error.Error() string is included with a default meta key. | ||
|
@@ -249,9 +242,11 @@ public function setError($e) | |
|
||
if (($e instanceof Exception) || ($e instanceof Throwable)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From http://php.net/manual/en/class.throwable.php
Is it not enough to typehint for Exception ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh ok, good to know! I didn't see the new Error object in PHP 7. |
||
$this->hasError = true; | ||
$this->setMeta(Tags\ERROR_MSG, $e->getMessage()); | ||
$this->setMeta(Tags\ERROR_TYPE, get_class($e)); | ||
$this->setMeta(Tags\ERROR_STACK, $e->getTraceAsString()); | ||
$this->setTags([ | ||
Tags\ERROR_MSG => $e->getMessage(), | ||
Tags\ERROR_TYPE => get_class($e), | ||
Tags\ERROR_STACK => $e->getTraceAsString(), | ||
]); | ||
return; | ||
} | ||
|
||
|
@@ -266,23 +261,15 @@ public function hasError() | |
} | ||
|
||
/** | ||
* Finish closes this Span (but not its children) providing the duration | ||
* of this part of the tracing session. This method is idempotent so | ||
* calling this method multiple times is safe and doesn't update the | ||
* current Span. Once a Span has been finished, methods that modify the Span | ||
* will become no-ops. | ||
* | ||
* @param int|null $finish | ||
* @return void | ||
* {@inheritdoc} | ||
*/ | ||
public function finish($finish = null) | ||
public function finish($finishTime = null, array $logRecords = []) | ||
{ | ||
if ($this->isFinished()) { | ||
return; | ||
} | ||
|
||
$this->duration = ($finish ?: Time\now()) - $this->start; | ||
$this->tracer->record($this); | ||
$this->duration = ($finishTime ?: Time\now()) - $this->startTime; | ||
} | ||
|
||
/** | ||
|
@@ -295,8 +282,51 @@ public function finishWithError($e) | |
$this->finish(); | ||
} | ||
|
||
private function isFinished() | ||
/** | ||
* @return bool | ||
*/ | ||
public function isFinished() | ||
{ | ||
return $this->duration !== null; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getOperationName() | ||
{ | ||
return $this->operationName; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContext() | ||
{ | ||
return $this->context; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function log(array $fields = [], $timestamp = null) | ||
{ | ||
throw new \BadMethodCallException('not implemented'); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function addBaggageItem($key, $value) | ||
{ | ||
$this->context = $this->context->withBaggageItem($key, $value); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getBaggageItem($key) | ||
{ | ||
return $this->context->getBaggageItem($key); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A detail but
Name
should be updated tooperationName
.