remove proprietary new relic exporters (#998)
New Relic now fully supports OTLP ingestion, and having proprietary exporters is no longer their strategy. The proprietary exporters have been marked as abandoned in packagist, and suggest exporter-otlp as a replacement.
This commit is contained in:
parent
593fa344bc
commit
5d35c998e7
|
|
@ -16,16 +16,12 @@ splits:
|
|||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/api.git"
|
||||
- prefix: "src/SDK"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/sdk.git"
|
||||
- prefix: "src/Contrib/Newrelic"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-newrelic.git"
|
||||
- prefix: "src/Contrib/Otlp"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-otlp.git"
|
||||
- prefix: "src/Contrib/Grpc"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/transport-grpc.git"
|
||||
- prefix: "src/Contrib/Zipkin"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-zipkin.git"
|
||||
- prefix: "src/Contrib/ZipkinToNewrelic"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-zipkintonewrelic.git"
|
||||
- prefix: "src/Extension/Propagator/B3"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/extension-propagator-b3.git"
|
||||
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -66,10 +66,6 @@ smoke-test-exporter-examples: FORCE ## Run (some) exporter smoke test examples
|
|||
$(DOCKER_COMPOSE) up -d --remove-orphans
|
||||
$(DC_RUN_PHP) php ./examples/traces/exporters/zipkin.php
|
||||
$(DC_RUN_PHP) php ./examples/traces/features/parent_span_example.php
|
||||
# The following examples do not use the DC_RUN_PHP global because they need environment variables.
|
||||
$(DOCKER_COMPOSE) run -e NEW_RELIC_ENDPOINT -e NEW_RELIC_INSERT_KEY --rm php php ./examples/traces/exporters/newrelic.php
|
||||
$(DOCKER_COMPOSE) run -e NEW_RELIC_ENDPOINT -e NEW_RELIC_INSERT_KEY --rm php php ./examples/traces/exporters/zipkin_to_newrelic.php
|
||||
$(DOCKER_COMPOSE) stop
|
||||
smoke-test-collector-integration: ## Run smoke test collector integration
|
||||
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml up -d --remove-orphans
|
||||
sleep 5
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@
|
|||
"src/API/Trace/functions.php",
|
||||
"src/Contrib/Otlp/_register.php",
|
||||
"src/Contrib/Grpc/_register.php",
|
||||
"src/Contrib/Newrelic/_register.php",
|
||||
"src/Contrib/Zipkin/_register.php",
|
||||
"src/Extension/Propagator/B3/_register.php",
|
||||
"src/SDK/Logs/Exporter/_register.php",
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
require __DIR__ . '/../../../vendor/autoload.php';
|
||||
|
||||
use OpenTelemetry\SDK\Common\Time\ClockFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
|
||||
use OpenTelemetry\SDK\Trace\TracerProvider;
|
||||
|
||||
/*
|
||||
* Experimental example to send trace data to New Relic.
|
||||
* It will send PHP Otel trace data end to end across the internet to a functional backend.
|
||||
* Needs a license key to connect. For a free account/key, go to: https://newrelic.com/signup/
|
||||
*/
|
||||
|
||||
$licenseKey = getenv('NEW_RELIC_INSERT_KEY');
|
||||
|
||||
// Needs a license key in the environment to connect to the backend server.
|
||||
|
||||
if ($licenseKey == false) {
|
||||
echo PHP_EOL . 'NEW_RELIC_INSERT_KEY not found in environment. Newrelic Example tracing is not enabled.' . PHP_EOL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default Trace API endpoint: https://trace-api.newrelic.com/trace/v1
|
||||
* EU data centers: https://trace-api.eu.newrelic.com/trace/v1
|
||||
*/
|
||||
putenv('NEW_RELIC_ENDPOINT', 'https://trace-api.newrelic.com/trace/v1');
|
||||
$newrelicExporter = (new \OpenTelemetry\Contrib\Newrelic\SpanExporterFactory())->create();
|
||||
|
||||
echo 'Starting Newrelic example';
|
||||
$tracerProvider = new TracerProvider(new SimpleSpanProcessor($newrelicExporter));
|
||||
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
// start a span, register some events
|
||||
$timestamp = ClockFactory::getDefault()->now();
|
||||
$span = $tracer->spanBuilder('session.generate.span.' . microtime(true))->startSpan();
|
||||
|
||||
echo sprintf(
|
||||
PHP_EOL . 'Exporting Trace: %s, Span: %s',
|
||||
$span->getContext()->getTraceId(),
|
||||
$span->getContext()->getSpanId()
|
||||
);
|
||||
|
||||
$span->setAttribute('remote_ip', '1.2.3.4')
|
||||
->setAttribute('country', 'USA');
|
||||
|
||||
$span->addEvent('found_login' . $i, [
|
||||
'id' => $i,
|
||||
'username' => 'otuser' . $i,
|
||||
], $timestamp);
|
||||
$span->addEvent('generated_session', [
|
||||
'id' => md5((string) microtime(true)),
|
||||
], $timestamp);
|
||||
|
||||
$span->end();
|
||||
}
|
||||
echo PHP_EOL . 'Newrelic example complete! See the results at https://one.newrelic.com/launcher/distributed-tracing.launcher?pane=eyJuZXJkbGV0SWQiOiJkaXN0cmlidXRlZC10cmFjaW5nLmhvbWUiLCJzb3J0SW5kZXgiOjAsInNvcnREaXJlY3Rpb24iOiJERVNDIiwicXVlcnkiOnsib3BlcmF0b3IiOiJBTkQiLCJpbmRleFF1ZXJ5Ijp7ImNvbmRpdGlvblR5cGUiOiJJTkRFWCIsIm9wZXJhdG9yIjoiQU5EIiwiY29uZGl0aW9uU2V0cyI6W119LCJzcGFuUXVlcnkiOnsib3BlcmF0b3IiOiJBTkQiLCJjb25kaXRpb25TZXRzIjpbeyJjb25kaXRpb25UeXBlIjoiU1BBTiIsIm9wZXJhdG9yIjoiQU5EIiwiY29uZGl0aW9ucyI6W3siYXR0ciI6InNlcnZpY2UubmFtZSIsIm9wZXJhdG9yIjoiRVEiLCJ2YWx1ZSI6ImFsd2F5c09uTmV3cmVsaWNFeGFtcGxlIn1dfV19fX0=&platform[timeRange][duration]=1800000&platform[$isFallbackTimeRange]=true';
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$tracerProvider->shutdown();
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
require __DIR__ . '/../../../vendor/autoload.php';
|
||||
|
||||
use OpenTelemetry\Contrib\ZipkinToNewrelic\Exporter as ZipkinToNewrelicExporter;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
|
||||
use OpenTelemetry\SDK\Common\Time\ClockFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
|
||||
use OpenTelemetry\SDK\Trace\TracerProvider;
|
||||
|
||||
/*
|
||||
* Experimental example to send trace data to New Relic.
|
||||
* It will send PHP Otel trace data end to end across the internet to a functional backend.
|
||||
* Needs a license key to connect. For a free account/key, go to: https://newrelic.com/signup/
|
||||
*/
|
||||
|
||||
$licenseKey = getenv('NEW_RELIC_INSERT_KEY');
|
||||
|
||||
// Needs a license key in the environment to connect to the backend server.
|
||||
|
||||
if ($licenseKey == false) {
|
||||
echo PHP_EOL . 'NEW_RELIC_INSERT_KEY not found in environment. Newrelic Example tracing is not enabled.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default Trace API endpoint: https://trace-api.newrelic.com/trace/v1
|
||||
* EU data centers: https://trace-api.eu.newrelic.com/trace/v1
|
||||
*/
|
||||
|
||||
$endpointUrl = Configuration::getString('NEW_RELIC_ENDPOINT', 'https://trace-api.newrelic.com/trace/v1');
|
||||
$transport = PsrTransportFactory::discover()->create($endpointUrl, $licenseKey);
|
||||
$zipkinToNewrelicExporter = new ZipkinToNewrelicExporter(
|
||||
'AlwaysOnZipkinToNewrelicExample',
|
||||
$transport
|
||||
);
|
||||
|
||||
echo 'Starting ZipkinToNewRelic example';
|
||||
$tracerProvider = new TracerProvider(new SimpleSpanProcessor($zipkinToNewrelicExporter));
|
||||
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
// start a span, register some events
|
||||
$timestamp = ClockFactory::getDefault()->now();
|
||||
$span = $tracer->spanBuilder('session.generate.span.' . microtime(true))->startSpan();
|
||||
|
||||
echo sprintf(
|
||||
PHP_EOL . 'Exporting Trace: %s, Span: %s',
|
||||
$span->getContext()->getTraceId(),
|
||||
$span->getContext()->getSpanId()
|
||||
);
|
||||
|
||||
$span->setAttribute('remote_ip', '1.2.3.4')
|
||||
->setAttribute('country', 'USA');
|
||||
|
||||
$span->addEvent('found_login' . $i, [
|
||||
'id' => $i,
|
||||
'username' => 'otuser' . $i,
|
||||
], $timestamp);
|
||||
$span->addEvent('generated_session', [
|
||||
'id' => md5((string) microtime(true)),
|
||||
], $timestamp);
|
||||
|
||||
$span->end();
|
||||
}
|
||||
echo PHP_EOL . 'ZipkinToNewrelic example complete! See the results at https://one.newrelic.com/launcher/distributed-tracing.launcher?pane=eyJuZXJkbGV0SWQiOiJkaXN0cmlidXRlZC10cmFjaW5nLmhvbWUiLCJzb3J0SW5kZXgiOjAsInNvcnREaXJlY3Rpb24iOiJERVNDIiwicXVlcnkiOnsib3BlcmF0b3IiOiJBTkQiLCJpbmRleFF1ZXJ5Ijp7ImNvbmRpdGlvblR5cGUiOiJJTkRFWCIsIm9wZXJhdG9yIjoiQU5EIiwiY29uZGl0aW9uU2V0cyI6W119LCJzcGFuUXVlcnkiOnsib3BlcmF0b3IiOiJBTkQiLCJjb25kaXRpb25TZXRzIjpbeyJjb25kaXRpb25UeXBlIjoiU1BBTiIsIm9wZXJhdG9yIjoiQU5EIiwiY29uZGl0aW9ucyI6W3siYXR0ciI6InNlcnZpY2UubmFtZSIsIm9wZXJhdG9yIjoiRVEiLCJ2YWx1ZSI6ImFsd2F5c09uWmlwa2luVG9OZXdyZWxpY0V4YW1wbGUifV19XX19fQ==&platform[timeRange][duration]=1800000&platform[$isFallbackTimeRange]=true';
|
||||
|
||||
echo PHP_EOL;
|
||||
$tracerProvider->shutdown();
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Contrib\Newrelic;
|
||||
|
||||
use JsonException;
|
||||
use OpenTelemetry\API\Behavior\LogsMessagesTrait;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\Future\FutureInterface;
|
||||
use OpenTelemetry\SDK\Trace\Behavior\UsesSpanConverterTrait;
|
||||
use OpenTelemetry\SDK\Trace\SpanExporterInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class NewrelicExporter - implements the export interface for data transfer via Newrelic protocol
|
||||
* @package OpenTelemetry\Exporter
|
||||
*
|
||||
* This is an experimental, non-supported exporter.
|
||||
* It will send PHP Otel trace data end to end across the internet to a functional backend.
|
||||
* Needs a license key to connect. For a free account/key, go to: https://newrelic.com/signup/
|
||||
*/
|
||||
class Exporter implements SpanExporterInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
use UsesSpanConverterTrait;
|
||||
|
||||
public const DATA_FORMAT_VERSION_DEFAULT = '1';
|
||||
|
||||
private TransportInterface $transport;
|
||||
private string $endpointUrl;
|
||||
|
||||
public function __construct(
|
||||
TransportInterface $transport,
|
||||
string $endpointUrl,
|
||||
SpanConverter $spanConverter = null
|
||||
) {
|
||||
$this->endpointUrl = $endpointUrl;
|
||||
$this->transport = $transport;
|
||||
$this->setSpanConverter($spanConverter ?? new SpanConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function serializeTrace(iterable $spans): string
|
||||
{
|
||||
return json_encode($this->convert($spans), JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
private function convert(iterable $spans): array
|
||||
{
|
||||
$commonAttributes = ['attributes' => [
|
||||
'host' => $this->endpointUrl, ]];
|
||||
|
||||
return [[ 'common' => $commonAttributes,
|
||||
'spans' => $this->getSpanConverter()->convert($spans), ]];
|
||||
}
|
||||
|
||||
public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface
|
||||
{
|
||||
return $this->transport
|
||||
->send($this->serializeTrace($batch), $cancellation)
|
||||
->map(static fn (): bool => true)
|
||||
->catch(static function (Throwable $throwable): bool {
|
||||
self::logError('Export failure', ['exception' => $throwable]);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public function shutdown(?CancellationInterface $cancellation = null): bool
|
||||
{
|
||||
return $this->transport->shutdown($cancellation);
|
||||
}
|
||||
|
||||
public function forceFlush(?CancellationInterface $cancellation = null): bool
|
||||
{
|
||||
return $this->transport->forceFlush($cancellation);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
# OpenTelemetry New Relic Exporter
|
||||
|
||||
A New Relic exporter for OpenTelemetry.
|
||||
|
||||
## Usage
|
||||
|
||||
See https://github.com/open-telemetry/opentelemetry-php/blob/main/examples/traces/exporters/newrelic.php
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Contrib\Newrelic;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Time\Util as TimeUtil;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanConverterInterface;
|
||||
use OpenTelemetry\SDK\Trace\SpanDataInterface;
|
||||
use OpenTelemetry\SemConv\ResourceAttributes;
|
||||
|
||||
/**
|
||||
* @see https://docs.newrelic.com/docs/distributed-tracing/trace-api/report-new-relic-format-traces-trace-api/#new-relic-guidelines
|
||||
*/
|
||||
class SpanConverter implements SpanConverterInterface
|
||||
{
|
||||
const STATUS_CODE_TAG_KEY = 'otel.status_code';
|
||||
const STATUS_DESCRIPTION_TAG_KEY = 'otel.status_description';
|
||||
const KEY_DROPPED_ATTRIBUTES_COUNT = 'otel.dropped_attributes_count';
|
||||
|
||||
private string $defaultServiceName;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->defaultServiceName = ResourceInfoFactory::defaultResource()->getAttributes()->get(ResourceAttributes::SERVICE_NAME);
|
||||
}
|
||||
|
||||
public function convert(iterable $spans): array
|
||||
{
|
||||
$aggregate = [];
|
||||
foreach ($spans as $span) {
|
||||
$aggregate[] = $this->convertSpan($span);
|
||||
}
|
||||
|
||||
return $aggregate;
|
||||
}
|
||||
|
||||
private function convertSpan(SpanDataInterface $span): array
|
||||
{
|
||||
$spanParent = $span->getParentContext();
|
||||
|
||||
$startTimestamp = TimeUtil::nanosToMillis($span->getStartEpochNanos());
|
||||
$endTimestamp = TimeUtil::nanosToMillis($span->getEndEpochNanos());
|
||||
|
||||
$serviceName = $span->getResource()->getAttributes()->get(ResourceAttributes::SERVICE_NAME)
|
||||
??
|
||||
$this->defaultServiceName;
|
||||
|
||||
$row = [
|
||||
'id' => $span->getSpanId(),
|
||||
'trace.id' => $span->getTraceId(),
|
||||
'attributes' => [
|
||||
'name' => $span->getName(),
|
||||
'service.name' => $serviceName,
|
||||
'parent.id' => $spanParent->isValid() ? $spanParent->getSpanId() : null,
|
||||
'timestamp' => $startTimestamp,
|
||||
'duration.ms' => (float) $endTimestamp - $startTimestamp,
|
||||
self::STATUS_CODE_TAG_KEY => $span->getStatus()->getCode(),
|
||||
self::STATUS_DESCRIPTION_TAG_KEY => $span->getStatus()->getDescription(),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($span->getAttributes() as $k => $v) {
|
||||
$row['attributes'][$k] = $v;
|
||||
}
|
||||
|
||||
foreach ($span->getResource()->getAttributes() as $k => $v) {
|
||||
$row['attributes'][$k] = $v;
|
||||
}
|
||||
foreach ($span->getInstrumentationScope()->getAttributes() as $k => $v) {
|
||||
$row['attributes'][$k] = $v;
|
||||
}
|
||||
|
||||
$droppedAttributes = $span->getAttributes()->getDroppedAttributesCount()
|
||||
+ $span->getInstrumentationScope()->getAttributes()->getDroppedAttributesCount()
|
||||
+ $span->getResource()->getAttributes()->getDroppedAttributesCount();
|
||||
|
||||
if ($droppedAttributes > 0) {
|
||||
$row['attributes'][self::KEY_DROPPED_ATTRIBUTES_COUNT] = $droppedAttributes;
|
||||
}
|
||||
|
||||
/*
|
||||
foreach ($span->getEvents() as $event) {
|
||||
if (!array_key_exists('annotations', $row)) {
|
||||
$row['annotations'] = [];
|
||||
}
|
||||
$row['annotations'][] = [
|
||||
'timestamp' => (int) ($event->getTimestamp() / 1e6), // RealtimeClock in milliseconds
|
||||
'value' => $event->getName(),
|
||||
];
|
||||
}
|
||||
*/
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Contrib\Newrelic;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
|
||||
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanExporter\SpanExporterFactoryInterface;
|
||||
use OpenTelemetry\SDK\Trace\SpanExporterInterface;
|
||||
|
||||
class SpanExporterFactory implements SpanExporterFactoryInterface
|
||||
{
|
||||
public function create(): SpanExporterInterface
|
||||
{
|
||||
$licenseKey = Configuration::getString('NEW_RELIC_INSERT_KEY');
|
||||
$endpointUrl = Configuration::getString('NEW_RELIC_ENDPOINT', 'https://trace-api.newrelic.com/trace/v1');
|
||||
$dataFormatVersion = Exporter::DATA_FORMAT_VERSION_DEFAULT;
|
||||
|
||||
$transport = PsrTransportFactory::discover()->create($endpointUrl, 'application/json', [
|
||||
'Api-Key' => $licenseKey,
|
||||
'Data-Format' => 'newrelic',
|
||||
'Data-Format-Version' => $dataFormatVersion,
|
||||
]);
|
||||
|
||||
return new Exporter($transport, $endpointUrl);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
\OpenTelemetry\SDK\Registry::registerSpanExporterFactory('newrelic', \OpenTelemetry\Contrib\Newrelic\SpanExporterFactory::class);
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
{
|
||||
"name": "open-telemetry/exporter-newrelic",
|
||||
"description": "New Relic exporter for OpenTelemetry PHP.",
|
||||
"keywords": ["opentelemetry", "otel", "tracing", "exporter", "newrelic"],
|
||||
"type": "library",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "opentelemetry-php contributors",
|
||||
"homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"open-telemetry/sdk": "^1.0",
|
||||
"php-http/async-client-implementation": "^1.0",
|
||||
"php-http/discovery": "^1.14",
|
||||
"psr/http-factory-implementation": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"OpenTelemetry\\Contrib\\Newrelic\\": "."
|
||||
},
|
||||
"files": [
|
||||
"_register.php"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Contrib\ZipkinToNewrelic;
|
||||
|
||||
use JsonException;
|
||||
use OpenTelemetry\API\Behavior\LogsMessagesTrait;
|
||||
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\Future\FutureInterface;
|
||||
use OpenTelemetry\SDK\Trace\Behavior\UsesSpanConverterTrait;
|
||||
use OpenTelemetry\SDK\Trace\SpanExporterInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class ZipkinExporter - implements the export interface for data transfer via Zipkin protocol
|
||||
* @package OpenTelemetry\Exporter
|
||||
*
|
||||
* This is an experimental, non-supported exporter.
|
||||
* It will send PHP Otel trace data end to end across the internet to a functional backend.
|
||||
* Needs a license key to connect. For a free account/key, go to: https://newrelic.com/signup/
|
||||
*/
|
||||
class Exporter implements SpanExporterInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
use UsesSpanConverterTrait;
|
||||
|
||||
private TransportInterface $transport;
|
||||
|
||||
public function __construct(
|
||||
TransportInterface $transport,
|
||||
SpanConverter $spanConverter = null
|
||||
) {
|
||||
$this->transport = $transport;
|
||||
$this->setSpanConverter($spanConverter ?? new SpanConverter());
|
||||
}
|
||||
|
||||
public static function create(
|
||||
string $endpointUrl,
|
||||
string $licenseKey
|
||||
): self {
|
||||
$transport = PsrTransportFactory::discover()->create($endpointUrl, 'application/json', [
|
||||
'Api-Key' => $licenseKey,
|
||||
'Data-Format' => 'zipkin',
|
||||
'Data-Format-Version' => '2',
|
||||
]);
|
||||
|
||||
return new self($transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function serializeTrace(iterable $spans): string
|
||||
{
|
||||
return json_encode(
|
||||
$this->getSpanConverter()->convert($spans),
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface
|
||||
{
|
||||
return $this->transport
|
||||
->send($this->serializeTrace($batch), $cancellation)
|
||||
->map(static fn (): bool => true)
|
||||
->catch(static function (Throwable $throwable): bool {
|
||||
self::logError('Export failure', ['exception' => $throwable]);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public function shutdown(?CancellationInterface $cancellation = null): bool
|
||||
{
|
||||
return $this->transport->shutdown($cancellation);
|
||||
}
|
||||
|
||||
public function forceFlush(?CancellationInterface $cancellation = null): bool
|
||||
{
|
||||
return $this->transport->forceFlush($cancellation);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
# OpenTelemetry Zipkin to New Relic Exporter
|
||||
|
||||
_Experimental_ New Relic exporter for OpenTelemetry, which uses the Zipkin protocol.
|
||||
|
||||
## Usage
|
||||
|
||||
See https://github.com/open-telemetry/opentelemetry-php/blob/main/examples/traces/exporters/zipkin_to_newrelic.php
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Contrib\ZipkinToNewrelic;
|
||||
|
||||
use function max;
|
||||
use OpenTelemetry\SDK\Common\Time\Util as TimeUtil;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanConverterInterface;
|
||||
use OpenTelemetry\SDK\Trace\SpanDataInterface;
|
||||
use OpenTelemetry\SemConv\ResourceAttributes;
|
||||
|
||||
class SpanConverter implements SpanConverterInterface
|
||||
{
|
||||
const STATUS_CODE_TAG_KEY = 'otel.status_code';
|
||||
const STATUS_DESCRIPTION_TAG_KEY = 'otel.status_description';
|
||||
|
||||
private string $defaultServiceName;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->defaultServiceName = ResourceInfoFactory::defaultResource()->getAttributes()->get(ResourceAttributes::SERVICE_NAME);
|
||||
}
|
||||
|
||||
private function sanitiseTagValue($value)
|
||||
{
|
||||
// Casting false to string makes an empty string
|
||||
if (is_bool($value)) {
|
||||
return $value ? 'true' : 'false';
|
||||
}
|
||||
|
||||
// Zipkin tags must be strings, but opentelemetry
|
||||
// accepts strings, booleans, numbers, and lists of each.
|
||||
if (is_array($value)) {
|
||||
return implode(',', array_map(fn ($value) => $this->sanitiseTagValue($value), $value));
|
||||
}
|
||||
|
||||
// Floats will lose precision if their string representation
|
||||
// is >=14 or >=17 digits, depending on PHP settings.
|
||||
// Can also throw E_RECOVERABLE_ERROR if $value is an object
|
||||
// without a __toString() method.
|
||||
// This is possible because OpenTelemetry\API\Trace\Span does not verify
|
||||
// setAttribute() $value input.
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
public function convert(iterable $spans): array
|
||||
{
|
||||
$aggregate = [];
|
||||
foreach ($spans as $span) {
|
||||
$aggregate[] = $this->convertSpan($span);
|
||||
}
|
||||
|
||||
return $aggregate;
|
||||
}
|
||||
|
||||
private function convertSpan(SpanDataInterface $span): array
|
||||
{
|
||||
$spanParent = $span->getParentContext();
|
||||
|
||||
$startTimestamp = TimeUtil::nanosToMicros($span->getStartEpochNanos());
|
||||
$endTimestamp = TimeUtil::nanosToMicros($span->getEndEpochNanos());
|
||||
|
||||
$serviceName = $span->getResource()->getAttributes()->get(ResourceAttributes::SERVICE_NAME)
|
||||
??
|
||||
$this->defaultServiceName;
|
||||
|
||||
$row = [
|
||||
'id' => $span->getSpanId(),
|
||||
'traceId' => $span->getTraceId(),
|
||||
'parentId' => $spanParent->isValid() ? $spanParent->getSpanId() : null,
|
||||
'localEndpoint' => [
|
||||
'serviceName' => $serviceName,
|
||||
],
|
||||
'name' => $span->getName(),
|
||||
'timestamp' => $startTimestamp,
|
||||
'duration' => max(1, $endTimestamp - $startTimestamp),
|
||||
'tags' => [
|
||||
self::STATUS_CODE_TAG_KEY => $span->getStatus()->getCode(),
|
||||
self::STATUS_DESCRIPTION_TAG_KEY => $span->getStatus()->getDescription(),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($span->getAttributes() as $k => $v) {
|
||||
$row['tags'][$k] = $this->sanitiseTagValue($v);
|
||||
}
|
||||
|
||||
foreach ($span->getResource()->getAttributes() as $k => $v) {
|
||||
$row['tags'][$k] = $this->sanitiseTagValue($v);
|
||||
}
|
||||
foreach ($span->getInstrumentationScope()->getAttributes() as $k => $v) {
|
||||
$row['tags'][$k] = $this->sanitiseTagValue($v);
|
||||
}
|
||||
|
||||
foreach ($span->getEvents() as $event) {
|
||||
if (!array_key_exists('annotations', $row)) {
|
||||
$row['annotations'] = [];
|
||||
}
|
||||
$row['annotations'][] = [
|
||||
'timestamp' => TimeUtil::nanosToMicros($event->getEpochNanos()),
|
||||
'value' => $event->getName(),
|
||||
];
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"name": "open-telemetry/exporter-zipkintonewrelic",
|
||||
"description": "Zipkin to New Relic exporter for OpenTelemetry PHP.",
|
||||
"keywords": ["opentelemetry", "otel", "tracing", "zipkin", "newrelic", "exporter", "contrib"],
|
||||
"type": "library",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "opentelemetry-php contributors",
|
||||
"homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"open-telemetry/sdk": "^1.0",
|
||||
"php-http/async-client-implementation": "^1.0",
|
||||
"php-http/discovery": "^1.14",
|
||||
"psr/http-factory-implementation": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"OpenTelemetry\\Contrib\\ZipkinToNewrelic\\": "."
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "open-telemetry/sdk-contrib",
|
||||
"description": "Vendor specific implementations for OpenTelemetry PHP API/SDK.",
|
||||
"keywords": ["opentelemetry", "otel", "metrics", "tracing", "logging", "apm", "otlp", "zipkin", "prometheus", "newrelic"],
|
||||
"keywords": ["opentelemetry", "otel", "metrics", "tracing", "logging", "apm", "otlp", "zipkin"],
|
||||
"type": "library",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
|
|
@ -33,7 +33,6 @@
|
|||
},
|
||||
"files": [
|
||||
"Grpc/_register.php",
|
||||
"Newrelic/_register.php",
|
||||
"Otlp/_register.php",
|
||||
"Zipkin/_register.php"
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ interface KnownValues
|
|||
public const VALUE_HTTP_NDJSON = 'http/ndjson';
|
||||
public const VALUE_OTLP = 'otlp';
|
||||
public const VALUE_ZIPKIN = 'zipkin';
|
||||
public const VALUE_NEWRELIC = 'newrelic';
|
||||
public const VALUE_PROMETHEUS = 'prometheus';
|
||||
public const VALUE_WITH_SAMPLED_TRACE = 'with_sampled_trace';
|
||||
public const VALUE_BATCH = 'batch';
|
||||
|
|
@ -142,7 +141,6 @@ interface KnownValues
|
|||
public const OTEL_TRACES_EXPORTER = [
|
||||
self::VALUE_OTLP,
|
||||
self::VALUE_ZIPKIN,
|
||||
self::VALUE_NEWRELIC,
|
||||
self::VALUE_NONE,
|
||||
];
|
||||
public const OTEL_METRICS_EXPORTER = [
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Contrib\Newrelic;
|
||||
|
||||
use OpenTelemetry\Contrib\Newrelic\Exporter;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use OpenTelemetry\Tests\Unit\SDK\Trace\SpanExporter\AbstractExporterTest;
|
||||
|
||||
/**
|
||||
* @covers OpenTelemetry\Contrib\Newrelic\Exporter
|
||||
*/
|
||||
class NewrelicExporterTest extends AbstractExporterTest
|
||||
{
|
||||
protected const LICENSE_KEY = 'abc123';
|
||||
|
||||
public function createExporterWithTransport(TransportInterface $transport): Exporter
|
||||
{
|
||||
return new Exporter(
|
||||
$transport,
|
||||
'http://endpoint.url'
|
||||
);
|
||||
}
|
||||
|
||||
public function getExporterClass(): string
|
||||
{
|
||||
return Exporter::class;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Contrib\Newrelic;
|
||||
|
||||
use OpenTelemetry\Contrib\Newrelic\SpanConverter;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Common\Attribute\AttributesInterface;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
|
||||
use OpenTelemetry\SDK\Trace\SpanDataInterface;
|
||||
use OpenTelemetry\SemConv\ResourceAttributes;
|
||||
use OpenTelemetry\Tests\Unit\SDK\Util\SpanData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers OpenTelemetry\Contrib\Newrelic\SpanConverter
|
||||
*/
|
||||
class NewrelicSpanConverterTest extends TestCase
|
||||
{
|
||||
public function test_should_convert_a_span_to_a_payload_for_newrelic(): void
|
||||
{
|
||||
$span = (new SpanData())
|
||||
->setName('guard.validate')
|
||||
->addAttribute('service', 'guard')
|
||||
->setResource(
|
||||
ResourceInfo::create(
|
||||
Attributes::create([
|
||||
'telemetry.sdk.name' => 'opentelemetry',
|
||||
'telemetry.sdk.language' => 'php',
|
||||
'telemetry.sdk.version' => 'dev',
|
||||
])
|
||||
)
|
||||
)
|
||||
->addEvent('validators.list', Attributes::create(['job' => 'stage.updateTime']), 1505855799433901068)
|
||||
->setHasEnded(true);
|
||||
|
||||
$converter = new SpanConverter();
|
||||
$row = $converter->convert([$span])[0];
|
||||
|
||||
$this->assertSame($span->getContext()->getSpanId(), $row['id']);
|
||||
$this->assertSame($span->getContext()->getTraceId(), $row['trace.id']);
|
||||
|
||||
$this->assertSame(
|
||||
ResourceInfoFactory::defaultResource()->getAttributes()->get(ResourceAttributes::SERVICE_NAME),
|
||||
$row['attributes']['service.name']
|
||||
);
|
||||
$this->assertSame($span->getName(), $row['attributes']['name']);
|
||||
$this->assertNull($row['attributes']['parent.id']);
|
||||
$this->assertSame(1505855794194, $row['attributes']['timestamp']);
|
||||
$this->assertIsFloat($row['attributes']['duration.ms']);
|
||||
$this->assertSame(5271.0, $row['attributes']['duration.ms']);
|
||||
|
||||
$attribute = $span->getAttributes()->get('service');
|
||||
$this->assertEquals($attribute, $row['attributes']['service']);
|
||||
|
||||
$this->assertSame('opentelemetry', $row['attributes']['telemetry.sdk.name']);
|
||||
$this->assertSame('php', $row['attributes']['telemetry.sdk.language']);
|
||||
$this->assertSame('dev', $row['attributes']['telemetry.sdk.version']);
|
||||
}
|
||||
|
||||
public function test_attributes_maintain_types(): void
|
||||
{
|
||||
$listOfStrings = ['string-1', 'string-2'];
|
||||
$listOfNumbers = [1, 2, 3, 3.1415, 42];
|
||||
$listOfBooleans = [true, true, false, true];
|
||||
$listOfRandoms = [true, [1, 2, 3], false, 'string-1', 3.1415];
|
||||
|
||||
$span = (new SpanData())
|
||||
->setName('attributes.test')
|
||||
->addAttribute('string', 'string')
|
||||
->addAttribute('integer-1', 1024)
|
||||
->addAttribute('integer-2', 0)
|
||||
->addAttribute('float', 1.2345)
|
||||
->addAttribute('boolean-1', true)
|
||||
->addAttribute('boolean-2', false)
|
||||
->addAttribute('list-of-strings', $listOfStrings)
|
||||
->addAttribute('list-of-numbers', $listOfNumbers)
|
||||
->addAttribute('list-of-booleans', $listOfBooleans)
|
||||
->addAttribute('list-of-random', $listOfRandoms);
|
||||
|
||||
$attributes = (new SpanConverter())->convert([$span])[0]['attributes'];
|
||||
|
||||
// Check that we can convert all attributes to tags
|
||||
$this->assertCount(17, $attributes);
|
||||
|
||||
// Attributes destined for Newrelic must be key/value pairs
|
||||
|
||||
$this->assertSame('string', $attributes['string']);
|
||||
$this->assertSame(1024, $attributes['integer-1']);
|
||||
$this->assertSame(0, $attributes['integer-2']);
|
||||
$this->assertSame(1.2345, $attributes['float']);
|
||||
$this->assertTrue($attributes['boolean-1']);
|
||||
$this->assertFalse($attributes['boolean-2']);
|
||||
|
||||
// Lists are accepted
|
||||
$this->assertSame($listOfStrings, $attributes['list-of-strings']);
|
||||
$this->assertSame($listOfNumbers, $attributes['list-of-numbers']);
|
||||
$this->assertSame($listOfBooleans, $attributes['list-of-booleans']);
|
||||
|
||||
// This currently works, but OpenTelemetry\Trace\Span should stop arrays
|
||||
// containing multiple value types from being passed to the Exporter.
|
||||
$this->assertSame($listOfRandoms, $attributes['list-of-random']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider droppedProvider
|
||||
*/
|
||||
public function test_displays_non_zero_dropped_counts(int $dropped, bool $expected): void
|
||||
{
|
||||
$attributes = $this->createMock(AttributesInterface::class);
|
||||
$attributes->method('getDroppedAttributesCount')->willReturn($dropped);
|
||||
$spanData = $this->createMock(SpanDataInterface::class);
|
||||
$spanData->method('getAttributes')->willReturn($attributes);
|
||||
|
||||
$converter = new SpanConverter();
|
||||
$converted = $converter->convert([$spanData])[0];
|
||||
|
||||
if ($expected) {
|
||||
$this->assertArrayHasKey(SpanConverter::KEY_DROPPED_ATTRIBUTES_COUNT, $converted['attributes']);
|
||||
} else {
|
||||
$this->assertArrayNotHasKey(SpanConverter::KEY_DROPPED_ATTRIBUTES_COUNT, $converted['attributes']);
|
||||
}
|
||||
}
|
||||
|
||||
public static function droppedProvider(): array
|
||||
{
|
||||
return [
|
||||
'no dropped' => [0, false],
|
||||
'some dropped' => [1, true],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Contrib\ZipkinToNewrelic;
|
||||
|
||||
use OpenTelemetry\Contrib\ZipkinToNewrelic\Exporter;
|
||||
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use OpenTelemetry\Tests\Unit\SDK\Trace\SpanExporter\AbstractExporterTest;
|
||||
|
||||
/**
|
||||
* @covers OpenTelemetry\Contrib\ZipkinToNewrelic\Exporter
|
||||
*/
|
||||
class ZipkinToNewrelicExporterTest extends AbstractExporterTest
|
||||
{
|
||||
protected const LICENSE_KEY = 'abc123';
|
||||
|
||||
/**
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
*/
|
||||
public function createExporterWithTransport(TransportInterface $transport): Exporter
|
||||
{
|
||||
return new Exporter(
|
||||
$transport
|
||||
);
|
||||
}
|
||||
|
||||
public function getExporterClass(): string
|
||||
{
|
||||
return Exporter::class;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Contrib\ZipkinToNewrelic;
|
||||
|
||||
use function implode;
|
||||
use OpenTelemetry\Contrib\ZipkinToNewrelic\SpanConverter;
|
||||
use OpenTelemetry\SDK\Common\Attribute\Attributes;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfo;
|
||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
|
||||
use OpenTelemetry\SemConv\ResourceAttributes;
|
||||
use OpenTelemetry\Tests\Unit\SDK\Util\SpanData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers OpenTelemetry\Contrib\ZipkinToNewrelic\SpanConverter
|
||||
*/
|
||||
class ZipkinToNewrelicSpanConverterTest extends TestCase
|
||||
{
|
||||
public function test_should_convert_a_span_to_a_payload_for_zipkin(): void
|
||||
{
|
||||
$span = (new SpanData())
|
||||
->setName('guard.validate')
|
||||
->addAttribute('service', 'guard')
|
||||
->setResource(
|
||||
ResourceInfo::create(
|
||||
Attributes::create([
|
||||
'telemetry.sdk.name' => 'opentelemetry',
|
||||
'telemetry.sdk.language' => 'php',
|
||||
'telemetry.sdk.version' => 'dev',
|
||||
])
|
||||
)
|
||||
)
|
||||
->addEvent('validators.list', Attributes::create(['job' => 'stage.updateTime']), 1505855799433901068)
|
||||
->setHasEnded(true);
|
||||
|
||||
$converter = new SpanConverter();
|
||||
$row = $converter->convert([$span])[0];
|
||||
|
||||
$this->assertSame($span->getContext()->getSpanId(), $row['id']);
|
||||
$this->assertSame($span->getContext()->getTraceId(), $row['traceId']);
|
||||
|
||||
$this->assertSame(
|
||||
ResourceInfoFactory::defaultResource()->getAttributes()->get(ResourceAttributes::SERVICE_NAME),
|
||||
$row['localEndpoint']['serviceName']
|
||||
);
|
||||
$this->assertSame($span->getName(), $row['name']);
|
||||
|
||||
$this->assertSame(1505855794194009, $row['timestamp']);
|
||||
$this->assertSame(5271717, $row['duration']);
|
||||
|
||||
$this->assertCount(6, $row['tags']);
|
||||
|
||||
$attribute = $span->getAttributes()->get('service');
|
||||
$this->assertSame($attribute, $row['tags']['service']);
|
||||
|
||||
$this->assertSame('opentelemetry', $row['tags']['telemetry.sdk.name']);
|
||||
$this->assertSame('php', $row['tags']['telemetry.sdk.language']);
|
||||
$this->assertSame('dev', $row['tags']['telemetry.sdk.version']);
|
||||
|
||||
$this->assertCount(1, $row['annotations']);
|
||||
[$annotation] = $row['annotations'];
|
||||
$this->assertSame('validators.list', $annotation['value']);
|
||||
$this->assertSame(1505855799433901, $annotation['timestamp']);
|
||||
}
|
||||
|
||||
public function test_tags_are_coerced_correctly_to_strings(): void
|
||||
{
|
||||
$listOfStrings = ['string-1', 'string-2'];
|
||||
$listOfNumbers = [1, 2, 3, 3.1415, 42];
|
||||
$listOfBooleans = [true, true, false, true];
|
||||
$listOfRandoms = [true, [1, 2, 3], false, 'string-1', 3.1415];
|
||||
|
||||
$span = (new SpanData())
|
||||
->setName('tags.test')
|
||||
->addAttribute('string', 'string')
|
||||
->addAttribute('integer-1', 1024)
|
||||
->addAttribute('integer-2', 0)
|
||||
->addAttribute('float', '1.2345')
|
||||
->addAttribute('boolean-1', true)
|
||||
->addAttribute('boolean-2', false)
|
||||
->addAttribute('list-of-strings', $listOfStrings)
|
||||
->addAttribute('list-of-numbers', $listOfNumbers)
|
||||
->addAttribute('list-of-booleans', $listOfBooleans)
|
||||
->addAttribute('list-of-random', $listOfRandoms);
|
||||
|
||||
$tags = (new SpanConverter())->convert([$span])[0]['tags'];
|
||||
|
||||
// Check that we can convert all attributes to tags
|
||||
$this->assertCount(12, $tags);
|
||||
|
||||
// Tags destined for Zipkin must be pairs of strings
|
||||
foreach ($tags as $tagKey => $tagValue) {
|
||||
$this->assertIsString($tagKey);
|
||||
$this->assertIsString($tagValue);
|
||||
}
|
||||
|
||||
$this->assertSame('string', $tags['string']);
|
||||
$this->assertSame('1024', $tags['integer-1']);
|
||||
$this->assertSame('0', $tags['integer-2']);
|
||||
$this->assertSame('1.2345', $tags['float']);
|
||||
$this->assertSame('true', $tags['boolean-1']);
|
||||
$this->assertSame('false', $tags['boolean-2']);
|
||||
|
||||
// Lists must be casted to strings and joined with a separator
|
||||
$this->assertSame(implode(',', $listOfStrings), $tags['list-of-strings']);
|
||||
$this->assertSame(implode(',', $listOfNumbers), $tags['list-of-numbers']);
|
||||
$this->assertSame('true,true,false,true', $tags['list-of-booleans']);
|
||||
|
||||
// This currently works, but OpenTelemetry\Trace\Span should stop arrays
|
||||
// containing multiple value types from being passed to the Exporter.
|
||||
$this->assertSame('true,1,2,3,false,string-1,3.1415', $tags['list-of-random']);
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,6 @@ class FactoryRegistryTest extends TestCase
|
|||
return [
|
||||
['otlp'],
|
||||
['zipkin'],
|
||||
['newrelic'],
|
||||
['console'],
|
||||
['memory'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -107,14 +107,12 @@ class ExporterFactoryTest extends TestCase
|
|||
public function invalidEnvProvider(): array
|
||||
{
|
||||
return [
|
||||
'newrelic' => ['newrelic'],
|
||||
'zipkintonewrelic' => ['zipkintonewrelic'],
|
||||
'otlp+invalid protocol' => [
|
||||
'otlp',
|
||||
['OTEL_EXPORTER_OTLP_PROTOCOL' => 'foo'],
|
||||
],
|
||||
'unknown exporter' => ['foo'],
|
||||
'multiple exporters' => ['newrelic,zipkin'],
|
||||
'multiple exporters' => ['console,zipkin'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue