Skip to content

Commit

Permalink
refactor otlp exporter (#838)
Browse files Browse the repository at this point in the history
* merge otlp exporters
continuing on from Nevay's work, this removes the individual OtlpHttp and OtlpGrpc exporters, and replaces with
Otlp\Exporter using a transport to manage grpc and http/protobuf complexity.

* tidy

* use mockery overload instead of prototype clone

* making all smoke-test examples work

* removing startBatch
verified that the call attributes have the same values when using TraceServiceClient

* tidy

* tidy

* Revert "use mockery overload instead of prototype clone"

This reverts commit bbb685b.
Mocking proto-generated files segfaults with ext-protobuf (which is harder to diagnose when running in a child process, which
was required for fancy mockery mocking of "new". So, back to the prototype approach, and skip the tests if ext-protobuf enabled.

* tests without mocking protobuf

* test

* typo

* reverting FromConnectionStringInterface

* grpc headers

* revert to dumb transports, handle multiple protocols

* tidy, adding initial otlp json support

* self-review

* linting

* remove redundant interface

* Revert "remove redundant interface"

This reverts commit 350d40c.

* fix getFloat

Co-authored-by: Tobias Bachert <git@b-privat.de>

* move withSignal into otlp-specific interface

* moving exporter/transport env handling into a new factory

* linting

* remove unused code

* tidy

* moving OtlpHttp into Otlp

* removing OtlpTransportFactoryInterface

* fix style

* fixing psalm error

* addressing review feedback

* replacing removed code

* fixing example

Co-authored-by: Tobias Bachert <git@b-privat.de>
  • Loading branch information
brettmc and Nevay committed Nov 2, 2022
1 parent ba98992 commit 0b43fac
Show file tree
Hide file tree
Showing 64 changed files with 985 additions and 1,210 deletions.
6 changes: 2 additions & 4 deletions .gitsplit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ splits:
- 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-common.git"
- prefix: "src/Contrib/OtlpGrpc"
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-otlp.git"
- prefix: "src/Contrib/Grpc"
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-otlp-grpc.git"
- prefix: "src/Contrib/OtlpHttp"
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-otlp-http.git"
- prefix: "src/Contrib/Zipkin"
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/exporter-zipkin.git"
- prefix: "src/Contrib/ZipkinToNewrelic"
Expand Down
10 changes: 3 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ phpmetrics: ## Run php metrics
smoke-test-examples: smoke-test-isolated-examples smoke-test-exporter-examples smoke-test-collector-integration smoke-test-prometheus-example ## Run smoke test examples
smoke-test-isolated-examples: ## Run smoke test isolated examples
$(DC_RUN_PHP) php ./examples/traces/getting_started.php
$(DC_RUN_PHP) php ./examples/traces/features/always_off_trace_example.php
$(DC_RUN_PHP) php ./examples/traces/features/batch_exporting.php
$(DC_RUN_PHP) php ./examples/traces/features/concurrent_spans.php
$(DC_RUN_PHP) php ./examples/traces/features/configuration_from_environment.php
$(DC_RUN_PHP) php ./examples/traces/features/creating_a_new_trace_in_the_same_process.php
$(DC_RUN_PHP) php ./examples/traces/features/parent_span_example.php
$(DC_RUN_PHP) php ./examples/traces/features/resource_detectors.php
$(DC_RUN_PHP) php ./examples/traces/features/span_resources.php
$(DC_RUN_PHP) php ./examples/traces/troubleshooting/air_gapped_trace_debugging.php
Expand All @@ -61,23 +59,21 @@ smoke-test-exporter-examples: FORCE ## Run (some) exporter smoke test examples
# Note this does not include every exporter at the moment
$(DOCKER_COMPOSE) up -d --remove-orphans
$(DC_RUN_PHP) php ./examples/traces/features/exporters/zipkin.php
$(DC_RUN_PHP) php ./examples/traces/features/always_off_trace_example.php
$(DC_RUN_PHP) php ./examples/traces/features/exporters/jaeger.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/features/exporters/newrelic.php
$(DOCKER_COMPOSE) run -e NEW_RELIC_ENDPOINT -e NEW_RELIC_INSERT_KEY --rm php php ./examples/traces/features/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
# This is slow because it's building the image from scratch (and parts of that, like installing the gRPC extension, are slow)
# This can be sped up by switching to the pre-built images hosted on ghcr.io (and referenced in other docker-compose**.yaml files)
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml run --rm php php ./examples/traces/features/exporters/otlp_grpc.php
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml run --rm php php ./examples/traces/features/exporters/otlp.php
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml run --rm php php ./examples/traces/features/exporters/otlp_http.php
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml stop
smoke-test-collector-metrics-integration:
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml up -d --force-recreate collector
COMPOSE_IGNORE_ORPHANS=TRUE $(DOCKER_COMPOSE) -f docker-compose.yaml run --rm php php ./examples/metrics/features/exporters/otlp.php
COMPOSE_IGNORE_ORPHANS=TRUE $(DOCKER_COMPOSE) -f docker-compose.yaml run --rm php php ./examples/metrics/features/exporters/otlp_http.php
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml logs collector
$(DOCKER_COMPOSE) -f docker-compose.collector.yaml stop collector
smoke-test-prometheus-example: metrics-prometheus-example stop-prometheus
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"require": {
"php": "^7.4 || ^8.0",
"ext-json": "*",
"cloudevents/sdk-php": "^v1.0.1",
"google/protobuf": "^3.3.0",
"grpc/grpc": "^1.30",
"packaged/thrift": "^0.15.0",
Expand Down Expand Up @@ -68,7 +69,8 @@
},
"autoload-dev": {
"psr-4": {
"OpenTelemetry\\Tests\\": "tests/"
"OpenTelemetry\\Tests\\": "tests/",
"OpenTelemetry\\Example\\": "examples/src/"
}
},
"require-dev": {
Expand Down Expand Up @@ -96,7 +98,7 @@
"psalm/plugin-mockery": "^0.9",
"psalm/plugin-phpunit": "^0.16",
"psalm/psalm": "^4.0",
"qossmic/deptrac-shim": "^0.22.1",
"qossmic/deptrac-shim": "^0.24",
"rector/rector": "^0.13.7",
"symfony/http-client": "^5.2"
},
Expand Down
1 change: 1 addition & 0 deletions deptrac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ deptrac:
Contrib:
- +SDK
- +OtelProto
- Grpc
- Prometheus
- Thrift
- JaegerThrift
Expand Down
4 changes: 1 addition & 3 deletions docker-compose.collector.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
version: '3.7'
services:
php:
build:
context: .
dockerfile: docker/Dockerfile
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-7.4}
volumes:
- ./:/usr/src/myapp
depends_on:
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions; \
zip \
pcntl \
grpc \
runkit7-alpha \
protobuf \
sockets \
intl \
@composer \
Expand Down
75 changes: 0 additions & 75 deletions examples/metrics/features/exporters/otlp.php

This file was deleted.

26 changes: 26 additions & 0 deletions examples/metrics/features/exporters/otlp_grpc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

require __DIR__ . '/../../../../vendor/autoload.php';

use OpenTelemetry\API\Common\Signal\Signals;
use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory;
use OpenTelemetry\Contrib\Otlp\MetricExporter;
use OpenTelemetry\Example\ExampleMetricsGenerator;
use OpenTelemetry\SDK\Common\Time\ClockFactory;
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;

\OpenTelemetry\SDK\Common\Log\LoggerHolder::set(new \Monolog\Logger('grpc', [new \Monolog\Handler\StreamHandler('php://stderr')]));

$clock = ClockFactory::getDefault();

$reader = new ExportingReader(
new MetricExporter(
(new GrpcTransportFactory())->withSignal(Signals::METRICS)->create('http://collector:4317')
),
$clock
);

$metricsGenerator = new ExampleMetricsGenerator($reader, $clock);
$metricsGenerator->generate();
22 changes: 22 additions & 0 deletions examples/metrics/features/exporters/otlp_http.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

require __DIR__ . '/../../../../vendor/autoload.php';

use OpenTelemetry\Contrib\Otlp\MetricExporter;
use OpenTelemetry\Example\ExampleMetricsGenerator;
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
use OpenTelemetry\SDK\Common\Time\ClockFactory;
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;

$clock = ClockFactory::getDefault();
$reader = new ExportingReader(
new MetricExporter(
PsrTransportFactory::discover()->create('http://collector:4318/v1/metrics', 'application/json')
),
$clock
);

$metricsGenerator = new ExampleMetricsGenerator($reader, $clock);
$metricsGenerator->generate();
22 changes: 22 additions & 0 deletions examples/metrics/features/exporters/stream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

require __DIR__ . '/../../../../vendor/autoload.php';

use OpenTelemetry\Contrib\Otlp\MetricExporter;
use OpenTelemetry\Example\ExampleMetricsGenerator;
use OpenTelemetry\SDK\Common\Export\Stream\StreamTransport;
use OpenTelemetry\SDK\Common\Time\ClockFactory;
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;

$clock = ClockFactory::getDefault();
$reader = new ExportingReader(
new MetricExporter(
new StreamTransport(STDOUT, 'application/x-ndjson')
),
$clock
);

$metricsGenerator = new ExampleMetricsGenerator($reader, $clock);
$metricsGenerator->generate();
79 changes: 79 additions & 0 deletions examples/src/ExampleMetricsGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\Example;

use OpenTelemetry\API\Metrics\ObserverInterface;
use OpenTelemetry\SDK\Common\Attribute\Attributes;
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
use OpenTelemetry\SDK\Common\Time\ClockInterface;
use OpenTelemetry\SDK\Metrics\Exemplar\ExemplarFilter\WithSampledTraceExemplarFilter;
use OpenTelemetry\SDK\Metrics\MeterProvider;
use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;
use OpenTelemetry\SDK\Metrics\StalenessHandler\ImmediateStalenessHandlerFactory;
use OpenTelemetry\SDK\Metrics\View\CriteriaViewRegistry;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;

class ExampleMetricsGenerator
{
private ExportingReader $reader;
private ClockInterface $clock;

public function __construct(ExportingReader $reader, ClockInterface $clock)
{
$this->reader = $reader;
$this->clock = $clock;
}

public function generate(): void
{
$meterProvider = new MeterProvider(
null,
ResourceInfoFactory::defaultResource(),
$this->clock,
Attributes::factory(),
new InstrumentationScopeFactory(Attributes::factory()),
[$this->reader],
new CriteriaViewRegistry(),
new WithSampledTraceExemplarFilter(),
new ImmediateStalenessHandlerFactory(),
);

$meter = $meterProvider->getMeter('io.opentelemetry.contrib.php');
$meter
->createObservableUpDownCounter('process.memory.usage', 'By', 'The amount of physical memory in use.')
->observe(static function (ObserverInterface $observer): void {
$observer->observe(memory_get_usage(true));
});

$serverDuration = $meter
->createHistogram('http.server.duration', 'ms', 'measures the duration inbound HTTP requests');

// During the time range (T0, T1]:
$serverDuration->record(50, ['http.method' => 'GET', 'http.status_code' => 200]);
$serverDuration->record(100, ['http.method' => 'GET', 'http.status_code' => 200]);
$serverDuration->record(1, ['http.method' => 'GET', 'http.status_code' => 500]);
$this->reader->collect();

// During the time range (T1, T2]:
$this->reader->collect();

// During the time range (T2, T3]:
$serverDuration->record(5, ['http.method' => 'GET', 'http.status_code' => 500]);
$serverDuration->record(2, ['http.method' => 'GET', 'http.status_code' => 500]);
$this->reader->collect();

// During the time range (T3, T4]:
$serverDuration->record(100, ['http.method' => 'GET', 'http.status_code' => 200]);
$this->reader->collect();

// During the time range (T4, T5]:
$serverDuration->record(100, ['http.method' => 'GET', 'http.status_code' => 200]);
$serverDuration->record(30, ['http.method' => 'GET', 'http.status_code' => 200]);
$serverDuration->record(50, ['http.method' => 'GET', 'http.status_code' => 200]);
$this->reader->collect();

$meterProvider->shutdown();
}
}
3 changes: 2 additions & 1 deletion examples/traces/features/batch_exporting.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);
require __DIR__ . '/../../../vendor/autoload.php';

