Skip to content

Commit

Permalink
sdk autoloading (#854)
Browse files Browse the repository at this point in the history
* sdk autoloading
* use instrumentation initializers
* basic sdk + autoloading documentation
* exampler filter from config
* configuration default types
  • Loading branch information
brettmc authored Nov 13, 2022
1 parent f083b10 commit 116e46d
Show file tree
Hide file tree
Showing 28 changed files with 625 additions and 22 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"src/Context/fiber/initialize_fiber_handler.php",
"src/API/Trace/functions.php",
"src/SDK/Common/Dev/Compatibility/_load.php",
"src/SDK/Common/Util/functions.php"
"src/SDK/Common/Util/functions.php",
"src/SDK/_autoload.php"
]
},
"autoload-dev": {
Expand Down Expand Up @@ -96,7 +97,7 @@
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.3",
"psalm/plugin-mockery": "^0.9",
"psalm/plugin-phpunit": "^0.16",
"psalm/plugin-phpunit": "^0.18",
"psalm/psalm": "^4.0",
"qossmic/deptrac-shim": "^0.24",
"rector/rector": "^0.13.7",
Expand Down
6 changes: 6 additions & 0 deletions deptrac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ deptrac:
collectors:
- type: className
regex: ^OpenTelemetry\\Contrib\\*
- name: Extension
collectors:
- type: className
regex: ^OpenTelemetry\\Extension\\*
- name: OtelProto
collectors:
- type: className
Expand Down Expand Up @@ -110,6 +114,8 @@ deptrac:
- Thrift
- JaegerThrift
- Swoole
Extension:
- +API
OtelProto:
- GoogleProtobuf
- Grpc
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ services:
environment:
XDEBUG_MODE: ${XDEBUG_MODE:-off}
XDEBUG_CONFIG: ${XDEBUG_CONFIG:-''}
PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-''}
zipkin:
image: openzipkin/zipkin-slim
ports:
Expand Down
18 changes: 18 additions & 0 deletions examples/autoload_sdk.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

putenv('OTEL_PHP_AUTOLOAD_ENABLED=true');
putenv('OTEL_TRACES_EXPORTER=otlp');
putenv('OTEL_EXPORTER_OTLP_PROTOCOL=grpc');
putenv('OTEL_METRICS_EXPORTER=otlp');
putenv('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=grpc');
putenv('OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317');
putenv('OTEL_PHP_TRACES_PROCESSOR=batch');

// Composer autoloader will execute SDK/_autoload.php which will register global instrumentation from environment configuration
require dirname(__DIR__) . '/vendor/autoload.php';

$instrumentation = new \OpenTelemetry\API\Common\Instrumentation\CachedInstrumentation('demo');

$instrumentation->tracer()->spanBuilder('root')->startSpan()->end();
7 changes: 7 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\CodeQuality\Rector\Array_\CallableThisArrayToAnonymousFunctionRector;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Set\ValueObject\SetList;
Expand All @@ -17,4 +18,10 @@
SetList::PHP_74,
SetList::CODE_QUALITY,
]);
$rectorConfig->skip([
CallableThisArrayToAnonymousFunctionRector::class => [
__DIR__ . '/src/SDK/SdkBuilder.php',
__DIR__ . '/src/SDK/SdkAutoloader.php',
],
]);
};
12 changes: 12 additions & 0 deletions src/Contrib/Otlp/ContentTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\Contrib\Otlp;

interface ContentTypes
{
public const PROTOBUF = 'application/x-protobuf';
public const JSON = 'application/json';
public const NDJSON = 'application/x-ndjson';
}
65 changes: 65 additions & 0 deletions src/Contrib/Otlp/MetricExporterFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\Contrib\Otlp;

use OpenTelemetry\API\Common\Signal\Signals;
use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory;
use OpenTelemetry\SDK\Common\Configuration\Configuration;
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
use OpenTelemetry\SDK\Common\Export\TransportInterface;
use OpenTelemetry\SDK\Metrics\MetricExporterInterface;
use UnexpectedValueException;

class MetricExporterFactory
{
/**
* @psalm-suppress ArgumentTypeCoercion
*/
public function create(): MetricExporterInterface
{
$protocol = Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_PROTOCOL)
? Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_METRICS_PROTOCOL)
: Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_PROTOCOL);

return new MetricExporter($this->buildTransport($protocol));
}

