Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
48a8722
Updated phpstan to 2.1.31
SergeyKleyman Oct 22, 2025
37c9d08
Fixed issues flagged by the static analysis 4845da
SergeyKleyman Oct 22, 2025
4de410f
Simplified DebugContext implementation
SergeyKleyman Oct 23, 2025
27dbdcc
Fixed issues flagged by the static analysis
SergeyKleyman Oct 23, 2025
cae1db8
Pin open-telemetry/gen-otlp-protobuf version to 1.5.0
SergeyKleyman Oct 23, 2025
ae9d853
Pinned brick/math version to 0.13.1
SergeyKleyman Oct 23, 2025
400a6d1
Revert pinning "open-telemetry/gen-otlp-protobuf" to "1.5.0"
SergeyKleyman Oct 23, 2025
9058440
Updated OTel SDK to 1.9.0
SergeyKleyman Oct 23, 2025
df8b706
Added PHP zip extension to test Docker containers
SergeyKleyman Oct 23, 2025
8b49466
Added libzip-dev to Alpine Docker
SergeyKleyman Oct 23, 2025
a933cae
Merge branch 'Update_phpstan_to_2.1.31' into Update_OTel_SDK_to_1.9.0
SergeyKleyman Oct 23, 2025
0ae4dcd
Added SdkDistroAttributes tests
SergeyKleyman Oct 23, 2025
db9bce7
Merge branch 'Update_OTel_SDK_to_1.9.0' into Fix_distro_name
SergeyKleyman Oct 23, 2025
b2aecd3
Fixed the issue by instrumenting ResourceInfoFactory::defaultResource
SergeyKleyman Oct 23, 2025
e6b0aa7
Changed implementation to use Registry::registerResourceDetector
SergeyKleyman Oct 23, 2025
c9a1487
Minor improvements to logging
SergeyKleyman Oct 23, 2025
f3e96ce
Get distro version to assert from app context
SergeyKleyman Oct 23, 2025
bd4c700
Merge branch 'main' into Update_OTel_SDK_to_1.9.0
SergeyKleyman Oct 23, 2025
c8c7239
Re-generate composer lock files to overwrite the ones merged from main
SergeyKleyman Oct 23, 2025
549c351
Merge branch 'Update_OTel_SDK_to_1.9.0' into Fix_distro_name
SergeyKleyman Oct 23, 2025
ee2a2b1
Assert version in app context is in sync with test
SergeyKleyman Oct 23, 2025
6fb88e3
Implemented capture of stderr and stdout for processes spawned by com…
SergeyKleyman Oct 24, 2025
93e2541
Merge branch 'main' into Capture_output_fron_processes_spawned_by_com…
SergeyKleyman Oct 24, 2025
dad92ac
Merge branch 'main' into Fix_distro_name
SergeyKleyman Oct 24, 2025
320a85e
Merge branch 'Capture_output_fron_processes_spawned_by_compotent_test…
SergeyKleyman Oct 24, 2025
54e3318
Fixed setting ELASTIC_OTEL_PHP_TESTS_LOGS_DIRECTORY in component tests
SergeyKleyman Oct 24, 2025
43109a2
Merge branch 'Capture_output_fron_processes_spawned_by_compotent_test…
SergeyKleyman Oct 24, 2025
b79189c
Log PHP memory_limit
SergeyKleyman Oct 24, 2025
3f702fe
Increased PHP's memory_limit to 256M
SergeyKleyman Oct 24, 2025
d4d27a9
Fix memory_limit print format
SergeyKleyman Oct 24, 2025
91e2ad6
Log memory usage in MockCollector
SergeyKleyman Oct 25, 2025
7db34f8
Refactor code so that MockCollector doesn't keep deserialized trace data
SergeyKleyman Oct 26, 2025
b21524c
Renamed some methods
SergeyKleyman Oct 26, 2025
7afe61b
Renamed methods/properties to sync with the new events concept
SergeyKleyman Oct 26, 2025
f3a6992
Merge branch 'main' into Fix_distro_name
SergeyKleyman Oct 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*
* @internal
*/
final class Autoloader
final class AutoloaderElasticOTelClasses
{
private const AUTOLOAD_FQ_CLASS_NAME_PREFIX = 'Elastic\\OTel\\';

Expand Down
2 changes: 1 addition & 1 deletion prod/php/ElasticOTel/InstrumentationBridge.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private static function elasticOTelHookNoThrow(?string $class, string $function,
}
}

