summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2023-10-24 17:50:00 +0300
committerAndrew Dolgov <[email protected]>2023-10-24 17:50:00 +0300
commit3d5308a6e5f2b3bbfc307716292d1cc98e424edb (patch)
treef90be99acb56d6bcf2b83a9c68b8abcbf24ed7a8
parent1e3b7f7a43819f03c5efa5078e102d664fb7917a (diff)
add stub opentelemetry classes in case it is disabled
-rw-r--r--.vscode/tasks.json2
-rw-r--r--classes/tracer.php204
-rwxr-xr-x[-rw-r--r--]utils/phpstan-watcher.sh0
3 files changed, 161 insertions, 45 deletions
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 69fd3f3f4..d59e3ff10 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -21,7 +21,7 @@
}
},
- "command": "${workspaceRoot}/utils/phpstan-watcher.sh",
+ "command": "chmod +x ${workspaceRoot}/utils/phpstan-watcher.sh && ${workspaceRoot}/utils/phpstan-watcher.sh",
},
{
"type": "gulp",
diff --git a/classes/tracer.php b/classes/tracer.php
index 034d85619..7163adb90 100644
--- a/classes/tracer.php
+++ b/classes/tracer.php
@@ -1,8 +1,16 @@
<?php
-
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
+use OpenTelemetry\API\Trace\SpanContextInterface;
+use OpenTelemetry\API\Trace\SpanInterface;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TraceFlags;
+use OpenTelemetry\API\Trace\TraceStateInterface;
+use OpenTelemetry\Context\ContextInterface;
+use OpenTelemetry\Context\ContextKey;
+use OpenTelemetry\Context\ContextKeyInterface;
+use OpenTelemetry\Context\ImplicitContextKeyedInterface;
+use OpenTelemetry\Context\ScopeInterface;
use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Common\Attribute\Attributes;
@@ -10,20 +18,126 @@ use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
use OpenTelemetry\SDK\Trace\Sampler\ParentBased;
-use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
use OpenTelemetry\SemConv\ResourceAttributes;
+class DummyContextInterface implements ContextInterface {
+
+ /** @var DummyContextInterface */
+ private static $instance;
+
+ public function __construct() {
+ self::$instance = $this;
+ }
+
+ /** @phpstan-ignore-next-line */
+ public static function createKey(string $key): ContextKeyInterface { return new ContextKey(); }
+
+ public static function getCurrent(): ContextInterface { return self::$instance; }
+
+ public function activate(): ScopeInterface { return new DummyScopeInterface(); }
+
+ public function with(ContextKeyInterface $key, $value): ContextInterface { return $this; }
+
+ public function withContextValue(ImplicitContextKeyedInterface $value): ContextInterface { return $this; }
+
+ public function get(ContextKeyInterface $key) { return new ContextKey(); }
+
+}
+
+class DummySpanContextInterface implements SpanContextInterface {
+
+ /** @var DummySpanContextInterface $instance */
+ private static $instance;
+
+ public function __construct() {
+ self::$instance = $this;
+ }
+
+ public static function createFromRemoteParent(string $traceId, string $spanId, int $traceFlags = TraceFlags::DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface { return self::$instance; }
+
+ public static function getInvalid(): SpanContextInterface { return self::$instance; }
+
+ public static function create(string $traceId, string $spanId, int $traceFlags = TraceFlags::DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface { return self::$instance; }
+
+ public function getTraceId(): string { return ""; }
+
+ public function getTraceIdBinary(): string { return ""; }
+
+ public function getSpanId(): string { return ""; }
+
+ public function getSpanIdBinary(): string { return ""; }
+
+ public function getTraceFlags(): int { return 0; }
+
+ public function getTraceState(): ?TraceStateInterface { return null; }
+
+ public function isValid(): bool { return false; }
+
+ public function isRemote(): bool { return false; }
+
+ public function isSampled(): bool { return false; }
+}
+
+class DummyScopeInterface implements ScopeInterface {
+ public function detach(): int { return 0; }
+}
+
+class DummySpanInterface implements SpanInterface {
+
+ /** @var DummySpanInterface $instance */
+ private static $instance;
+
+ public function __construct() {
+ self::$instance = $this;
+ }
+
+ public static function fromContext(ContextInterface $context): SpanInterface { return self::$instance; }
+
+ public static function getCurrent(): SpanInterface { return self::$instance; }
+
+ public static function getInvalid(): SpanInterface { return self::$instance; }
+
+ public static function wrap(SpanContextInterface $spanContext): SpanInterface { return self::$instance; }
+
+ public function getContext(): SpanContextInterface { return new DummySpanContextInterface(); }
+
+ public function isRecording(): bool { return false; }
+
+ /** @phpstan-ignore-next-line */
+ public function setAttribute(string $key, $value): SpanInterface { return self::$instance; }
+
+ /** @phpstan-ignore-next-line */
+ public function setAttributes(iterable $attributes): SpanInterface { return self::$instance; }
+
+ /** @phpstan-ignore-next-line */
+ public function addEvent(string $name, iterable $attributes = [], ?int $timestamp = null): SpanInterface { return $this; }
+
+ /** @phpstan-ignore-next-line */
+ public function recordException(Throwable $exception, iterable $attributes = []): SpanInterface { return $this; }
+
+ public function updateName(string $name): SpanInterface { return $this; }
+
+ public function setStatus(string $code, ?string $description = null): SpanInterface { return $this; }
+
+ public function end(?int $endEpochNanos = null): void { }
+
+ public function activate(): ScopeInterface { return new DummyScopeInterface(); }
+
+ public function storeInContext(ContextInterface $context): ContextInterface { return new DummyContextInterface(); }
+
+}
+
class Tracer {
/** @var Tracer $instance */
- private static $instance;
+ private static $instance = null;
/** @var OpenTelemetry\SDK\Trace\TracerProviderInterface $tracerProvider */
- private $tracerProvider;
+ private $tracerProvider = null;
/** @var OpenTelemetry\API\Trace\TracerInterface $tracer */
- private $tracer;
+ private $tracer = null;
public function __construct() {
$OPENTELEMETRY_ENDPOINT = Config::get(Config::OPENTELEMETRY_ENDPOINT);
@@ -31,41 +145,39 @@ class Tracer {
if ($OPENTELEMETRY_ENDPOINT) {
$transport = (new OtlpHttpTransportFactory())->create($OPENTELEMETRY_ENDPOINT, 'application/x-protobuf');
$exporter = new SpanExporter($transport);
- } else {
- $exporter = new InMemoryExporter();
- }
- $resource = ResourceInfoFactory::emptyResource()->merge(
- ResourceInfo::create(Attributes::create(
- [ResourceAttributes::SERVICE_NAME => Config::get(Config::OPENTELEMETRY_SERVICE)]
- ), ResourceAttributes::SCHEMA_URL),
- );
-
- $this->tracerProvider = TracerProvider::builder()
- ->addSpanProcessor(new SimpleSpanProcessor($exporter))
- ->setResource($resource)
- ->setSampler(new ParentBased(new AlwaysOnSampler()))
- ->build();
-
- $this->tracer = $this->tracerProvider->getTracer('io.opentelemetry.contrib.php');
-
- $context = TraceContextPropagator::getInstance()->extract(getallheaders());
-
- $span = $this->tracer->spanBuilder($_SESSION['name'] ?? 'not logged in')
- ->setParent($context)
- ->setSpanKind(SpanKind::KIND_SERVER)
- ->setAttribute('php.request', json_encode($_REQUEST))
- ->setAttribute('php.server', json_encode($_SERVER))
- ->setAttribute('php.session', json_encode($_SESSION ?? []))
- ->startSpan();
-
- $scope = $span->activate();
-
- register_shutdown_function(function() use ($span, $scope) {
- $span->end();
- $scope->detach();
- $this->tracerProvider->shutdown();
- });
+ $resource = ResourceInfoFactory::emptyResource()->merge(
+ ResourceInfo::create(Attributes::create(
+ [ResourceAttributes::SERVICE_NAME => Config::get(Config::OPENTELEMETRY_SERVICE)]
+ ), ResourceAttributes::SCHEMA_URL),
+ );
+
+ $this->tracerProvider = TracerProvider::builder()
+ ->addSpanProcessor(new SimpleSpanProcessor($exporter))
+ ->setResource($resource)
+ ->setSampler(new ParentBased(new AlwaysOnSampler()))
+ ->build();
+
+ $this->tracer = $this->tracerProvider->getTracer('io.opentelemetry.contrib.php');
+
+ $context = TraceContextPropagator::getInstance()->extract(getallheaders());
+
+ $span = $this->tracer->spanBuilder($_SESSION['name'] ?? 'not logged in')
+ ->setParent($context)
+ ->setSpanKind(SpanKind::KIND_SERVER)
+ ->setAttribute('php.request', json_encode($_REQUEST))
+ ->setAttribute('php.server', json_encode($_SERVER))
+ ->setAttribute('php.session', json_encode($_SESSION ?? []))
+ ->startSpan();
+
+ $scope = $span->activate();
+
+ register_shutdown_function(function() use ($span, $scope) {
+ $span->end();
+ $scope->detach();
+ $this->tracerProvider->shutdown();
+ });
+ }
}
/**
@@ -73,12 +185,16 @@ class Tracer {
* @return OpenTelemetry\API\Trace\SpanInterface
*/
private function _start(string $name) {
- $span = $this->tracer
- ->spanBuilder($name)
- ->setSpanKind(SpanKind::KIND_SERVER)
- ->startSpan();
+ if ($this->tracer != null) {
+ $span = $this->tracer
+ ->spanBuilder($name)
+ ->setSpanKind(SpanKind::KIND_SERVER)
+ ->startSpan();
- $span->activate();
+ $span->activate();
+ } else {
+ $span = new DummySpanInterface();
+ }
return $span;
}
diff --git a/utils/phpstan-watcher.sh b/utils/phpstan-watcher.sh
index 1972df049..1972df049 100644..100755
--- a/utils/phpstan-watcher.sh
+++ b/utils/phpstan-watcher.sh