private function buildTransport(string $protocol): TransportInterface
{
/**
* @todo (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#periodic-exporting-metricreader)
* - OTEL_METRIC_EXPORT_INTERVAL
* - OTEL_METRIC_EXPORT_TIMEOUT
*/
$endpoint = Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_ENDPOINT)
? Configuration::getString(Variables::OTEL_EXPORTER_OTLP_METRICS_ENDPOINT)
: Configuration::getString(Variables::OTEL_EXPORTER_OTLP_ENDPOINT);

$headers = Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_HEADERS)
? Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_METRICS_HEADERS)
: Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_HEADERS);
$headers += OtlpUtil::getUserAgentHeader();

switch ($protocol) {
case KnownValues::VALUE_GRPC:
return (new GrpcTransportFactory())->create(
$endpoint . OtlpUtil::method(Signals::METRICS),
ContentTypes::PROTOBUF,
$headers,
);
case KnownValues::VALUE_HTTP_PROTOBUF:
case KnownValues::VALUE_HTTP_JSON:
return PsrTransportFactory::discover()->create(
$endpoint,
Protocols::contentType($protocol),
$headers,
);
default:
throw new UnexpectedValueException('Unknown otlp protocol: ' . $protocol);
}
}
}
8 changes: 4 additions & 4 deletions src/Contrib/Otlp/Protocols.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ class Protocols
public const HTTP_JSON = KnownValues::VALUE_HTTP_JSON;
public const HTTP_NDJSON = KnownValues::VALUE_HTTP_NDJSON;
private const PROTOCOLS = [
self::GRPC => 'application/x-protobuf',
self::HTTP_PROTOBUF => 'application/x-protobuf',
self::HTTP_JSON => 'application/json',
self::HTTP_NDJSON => 'application/x-ndjson',
self::GRPC => ContentTypes::PROTOBUF,
self::HTTP_PROTOBUF => ContentTypes::PROTOBUF,
self::HTTP_JSON => ContentTypes::JSON,
self::HTTP_NDJSON => ContentTypes::NDJSON,
];

public static function validate(string $protocol): void
Expand Down
2 changes: 1 addition & 1 deletion src/Contrib/Zipkin/SpanConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private static function convertEventAttributesToJson(EventInterface $event): ?st
}

$attributesAsJson = json_encode($event->getAttributes()->toArray());
if (($attributesAsJson === false) || ($attributesAsJson === '')) {
if (($attributesAsJson === false)) {
return null;
}

Expand Down
10 changes: 5 additions & 5 deletions src/SDK/Common/Configuration/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static function getInt(string $key, int $default = null): int
);
}