private function retryDelayedHooks(): void
public function retryDelayedHooks(): void
{
$delayedHooksCount = count($this->delayedHooks);
BootstrapStageLogger::logTrace('Entered. delayedHooks count: ' . $delayedHooksCount, __FILE__, __LINE__, __CLASS__, __FUNCTION__);
Expand Down
84 changes: 84 additions & 0 deletions prod/php/ElasticOTel/OverrideOTelSdkResourceAttributes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

declare(strict_types=1);

namespace Elastic\OTel;

use OpenTelemetry\SDK\Common\Attribute\Attributes;
use OpenTelemetry\SDK\Registry;
use OpenTelemetry\SDK\Resource\ResourceDetectorInterface;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SemConv\ResourceAttributes;

/**
* Code in this file is part of implementation internals, and thus it is not covered by the backward compatibility.
*
* @internal
*/
final class OverrideOTelSdkResourceAttributes implements ResourceDetectorInterface
{
private static ?string $distroVersion = null;

public static function register(string $elasticOTelNativePartVersion): void
{
self::$distroVersion = self::buildDistroVersion($elasticOTelNativePartVersion);
Registry::registerResourceDetector(self::class, new self());
BootstrapStageLogger::logDebug('Registered; distroVersion: ' . self::$distroVersion, __FILE__, __LINE__, __CLASS__, __FUNCTION__);
}

public function getResource(): ResourceInfo
{
/**
* @see https://github.com/elastic/apm/blob/9a8390a161db1cab0f7e27f03111ff4bececf523/specs/agents/otel-distribution.md?plain=1#L79
* @see https://github.com/elastic/opentelemetry-lib/blob/434982a9d78a9b0ee1f47bccb9f03d6b7bf3570f/enrichments/internal/elastic/resource.go#L102
* @see https://github.com/elastic/kibana/blob/v9.1.0/x-pack/solutions/observability/plugins/apm/common/agent_configuration/setting_definitions/edot_sdk_settings.ts
*
* - `telemetry.distro.name`: must be set to `elastic`
* - `telemetry.distro.version`: must reflect the distribution version
* - `agent.name`: is built by Elastic's ingestion as <telemetry.sdk.name>/<telemetry.sdk.language>/<telemetry.distro.name> and expected by Kibana to be `opentelemetry/php/elastic`
*/

$attributes = [
ResourceAttributes::TELEMETRY_DISTRO_NAME => 'elastic',
ResourceAttributes::TELEMETRY_DISTRO_VERSION => self::getDistroVersion(),
];

BootstrapStageLogger::logDebug('Returning attributes: ' . json_encode($attributes), __FILE__, __LINE__, __CLASS__, __FUNCTION__);
return ResourceInfo::create(Attributes::create($attributes), ResourceAttributes::SCHEMA_URL);
}

private static function buildDistroVersion(string $elasticOTelNativePartVersion): string
{
if ($elasticOTelNativePartVersion === PhpPartVersion::VALUE) {
return $elasticOTelNativePartVersion;
}

$logMsg = 'Native part and PHP part versions do not match. native part version: ' . $elasticOTelNativePartVersion . '; PHP part version: ' . PhpPartVersion::VALUE;
BootstrapStageLogger::logWarning($logMsg, __FILE__, __LINE__, __CLASS__, __FUNCTION__);
return $elasticOTelNativePartVersion . '/' . PhpPartVersion::VALUE;
}

public static function getDistroVersion(): string
{
return self::$distroVersion ?? PhpPartVersion::VALUE;
}
}
57 changes: 7 additions & 50 deletions prod/php/ElasticOTel/PhpPartFacade.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,6 @@ final class PhpPartFacade

public const CONFIG_ENV_VAR_NAME_DEV_INTERNAL_MODE_IS_DEV = 'ELASTIC_OTEL_PHP_DEV_INTERNAL_MODE_IS_DEV';

/**
* We need to use TELEMETRY_DISTRO_NAME and TELEMETRY_DISTRO_VERSION attribute names before OTel SDK is loaded by composer
* so we copy those values to local constants
*
* @see \OpenTelemetry\SemConv\TraceAttributes::TELEMETRY_DISTRO_NAME
* @see \OpenTelemetry\SemConv\TraceAttributes::TELEMETRY_DISTRO_VERSION
*
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
*/
public const OTEL_ATTR_NAME_TELEMETRY_DISTRO_NAME = 'telemetry.distro.name';
public const OTEL_ATTR_NAME_TELEMETRY_DISTRO_VERSION = 'telemetry.distro.version';

/**
* Called by the extension
*
Expand Down Expand Up @@ -114,12 +102,13 @@ public static function bootstrap(string $elasticOTelNativePartVersion, int $maxE
}

try {
require __DIR__ . DIRECTORY_SEPARATOR . 'Autoloader.php';
Autoloader::register(__DIR__);
require __DIR__ . DIRECTORY_SEPARATOR . 'AutoloaderElasticOTelClasses.php';
AutoloaderElasticOTelClasses::register(__DIR__);

InstrumentationBridge::singletonInstance()->bootstrap();
self::prepareEnvForOTelSdk($elasticOTelNativePartVersion);
self::registerAutoloader();
self::prepareForOTelSdk();
self::registerAutoloaderForVendorDir();
OverrideOTelSdkResourceAttributes::register($elasticOTelNativePartVersion);
self::registerNativeOtlpSerializer();
self::registerAsyncTransportFactory();
self::registerOtelLogWriter();
Expand Down Expand Up @@ -178,22 +167,6 @@ public static function inferredSpans(int $durationMs, bool $internalFunction): b
return true;
}

private static function buildElasticOTelVersion(string $nativePartVersion): string
{
if ($nativePartVersion === PhpPartVersion::VALUE) {
return $nativePartVersion;
}

BootstrapStageLogger::logWarning(
'Native part and PHP part versions do not match. native part version: ' . $nativePartVersion . '; PHP part version: ' . PhpPartVersion::VALUE,
__FILE__,
__LINE__,
__CLASS__,
__FUNCTION__
);
return $nativePartVersion . '/' . PhpPartVersion::VALUE;
}

private static function isInDevMode(): bool
{
$modeIsDevEnvVarVal = getenv(self::CONFIG_ENV_VAR_NAME_DEV_INTERNAL_MODE_IS_DEV);
Expand All @@ -212,21 +185,6 @@ private static function isInDevMode(): bool
return false;
}

private static function prepareEnvForOTelAttributes(string $elasticOTelNativePartVersion): void
{
$envVarName = 'OTEL_RESOURCE_ATTRIBUTES';
$envVarValueOnEntry = getenv($envVarName);
$envVarValue = (is_string($envVarValueOnEntry) && strlen($envVarValueOnEntry) !== 0) ? ($envVarValueOnEntry . ',') : '';

// https://opentelemetry.io/docs/specs/semconv/resource/#telemetry-distribution-experimental
$envVarValue .=
self::OTEL_ATTR_NAME_TELEMETRY_DISTRO_NAME . '=elastic'
. ','
. self::OTEL_ATTR_NAME_TELEMETRY_DISTRO_VERSION . '=' . self::buildElasticOTelVersion($elasticOTelNativePartVersion);

self::setEnvVar($envVarName, $envVarValue);
}

/**
* @param non-empty-string $envVarName
*/
Expand All @@ -237,13 +195,12 @@ private static function setEnvVar(string $envVarName, string $envVarValue): void
}
}

private static function prepareEnvForOTelSdk(string $elasticOTelNativePartVersion): void
private static function prepareForOTelSdk(): void
{
self::setEnvVar('OTEL_PHP_AUTOLOAD_ENABLED', 'true');
self::prepareEnvForOTelAttributes($elasticOTelNativePartVersion);
}

private static function registerAutoloader(): void
private static function registerAutoloaderForVendorDir(): void
{
$vendorDir = ProdPhpDir::$fullPath . DIRECTORY_SEPARATOR . (
self::isInDevMode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@
use ElasticOTelTests\ComponentTests\Util\AppCodeHostParams;
use ElasticOTelTests\ComponentTests\Util\AppCodeRequestParams;
use ElasticOTelTests\ComponentTests\Util\AppCodeTarget;
use ElasticOTelTests\ComponentTests\Util\AttributesExpectations;
use ElasticOTelTests\ComponentTests\Util\ComponentTestCaseBase;
use ElasticOTelTests\ComponentTests\Util\CurlHandleForTests;
use ElasticOTelTests\ComponentTests\Util\HttpAppCodeRequestParams;
use ElasticOTelTests\ComponentTests\Util\HttpClientUtilForTests;
use ElasticOTelTests\ComponentTests\Util\OtlpData\Span;
use ElasticOTelTests\ComponentTests\Util\OtlpData\SpanKind;
use ElasticOTelTests\ComponentTests\Util\PhpSerializationUtil;
use ElasticOTelTests\ComponentTests\Util\RequestHeadersRawSnapshotSource;
use ElasticOTelTests\ComponentTests\Util\ResourcesClient;
use ElasticOTelTests\ComponentTests\Util\Span;
use ElasticOTelTests\ComponentTests\Util\SpanAttributesExpectations;
use ElasticOTelTests\ComponentTests\Util\SpanExpectationsBuilder;
use ElasticOTelTests\ComponentTests\Util\SpanKind;
use ElasticOTelTests\ComponentTests\Util\UrlUtil;
use ElasticOTelTests\ComponentTests\Util\WaitForEventCounts;
use ElasticOTelTests\ComponentTests\Util\WaitForOTelSignalCounts;
use ElasticOTelTests\Util\AssertEx;
use ElasticOTelTests\Util\Config\OptionForProdName;
use ElasticOTelTests\Util\Config\OptionForTestsName;
Expand Down Expand Up @@ -225,7 +225,7 @@ function (AppCodeRequestParams $clientAppCodeReqParams) use ($testArgs, $appCode
// |------------------------------------------------------| |--------------------------------|
// client app host server app host

$curlClientSpanAttributesExpectations = new SpanAttributesExpectations(
$curlClientSpanAttributesExpectations = new AttributesExpectations(
[
TraceAttributes::CODE_FUNCTION_NAME => 'curl_exec',
TraceAttributes::HTTP_REQUEST_METHOD => HttpMethods::GET,
Expand All @@ -238,7 +238,7 @@ function (AppCodeRequestParams $clientAppCodeReqParams) use ($testArgs, $appCode
);
$expectationsForCurlClientSpan = (new SpanExpectationsBuilder())->name(HttpMethods::GET)->kind(SpanKind::client)->attributes($curlClientSpanAttributesExpectations)->build();

$serverTxSpanAttributesExpectations = new SpanAttributesExpectations(
$serverTxSpanAttributesExpectations = new AttributesExpectations(
[
TraceAttributes::HTTP_REQUEST_METHOD => HttpMethods::GET,
TraceAttributes::HTTP_RESPONSE_STATUS_CODE => self::SERVER_RESPONSE_HTTP_STATUS,
Expand All @@ -252,25 +252,25 @@ function (AppCodeRequestParams $clientAppCodeReqParams) use ($testArgs, $appCode
$expectedServerTxSpanName = HttpMethods::GET . ' ' . $appCodeRequestParamsForServer->urlParts->path;
$expectationsForServerTxSpan = (new SpanExpectationsBuilder())->name($expectedServerTxSpanName)->kind(SpanKind::server)->attributes($serverTxSpanAttributesExpectations)->build();

$exportedData = $testCaseHandle->waitForEnoughExportedData(WaitForEventCounts::spans($enableCurlInstrumentationForClient ? 3 : 2));
$dbgCtx->add(compact('exportedData'));
$agentBackendComms = $testCaseHandle->waitForEnoughAgentBackendComms(WaitForOTelSignalCounts::spans($enableCurlInstrumentationForClient ? 3 : 2));
$dbgCtx->add(compact('agentBackendComms'));

//
// Assert
//

if ($enableCurlInstrumentationForClient) {
$rootSpan = $exportedData->singleRootSpan();
foreach ($exportedData->spans as $span) {
$rootSpan = $agentBackendComms->singleRootSpan();
foreach ($agentBackendComms->spans() as $span) {
self::assertSame($rootSpan->traceId, $span->traceId);
}
$curlClientSpan = $exportedData->singleChildSpan($rootSpan->id);
$curlClientSpan = $agentBackendComms->singleChildSpan($rootSpan->id);
$expectationsForCurlClientSpan->assertMatches($curlClientSpan);
$serverTxSpan = $exportedData->singleChildSpan($curlClientSpan->id);
$serverTxSpan = $agentBackendComms->singleChildSpan($curlClientSpan->id);
} else {
$serverTxSpan = IterableUtil::singleValue($exportedData->findSpansWithAttributeValue(TraceAttributes::SERVER_PORT, $appCodeRequestParamsForServer->urlParts->port));
$serverTxSpan = IterableUtil::singleValue($agentBackendComms->findSpansWithAttributeValue(TraceAttributes::SERVER_PORT, $appCodeRequestParamsForServer->urlParts->port));
self::assertNull($serverTxSpan->parentId);
$clientTxSpan = IterableUtil::singleValue(IterableUtil::findByPredicateOnValue($exportedData->spans, fn(Span $span) => $span->parentId === null && $span !== $serverTxSpan));
$clientTxSpan = IterableUtil::singleValue(IterableUtil::findByPredicateOnValue($agentBackendComms->spans(), fn(Span $span) => $span->parentId === null && $span !== $serverTxSpan));
self::assertNotEquals($serverTxSpan->traceId, $clientTxSpan->traceId);
}

Expand Down
Loading