use OpenTelemetry\SDK\Common\Time\ClockFactory;
use OpenTelemetry\SDK\Trace\SpanExporter\ConsoleSpanExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
Expand All @@ -15,7 +16,7 @@
$tracerProvider = new TracerProvider(
new BatchSpanProcessor(
new ConsoleSpanExporter(),
null,
ClockFactory::getDefault(),
2048, //max spans to queue before sending to exporter
$delayMillis, //batch delay milliseconds
)
Expand Down
3 changes: 2 additions & 1 deletion examples/traces/features/exporters/jaeger.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');

$rootSpan = $tracer->spanBuilder('root')->startSpan();
$rootSpan->activate();
$scope = $rootSpan->activate();

for ($i = 0; $i < 5; $i++) {
// start a span, register some events
Expand Down Expand Up @@ -51,6 +51,7 @@

$span->end();
}
$scope->detach();
$rootSpan->end();
echo PHP_EOL . 'Jaeger example complete! See the results at http://localhost:16686/';

Expand Down
2 changes: 1 addition & 1 deletion examples/traces/features/exporters/newrelic.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// 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.';
echo PHP_EOL . 'NEW_RELIC_INSERT_KEY not found in environment. Newrelic Example tracing is not enabled.' . PHP_EOL;

return;
}
Expand Down
Loading

0 comments on commit 0b43fac

Please sign in to comment.