public static function getString(string $key, string $default = ''): string
public static function getString(string $key, string $default = null): string
{
return (string) self::validateVariableValue(
CompositeResolver::instance()->resolve(
Expand All @@ -58,7 +58,7 @@ public static function getBoolean(string $key, bool $default = null): bool
);
}

public static function getMixed(string $key, string $default = null)
public static function getMixed(string $key, $default = null)
{
return self::validateVariableValue(
CompositeResolver::instance()->resolve(
Expand All @@ -68,7 +68,7 @@ public static function getMixed(string $key, string $default = null)
);
}

public static function getMap(string $key, string $default = null): array
public static function getMap(string $key, array $default = null): array
{
return MapParser::parse(
CompositeResolver::instance()->resolve(
Expand All @@ -78,7 +78,7 @@ public static function getMap(string $key, string $default = null): array
);
}

public static function getList(string $key, string $default = null): array
public static function getList(string $key, array $default = null): array
{
return ListParser::parse(
CompositeResolver::instance()->resolve(
Expand All @@ -98,7 +98,7 @@ public static function getEnum(string $key, string $default = null): string
);
}

public static function getFloat(string $key, string $default = null): float
public static function getFloat(string $key, float $default = null): float
{
return (float) self::validateVariableValue(
CompositeResolver::instance()->resolve(
Expand Down
1 change: 1 addition & 0 deletions src/SDK/Common/Configuration/Defaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,5 @@ interface Defaults
*/
public const OTEL_PHP_TRACES_PROCESSOR = 'batch';
public const OTEL_PHP_DETECTORS = 'all';
public const OTEL_PHP_AUTOLOAD_ENABLED = 'false';
}
1 change: 1 addition & 0 deletions src/SDK/Common/Configuration/KnownValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ interface KnownValues
self::VALUE_NOOP,
self::VALUE_NONE,
];
public const OTEL_PHP_AUTOLOAD_ENABLED = self::VALUES_BOOLEAN;
public const VALUE_DETECTORS_ENVIRONMENT = 'env';
public const VALUE_DETECTORS_HOST = 'host';
public const VALUE_DETECTORS_OS = 'os';
Expand Down
1 change: 1 addition & 0 deletions src/SDK/Common/Configuration/Variables.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,5 @@ interface Variables
*/
public const OTEL_PHP_TRACES_PROCESSOR = 'OTEL_PHP_TRACES_PROCESSOR';
public const OTEL_PHP_DETECTORS = 'OTEL_PHP_DETECTORS';
public const OTEL_PHP_AUTOLOAD_ENABLED = 'OTEL_PHP_AUTOLOAD_ENABLED';
}
11 changes: 10 additions & 1 deletion src/SDK/Metrics/MeterProviderBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
use OpenTelemetry\SDK\Common\Time\ClockFactory;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\WithSampledTraceExemplarFilter;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface;
use OpenTelemetry\SDK\Metrics\StalenessHandler\ImmediateStalenessHandlerFactory;
use OpenTelemetry\SDK\Metrics\View\CriteriaViewRegistry;
use OpenTelemetry\SDK\Resource\ResourceInfo;
Expand All @@ -18,6 +19,7 @@ class MeterProviderBuilder
// @var array<MetricReaderInterface>
private array $metricReaders = [];
private ?ResourceInfo $resource = null;
private ?ExemplarFilterInterface $exemplarFilter = null;

public function registerMetricReader(MetricReaderInterface $reader): self
{
Expand All @@ -33,6 +35,13 @@ public function setResource(ResourceInfo $resource): self
return $this;
}

public function setExemplarFilter(ExemplarFilterInterface $exemplarFilter): self
{
$this->exemplarFilter = $exemplarFilter;

return $this;
}

public function addReader(MetricReaderInterface $reader): self
{
$this->metricReaders[] = $reader;
Expand All @@ -53,7 +62,7 @@ public function build(): MeterProviderInterface
new InstrumentationScopeFactory(Attributes::factory()),
$this->metricReaders,
new CriteriaViewRegistry(),
new WithSampledTraceExemplarFilter(),
$this->exemplarFilter ?? new WithSampledTraceExemplarFilter(),
new ImmediateStalenessHandlerFactory(),
);
}
Expand Down
71 changes: 71 additions & 0 deletions src/SDK/Metrics/MeterProviderFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\SDK\Metrics;

use OpenTelemetry\SDK\Behavior\LogsMessagesTrait;
use OpenTelemetry\SDK\Common\Configuration\Configuration;
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\Common\Time\ClockFactory;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\AllExemplarFilter;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\NoneExemplarFilter;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\WithSampledTraceExemplarFilter;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilterInterface;
use OpenTelemetry\SDK\Metrics\MetricExporter\NoopMetricExporter;
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
use OpenTelemetry\SDK\Sdk;

class MeterProviderFactory
{
use LogsMessagesTrait;

private const KNOWN_EXPORTER_FACTORIES = [
KnownValues::VALUE_OTLP => '\OpenTelemetry\Contrib\Otlp\MetricExporterFactory',
];

public function create(): MeterProviderInterface
{
if (Sdk::isDisabled()) {
return new NoopMeterProvider();
}
$exporterName = Configuration::getString(Variables::OTEL_METRICS_EXPORTER);
if ($exporterName === KnownValues::VALUE_NONE) {
$exporter = new NoopMetricExporter();
} elseif (!array_key_exists($exporterName, self::KNOWN_EXPORTER_FACTORIES)) {
self::logError('Factory cannot create exporter: ' . $exporterName);
$exporter = new NoopMetricExporter();
} else {
$factoryClass = self::KNOWN_EXPORTER_FACTORIES[$exporterName];
$factory = new $factoryClass();
$exporter = $factory->create();
}
$reader = new ExportingReader($exporter, ClockFactory::getDefault());
$resource = ResourceInfoFactory::defaultResource();
$exemplarFilter = $this->createExemplarFilter(Configuration::getEnum(Variables::OTEL_METRICS_EXEMPLAR_FILTER));

return MeterProvider::builder()
->setResource($resource)
->addReader($reader)
->setExemplarFilter($exemplarFilter)
->build();
}

private function createExemplarFilter(string $name): ExemplarFilterInterface
{
switch ($name) {
case KnownValues::VALUE_WITH_SAMPLED_TRACE:
return new WithSampledTraceExemplarFilter();
case KnownValues::VALUE_ALL:
return new AllExemplarFilter();
case KnownValues::VALUE_NONE:
return new NoneExemplarFilter();
default:
self::logWarning('Unknown exemplar filter: ' . $name);

return new NoneExemplarFilter();
}
}
}
Loading

0 comments on commit 116e46d

Please sign in to comment.