From 8f3646a9c93a06f76f6abb31020fdb74b4b1fc59 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 9 Apr 2023 20:50:33 +0300 Subject: exp: jaeger tracing --- .../jaeger-client-php/src/Jaeger/Tracer.php | 420 +++++++++++++++++++++ 1 file changed, 420 insertions(+) create mode 100644 vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Tracer.php (limited to 'vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Tracer.php') diff --git a/vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Tracer.php b/vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Tracer.php new file mode 100644 index 000000000..bb0649a0b --- /dev/null +++ b/vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Tracer.php @@ -0,0 +1,420 @@ +serviceName = $serviceName; + $this->reporter = $reporter; + $this->sampler = $sampler; + $this->oneSpanPerRpc = $oneSpanPerRpc; + + $this->logger = $logger ?? new NullLogger(); + $this->scopeManager = $scopeManager ?? new ScopeManager(); + + $this->debugIdHeader = $debugIdHeader; + + $this->codecs = [ + TEXT_MAP => new TextCodec( + false, + $traceIdHeader, + $baggageHeaderPrefix, + $debugIdHeader + ), + HTTP_HEADERS => new TextCodec( + true, + $traceIdHeader, + $baggageHeaderPrefix, + $debugIdHeader + ), + BINARY => new BinaryCodec(), + ZIPKIN_SPAN_FORMAT => new ZipkinCodec(), + ]; + + $this->tags = [ + JAEGER_VERSION_TAG_KEY => JAEGER_CLIENT_VERSION, + ]; + if ($tags !== null) { + $this->tags = array_merge($this->tags, $tags); + } + + $hostname = $this->getHostName(); + $this->ipAddress = $this->getHostByName($hostname); + + if (!empty($hostname)) { + $this->tags[JAEGER_HOSTNAME_TAG_KEY] = $hostname; + } + } + + /** + * @return string[] + */ + public function getTags(): array + { + return $this->tags; + } + + /** + * {@inheritdoc} + */ + public function startSpan(string $operationName, $options = []): OTSpan + { + if (!($options instanceof StartSpanOptions)) { + $options = StartSpanOptions::create($options); + } + + $parent = $this->getParentSpanContext($options); + $tags = $options->getTags(); + + $rpcServer = ($tags[SPAN_KIND] ?? null) == SPAN_KIND_RPC_SERVER; + + if ($parent == null || $parent->isDebugIdContainerOnly()) { + $traceId = $this->randomId(); + $spanId = $traceId; + $parentId = null; + $flags = 0; + $baggage = null; + if ($parent == null) { + list($sampled, $samplerTags) = $this->sampler->isSampled($traceId, $operationName); + if ($sampled) { + $flags = SAMPLED_FLAG; + $tags = $tags ?? []; + foreach ($samplerTags as $key => $value) { + $tags[$key] = $value; + } + } + } else { // have debug id + $flags = SAMPLED_FLAG | DEBUG_FLAG; + $tags = $tags ?? []; + $tags[$this->debugIdHeader] = $parent->getDebugId(); + } + } else { + $traceId = $parent->getTraceId(); + if ($rpcServer && $this->oneSpanPerRpc) { + // Zipkin-style one-span-per-RPC + $spanId = $parent->getSpanId(); + $parentId = $parent->getParentId(); + } else { + $spanId = $this->randomId(); + $parentId = $parent->getSpanId(); + } + + $flags = $parent->getFlags(); + $baggage = $parent->getBaggage(); + } + + $spanContext = new SpanContext( + $traceId, + $spanId, + $parentId, + $flags, + $baggage + ); + + $span = new Span( + $spanContext, + $this, + $operationName, + $tags ?? [], + $options->getStartTime() + ); + + $mergedTags = array_merge($this->tags, $tags); + $span->setTags($mergedTags); + + return $span; + } + + /** + * {@inheritdoc} + * + * @param SpanContext $spanContext + * @param string $format + * @param mixed $carrier + * @return void + * + * @throws UnsupportedFormat + */ + public function inject(OTSpanContext $spanContext, string $format, &$carrier): void + { + if ($spanContext instanceof SpanContext) { + $codec = $this->codecs[$format] ?? null; + + if ($codec == null) { + throw UnsupportedFormatException::forFormat(is_scalar($format) ? $format : gettype($format)); + } + + + $codec->inject($spanContext, $carrier); + return; + } + + $message = sprintf( + 'Invalid span context. Expected Jaeger\SpanContext, got %s.', + is_object($spanContext) ? get_class($spanContext) : gettype($spanContext) + ); + + $this->logger->warning($message); + } + + /** + * {@inheritdoc} + * + * @param mixed $carrier + * @return SpanContext|null + * + * @throws UnsupportedFormat + */ + public function extract(string $format, $carrier): ?OTSpanContext + { + $codec = $this->codecs[$format] ?? null; + + if ($codec == null) { + throw UnsupportedFormatException::forFormat(is_scalar($format) ? $format : gettype($format)); + } + + try { + return $codec->extract($carrier); + } catch (\Throwable $e) { + $this->logger->warning($e->getMessage()); + + return null; + } + } + + /** + * {@inheritdoc} + */ + public function flush(): void + { + $this->sampler->close(); + $this->reporter->close(); + } + + public function reportSpan(Span $span) + { + $this->reporter->reportSpan($span); + } + + /** + * {@inheritdoc} + */ + public function getScopeManager(): OTScopeManager + { + return $this->scopeManager; + } + + /** + * {@inheritdoc} + */ + public function getActiveSpan(): ?OTSpan + { + $activeScope = $this->getScopeManager()->getActive(); + if ($activeScope === null) { + return null; + } + + return $activeScope->getSpan(); + } + + /** + * {@inheritdoc} + */ + public function startActiveSpan(string $operationName, $options = []): OTScope + { + if (!$options instanceof StartSpanOptions) { + $options = StartSpanOptions::create($options); + } + + if (!$this->getParentSpanContext($options) && $this->getActiveSpan() !== null) { + $parent = $this->getActiveSpan()->getContext(); + $options = $options->withParent($parent); + } + + $span = $this->startSpan($operationName, $options); + $scope = $this->scopeManager->activate($span, $options->shouldFinishSpanOnClose()); + + return $scope; + } + + /** + * Gets parent span context (if any). + * + * @param StartSpanOptions $options + * @return null|OTSpanContext|SpanContext + */ + private function getParentSpanContext(StartSpanOptions $options) + { + $references = $options->getReferences(); + foreach ($references as $ref) { + if ($ref->isType(Reference::CHILD_OF)) { + return $ref->getSpanContext(); + } + } + + return null; + } + + /** + * @return string + * @throws Exception + */ + private function randomId(): string + { + return (string) random_int(0, PHP_INT_MAX); + } + + /** + * The facade to get the host name. + * + * @return string + */ + protected function getHostName() + { + return gethostname(); + } + + /** + * The facade to get IPv4 address corresponding to a given Internet host name. + * + * NOTE: DNS Resolution may take too long, and during this time your script is NOT being executed. + * + * @param string|null $hostname + * @return string + */ + protected function getHostByName($hostname) + { + if (empty($hostname)) { + $this->logger->error('Unable to determine host name'); + return '127.0.0.1'; + } + + return gethostbyname($hostname); + } + + /** + * @param SamplerInterface $sampler + * @return $this + */ + public function setSampler(SamplerInterface $sampler) + { + $this->sampler = $sampler; + + return $this; + } + + /** + * @return string + */ + public function getServiceName() + { + return $this->serviceName; + } + + /** + * @return string + */ + public function getIpAddress() + { + return $this->ipAddress; + } +} -- cgit v1.2.3