依赖项在使用OpenTelemetry自动仪器化PHP时不会显示。

huangapple go评论76阅读模式
英文:

Dependencies do not show with OpenTelemetry automatic instrumentation for PHP

问题

我有一个非常简单的PHP堆栈,包括PHP + Otel自动化仪器 + Elastic APM + Prometheus。

我的堆栈从我的php应用程序中获取跟踪和度量信息。
我的跟踪被转发到弹性云,我在那里使用APM。我的度量信息发送到Prometheus。

我发现我的跟踪只部分工作,因为我看不到依赖关系。在这种情况下,依赖关系将是我的外部API。

我的堆栈的基础部分:(我没有附加php.ini和**.htaccess**文件,因为我认为这不相关。)

> index.php

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use DI\Container;
use GuzzleHttp\Client;

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

$container = new Container();

AppFactory::setContainer($container);
$app = AppFactory::create();

$app->get('/', function (Request $request, Response $response) {
    $response->getBody()->write('<h3>RANDOM API</h3>
    <p>O que você gostaria de ver?</p>
    <ul>
        <li>Random dogs? <a href="/dogs">Clique</li>
    </ul>');

    return $response;
});

$app->get('/healthcheck', function (Request $request, Response $response) {
    return $response->withStatus(204);
});

$app->get('/dogs', function (Request $request, Response $response) {
    $client = new Client();

    try {
        $apiResponse = $client->get('https://dog.ceo/api/breeds/image/random');
        $dogData = json_decode($apiResponse->getBody());

        $response->getBody()->write('<img src="' . $dogData->message . '" alt="random dog" style="max-width: 500px"/>');

    } catch (\Exception $e) {
        $response->getBody()->write($e->getMessage());
        return $response->withStatus(500);
    }

    return $response;
});

$app->run();

> Dockerfile

FROM php:8.2

RUN set -xe; \
    apt-get update; \
    apt-get -y install g++ zlib1g-dev build-essential zlib1g-dev gcc make autoconf m4 perl git; \
    curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \
    pecl install grpc && docker-php-ext-enable grpc; \
    pecl install opentelemetry-beta && docker-php-ext-enable opentelemetry

ENV COMPOSER_ALLOW_SUPERUSER 1
ENV OTEL_PHP_AUTOLOAD_ENABLED=true
ENV OTEL_SERVICE_NAME=your-service-name
ENV OTEL_TRACES_EXPORTER=console
ENV OTEL_METRICS_EXPORTER=otlp
ENV OTEL_EXPORTER_OTLP_PROTOCOL=grpc
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317
ENV OTEL_PROPAGATORS=baggage,tracecontext

WORKDIR /usr/src/myapp

COPY composer.json composer.lock* /usr/src/myapp/

RUN composer install --no-dev --no-scripts --no-autoloader

COPY . /usr/src/myapp

RUN composer dump-autoload --optimize --classmap-authoritative; \
    composer require slim/slim:^4 slim/psr7:^1; \
    composer require open-telemetry/exporter-otlp php-http/guzzle7-adapter; \
    composer require open-telemetry/transport-grpc; \
    composer config allow-plugins.php-http/discovery false; \
    composer require open-telemetry/sdk open-telemetry/opentelemetry-auto-slim; \
    php --ri opentelemetry

COPY php.ini /usr/local/etc/php/php.ini

CMD [ "php", "-S", "0.0.0.0:8080" ]

> docker-compose.yml

services:
  otel_collector:
    networks:
      - backend
    image: otel/opentelemetry-collector-contrib:latest
    volumes:
      - "./otel-collector-config.yml:/etc/otelcol/otel-collector-config.yml"
    command: --config /etc/otelcol/otel-collector-config.yml
    ports:
      - "14278:14278"
      - "65535:65535"
      - "55677:55677"
      - "12345:12345"
      - "4318:4318"
      - "4317:4317"    
      - "8889:8889"  
  prometheus:
    networks:
      - backend
    image: prom/prometheus:latest
    volumes:
      - "./prometheus.yml:/etc/prometheus/prometheus.yml"
    ports:
      - "9090:9090"

  app-php:
    build: ./php
    image: app-php
    ports:
      - 8083:8080
    container_name: app-php
    environment:
      OTEL_EXPORTER_OTLP_ENDPOINT: http://otel_collector:4317
      OTEL_SERVICE_NAME: app-php
      OTEL_TRACES_EXPORTER: otlp
    networks:
      - backend
  
networks:
  backend:

> composer.json

{
    "require": {
        "slim/slim": "4.*",
        "php-di/php-di": "^6.3",
        "guzzlehttp/guzzle": "^7.3",
        "open-telemetry/api": "^1.0.0",
        "open-telemetry/sdk": "^1.0.0"
    },
    "minimum-stability": "dev"
}

> otel-collector-config.yml

receivers:
  otlp:
    protocols:
      grpc: {}
      http: {}

exporters

<details>
<summary>英文:</summary>

I have a very simple stack of PHP + Otel auto instrumetation + Elastic APM + Prometheus.

My stack gets tracing and metrics information from my php app.
My tracings are forwarded to the elastic cloud, where I use APM. My metrics go to Prometheus.

I see that my tracing is partially working as I can&#39;t see the dependencies. Which in this case would be my external api.

[![enter image description here][1]][1]
[![enter image description here][2]][2]

**The base of my stack:** (*I didn&#39;t attach the **php.ini** and **.htaccess** files as I don&#39;t think it&#39;s relevant.*)

&gt; index.php
~~~php
&lt;?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use DI\Container;
use GuzzleHttp\Client;

require __DIR__ . &#39;/vendor/autoload.php&#39;;

$container = new Container();

AppFactory::setContainer($container);
$app = AppFactory::create();

$app-&gt;get(&#39;/&#39;, function (Request $request, Response $response) {
    $response-&gt;getBody()-&gt;write(&#39;&lt;h3&gt;RANDOM API&lt;/h3&gt;
    &lt;p&gt;O que voc&#234; gostaria de ver?&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Random dogs? &lt;a href=&quot;/dogs&quot;&gt;Clique&lt;/li&gt;
    &lt;/ul&gt;&#39;);

    return $response;
});

$app-&gt;get(&#39;/healthcheck&#39;, function (Request $request, Response $response) {
    return $response-&gt;withStatus(204);
});

$app-&gt;get(&#39;/dogs&#39;, function (Request $request, Response $response) {
    $client = new Client();

    try {
        $apiResponse = $client-&gt;get(&#39;https://dog.ceo/api/breeds/image/random&#39;);
        $dogData = json_decode($apiResponse-&gt;getBody());

        $response-&gt;getBody()-&gt;write(&#39;&lt;img src=&quot;&#39; . $dogData-&gt;message . &#39;&quot; alt=&quot;random dog&quot; style=&quot;max-width: 500px&quot;/&gt;&#39;);

    } catch (\Exception $e) {
        $response-&gt;getBody()-&gt;write($e-&gt;getMessage());
        return $response-&gt;withStatus(500);
    }

    return $response;
});

$app-&gt;run();
~~~

&gt; Dockerfile

```dockerfile
FROM php:8.2

RUN set -xe; \
    apt-get update; \
    apt-get -y install g++ zlib1g-dev build-essential zlib1g-dev gcc make autoconf m4 perl git; \
    curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \
    pecl install grpc &amp;&amp; docker-php-ext-enable grpc; \
    pecl install opentelemetry-beta &amp;&amp; docker-php-ext-enable opentelemetry

ENV COMPOSER_ALLOW_SUPERUSER 1
ENV OTEL_PHP_AUTOLOAD_ENABLED=true
ENV OTEL_SERVICE_NAME=your-service-name
ENV OTEL_TRACES_EXPORTER=console
ENV OTEL_METRICS_EXPORTER=otlp
ENV OTEL_EXPORTER_OTLP_PROTOCOL=grpc
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317
ENV OTEL_PROPAGATORS=baggage,tracecontext

WORKDIR /usr/src/myapp

COPY composer.json composer.lock* /usr/src/myapp/

RUN composer install --no-dev --no-scripts --no-autoloader

COPY . /usr/src/myapp

RUN composer dump-autoload --optimize --classmap-authoritative; \
    composer require slim/slim:^4 slim/psr7:^1; \
    composer require open-telemetry/exporter-otlp php-http/guzzle7-adapter; \
    composer require open-telemetry/transport-grpc; \
    composer config allow-plugins.php-http/discovery false; \
    composer require open-telemetry/sdk open-telemetry/opentelemetry-auto-slim; \
    php --ri opentelemetry

COPY php.ini /usr/local/etc/php/php.ini

CMD [ &quot;php&quot;, &quot;-S&quot;, &quot;0.0.0.0:8080&quot; ]

> docker-compose.yml

services:
  otel_collector:
    networks:
      - backend
    image: otel/opentelemetry-collector-contrib:latest
    volumes:
      - &quot;./otel-collector-config.yml:/etc/otelcol/otel-collector-config.yml&quot;
    command: --config /etc/otelcol/otel-collector-config.yml
    ports:
      - &quot;14278:14278&quot;
      - &quot;65535:65535&quot;
      - &quot;55677:55677&quot;
      - &quot;12345:12345&quot;
      - &quot;4318:4318&quot;
      - &quot;4317:4317&quot;    
      - &quot;8889:8889&quot;  
  prometheus:
    networks:
      - backend
    image: prom/prometheus:latest
    volumes:
      - &quot;./prometheus.yml:/etc/prometheus/prometheus.yml&quot;
    ports:
      - &quot;9090:9090&quot;

  app-php:
    build: ./php
    image: app-php
    ports:
      - 8083:8080
    container_name: app-php
    environment:
      OTEL_EXPORTER_OTLP_ENDPOINT: http://otel_collector:4317
      OTEL_SERVICE_NAME: app-php
      OTEL_TRACES_EXPORTER: otlp
    networks:
      - backend
  
networks:
  backend:

> composer.json

{
    &quot;require&quot;: {
        &quot;slim/slim&quot;: &quot;4.*&quot;,
        &quot;php-di/php-di&quot;: &quot;^6.3&quot;,
        &quot;guzzlehttp/guzzle&quot;: &quot;^7.3&quot;,
        &quot;open-telemetry/api&quot;: &quot;^1.0.0&quot;,
        &quot;open-telemetry/sdk&quot;: &quot;^1.0.0&quot;
    },
    &quot;minimum-stability&quot;: &quot;dev&quot;
}

> otel-collector-config.yml

receivers:
  otlp:
    protocols:
      grpc: {}
      http: {}

exporters:
  prometheus:
    endpoint: &quot;0.0.0.0:8889&quot;


  logging:
    verbosity: detailed
   

  otlp/elastic: 
    endpoint: &quot;xxx-xxx-xxx&quot;  
    headers:
      Authorization: &quot;xxx-xxx-xxx&quot;

 
processors:
  batch: {}

service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheus, logging]
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/elastic, logging]

>prometheus.yml

global:
  scrape_interval:     15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: aggregated-trace-metrics
    static_configs:
    - targets: [&#39;otel_collector:8889&#39;]

答案1

得分: 3

看起来你的Slim框架应用程序的路由正在被跟踪并在elastic中可见,但你缺少对https://dog.ceo的http调用的跟踪。

Slim框架的自动仪器化不会仪器化外部的http调用。如果你正在使用的$client是一个PSR-18 http客户端,那么可以通过安装open-telemetry/opentelemetry-auto-psr18包来进行自动仪器化。请注意,$client->get()不是PSR-18规范的一部分,只有sendRequest()是。如果你正在使用的http客户端通过代理get()来调用sendRequest(),那么它应该能够工作。否则,可以使用PSR-18的方法创建请求并发送它:

$request = new Request('GET', 'https://dog.ceo/api/breeds/image/random');
$client->sendRequest($request);
英文:

It looks like your routes for the Slim Framework application are being traced and are visible in elastic, but you are missing spans for the http calls to https://dog.ceo

The slim framework auto-instrumentation does not instrument outgoing http calls. If the $client that you are using is a PSR-18 http client, then it can be auto-instrumented by installing the open-telemetry/opentelemetry-auto-psr18 package. Do note that $client-&gt;get() is not part of the PSR-18 spec, only sendRequest() is. If the http client you are using proxies get() through to sendRequest(), then it should work. Otherwise, create the request and send it using the PSR-18 method:

$request = new Request(&#39;GET&#39;, &#39;https://dog.ceo/api/breeds/image/random&#39;);
$client-&gt;sendRequest($request);

huangapple
  • 本文由 发表于 2023年7月20日 13:32:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76726928.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定