Skip to content

Commit

Permalink
Added support for distributed tracing
Browse files Browse the repository at this point in the history
Including automatic HTTP header injection for outgoing HTTP request using curl (or any higher level library that is based on curl such as Guzzle)
  • Loading branch information
SergeyKleyman committed Nov 9, 2020
1 parent b4c04c0 commit 7ab8058
Show file tree
Hide file tree
Showing 47 changed files with 808 additions and 196 deletions.
Expand Up @@ -8,9 +8,9 @@

use Elastic\Apm\Impl\TracerBuilder;
use ElasticApmTests\UnitTests\Util\MockEventSink;
use ElasticApmTests\UnitTests\Util\UnitTestCaseBase;
use ElasticApmTests\UnitTests\Util\TracerUnitTestCaseBase;

class ExampleUsingPublicApi extends UnitTestCaseBase
class ExampleUsingPublicApi extends TracerUnitTestCaseBase
{
public function main(): void
{
Expand Down
@@ -1,11 +1,11 @@
<?php

/** @noinspection PhpUndefinedClassInspection */

declare(strict_types=1);

namespace Elastic\Apm\AutoInstrument;

use Throwable;

interface InterceptedCallTrackerInterface
{
/**
Expand All @@ -20,6 +20,8 @@ public function preHook(?object $interceptedCallThis, ...$interceptedCallArgs):
* @param int $numberOfStackFramesToSkip
* @param bool $hasExitedByException
* @param mixed|Throwable $returnValueOrThrown Return value of the intercepted call or thrown object
*
* @noinspection PhpMissingParamTypeInspection
*/
public function postHook(int $numberOfStackFramesToSkip, bool $hasExitedByException, $returnValueOrThrown): void;
}
2 changes: 0 additions & 2 deletions src/ElasticApm/AutoInstrument/PluginInterface.php
@@ -1,7 +1,5 @@
<?php

/** @noinspection PhpUndefinedClassInspection */

declare(strict_types=1);

namespace Elastic\Apm\AutoInstrument;
Expand Down
@@ -1,7 +1,5 @@
<?php

/** @noinspection PhpUndefinedClassInspection */

declare(strict_types=1);

namespace Elastic\Apm\AutoInstrument;
Expand Down
17 changes: 17 additions & 0 deletions src/ElasticApm/DistributedTracingData.php
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Elastic\Apm;

final class DistributedTracingData
{
/** @var string */
public $traceId;

/** @var string */
public $parentId;

/** @var bool */
public $isSampled;
}
104 changes: 87 additions & 17 deletions src/ElasticApm/ElasticApm.php
@@ -1,7 +1,5 @@
<?php

/** @noinspection PhpUndefinedClassInspection */

declare(strict_types=1);

namespace Elastic\Apm;
Expand All @@ -24,32 +22,38 @@ final class ElasticApm
/**
* Begins a new transaction and sets it as the current transaction.
*
* @param string $name New transaction's name
* @param string $type New transaction's type
* @param float|null $timestamp Start time of the new transaction
* @param string $name New transaction's name
* @param string $type New transaction's type
* @param float|null $timestamp Start time of the new transaction
* @param DistributedTracingData|null $distributedTracingData
*
* @return TransactionInterface New transaction
*
* @see TransactionInterface::setName() For the description.
* @see TransactionInterface::setType() For the description.
* @see TransactionInterface::getTimestamp() For the description.
*
* @return TransactionInterface New transaction
*/
public static function beginCurrentTransaction(
string $name,
string $type,
?float $timestamp = null
?float $timestamp = null,
?DistributedTracingData $distributedTracingData = null
): TransactionInterface {
return GlobalTracerHolder::get()->beginCurrentTransaction($name, $type, $timestamp);
return GlobalTracerHolder::get()->beginCurrentTransaction($name, $type, $timestamp, $distributedTracingData);
}

/**
* Begins a new transaction, sets as the current transaction,
* runs the provided callback as the new transaction and automatically ends the new transaction.
*
* @param string $name New transaction's name
* @param string $type New transaction's type
* @param Closure $callback Callback to execute as the new transaction
* @param float|null $timestamp Start time of the new transaction
* @param string $name New transaction's name
* @param string $type New transaction's type
* @param Closure $callback Callback to execute as the new transaction
* @param float|null $timestamp Start time of the new transaction
* @param DistributedTracingData|null $distributedTracingData
*
* @return mixed The return value of $callback
*
* @template T
* @phpstan-param Closure(TransactionInterface $newTransaction): T $callback
Expand All @@ -58,16 +62,21 @@ public static function beginCurrentTransaction(
* @see TransactionInterface::setName() For the description.
* @see TransactionInterface::setType() For the description.
* @see TransactionInterface::getTimestamp() For the description.
*
* @return mixed The return value of $callback
*/
public static function captureCurrentTransaction(
string $name,
string $type,
Closure $callback,
?float $timestamp = null
?float $timestamp = null,
?DistributedTracingData $distributedTracingData = null
) {
return GlobalTracerHolder::get()->captureCurrentTransaction($name, $type, $callback, $timestamp);
return GlobalTracerHolder::get()->captureCurrentTransaction(
$name,
$type,
$callback,
$timestamp,
$distributedTracingData
);
}

/**
Expand All @@ -80,13 +89,74 @@ public static function getCurrentTransaction(): TransactionInterface
return GlobalTracerHolder::get()->getCurrentTransaction();
}

/**
* Begins a new transaction.
*
* @param string $name New transaction's name
* @param string $type New transaction's type
* @param float|null $timestamp Start time of the new transaction
* @param DistributedTracingData|null $distributedTracingData
*
* @return TransactionInterface New transaction
*
* @see TransactionInterface::setName() For the description.
* @see TransactionInterface::setType() For the description.
* @see TransactionInterface::getTimestamp() For the description.
*
*/
public static function beginTransaction(
string $name,
string $type,
?float $timestamp = null,
?DistributedTracingData $distributedTracingData = null
): TransactionInterface {
return GlobalTracerHolder::get()->beginTransaction($name, $type, $timestamp, $distributedTracingData);
}

/**
* Begins a new transaction,
* runs the provided callback as the new transaction and automatically ends the new transaction.
*
* @param string $name New transaction's name
* @param string $type New transaction's type
* @param Closure $callback Callback to execute as the new transaction
* @param float|null $timestamp Start time of the new transaction
* @param DistributedTracingData|null $distributedTracingData
*
* @return mixed The return value of $callback
*
* @template T
* @phpstan-param Closure(TransactionInterface $newTransaction): T $callback
* @phpstan-return T
*
* @see TransactionInterface::setName() For the description.
* @see TransactionInterface::setType() For the description.
* @see TransactionInterface::getTimestamp() For the description.
*/
public static function captureTransaction(
string $name,
string $type,
Closure $callback,
?float $timestamp = null,
?DistributedTracingData $distributedTracingData = null
) {
return GlobalTracerHolder::get()->captureTransaction(
$name,
$type,
$callback,
$timestamp,
$distributedTracingData
);
}

/**
* Creates an error based on the given Throwable instance
* with the current execution segment (if there is one) as the parent.
*
* @param Throwable $throwable
*
* @return string|null ID of the reported error event or null if no event was reported
* (for example, becasue recording is disabled)
* (for example, because recording is disabled)
*
* @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json
*/
Expand Down
4 changes: 0 additions & 4 deletions src/ElasticApm/ExecutionSegmentContextInterface.php
@@ -1,13 +1,9 @@
<?php

/** @noinspection PhpUndefinedClassInspection */

declare(strict_types=1);

namespace Elastic\Apm;

use Closure;

/**
* This interface has functionality shared between Transaction and Span contexts'.
*/
Expand Down
9 changes: 6 additions & 3 deletions src/ElasticApm/ExecutionSegmentInterface.php
@@ -1,7 +1,5 @@
<?php

/** @noinspection PhpUndefinedClassInspection */

declare(strict_types=1);

namespace Elastic\Apm;
Expand Down Expand Up @@ -130,6 +128,11 @@ public function setName(string $name): void;
*/
public function setType(string $type): void;

/**
* Returns distributed tracing data
*/
public function getDistributedTracingData(): ?DistributedTracingData;

/**
* Sets the end timestamp and finalizes this object's state.
*
Expand All @@ -151,7 +154,7 @@ public function hasEnded(): bool;
*
* @param Throwable $throwable
* @return string|null ID of the reported error event or null if no event was reported
* (for example, becasue recording is disabled)
* (for example, because recording is disabled)
*
* @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json
*/
Expand Down
17 changes: 15 additions & 2 deletions src/ElasticApm/Impl/AutoInstrument/BuiltinPlugin.php
Expand Up @@ -6,6 +6,7 @@

use Elastic\Apm\AutoInstrument\PluginInterface;
use Elastic\Apm\AutoInstrument\RegistrationContextInterface;
use Elastic\Apm\Impl\Tracer;

/**
* Code in this file is part of implementation internals and thus it is not covered by the backward compatibility.
Expand All @@ -14,10 +15,22 @@
*/
final class BuiltinPlugin implements PluginInterface
{
/** @var PdoAutoInstrumentation */
private $pdoAutoInstrumentation;

/** @var CurlAutoInstrumentation */
private $curlAutoInstrumentation;

public function __construct(Tracer $tracer)
{
$this->pdoAutoInstrumentation = new PdoAutoInstrumentation($tracer);
$this->curlAutoInstrumentation = new CurlAutoInstrumentation($tracer);
}

public function register(RegistrationContextInterface $ctx): void
{
PdoAutoInstrumentation::register($ctx);
CurlAutoInstrumentation::register($ctx);
$this->pdoAutoInstrumentation->register($ctx);
$this->curlAutoInstrumentation->register($ctx);
}

public function getDescription(): string
Expand Down

0 comments on commit 7ab8058

Please sign in to comment.