diff --git a/manifests/php.yml b/manifests/php.yml index 41e22f3ecb0..2e44da86b27 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -594,7 +594,6 @@ manifest: - declaration: missing_feature (The always_on sampler mapping is properly implemented in v1.2.0) component_version: <=1.1.0 tests/parametric/test_otel_logs.py: missing_feature - tests/parametric/test_otel_metrics.py: missing_feature tests/parametric/test_otel_span_methods.py::Test_Otel_Span_Methods: v0.94.0 tests/parametric/test_otel_span_methods.py::Test_Otel_Span_Methods::test_otel_add_event_meta_serialization: - declaration: missing_feature (Not implemented) diff --git a/tests/parametric/test_otel_metrics.py b/tests/parametric/test_otel_metrics.py index 4526c78b312..78b7b2ca2ac 100644 --- a/tests/parametric/test_otel_metrics.py +++ b/tests/parametric/test_otel_metrics.py @@ -1,7 +1,7 @@ from urllib.parse import urlparse import pytest -from utils import features, scenarios +from utils import features, scenarios, missing_feature, context from utils.docker_fixtures import TestAgentAPI from .conftest import APMLibrary @@ -352,6 +352,7 @@ class Test_Otel_Metrics_Api_Meter: """ @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) + @missing_feature(context.library == "php", reason="min max bug in otel php", force_skip=True) def test_otel_create_instruments_by_distinct(self, test_agent: TestAgentAPI, test_library: APMLibrary): counter_name = "test_otel_create_counter" updowncounter_name = "test_otel_create_updowncounter" @@ -562,6 +563,7 @@ class Test_Otel_Metrics_Api_Instrument: """ @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) + @missing_feature(context.library == "php", reason="otel php does not follow this", force_skip=True) def test_otel_counter_add_non_negative_and_negative_values( self, test_agent: TestAgentAPI, test_library: APMLibrary ): @@ -837,6 +839,7 @@ def test_otel_gauge_record_multiple_values_with_different_tags( assert_gauge_aggregation(metric["gauge"], second_value, NON_DEFAULT_MEASUREMENT_ATTRIBUTES) @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) + @missing_feature(context.library == "php", reason="otel php does not follow this", force_skip=True) def test_otel_histogram_add_non_negative_and_negative_values( self, test_agent: TestAgentAPI, test_library: APMLibrary ): @@ -897,6 +900,7 @@ def test_otel_histogram_add_non_negative_and_negative_values( ) @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) + @missing_feature(context.library == "php", reason="min max bug in otel php", force_skip=True) def test_otel_histogram_add_non_negative_values_with_different_tags( self, test_agent: TestAgentAPI, test_library: APMLibrary ): @@ -1073,6 +1077,7 @@ class Test_Otel_Metrics_Configuration_Temporality_Preference: ], ids=["default", "delta", "cumulative"], ) + @missing_feature(context.library == "php", reason="min max bug in otel php", force_skip=True) def test_otel_aggregation_temporality( self, library_env: dict[str, str], test_agent: TestAgentAPI, test_library: APMLibrary ): @@ -1348,6 +1353,7 @@ def test_otlp_metrics_custom_endpoint_http_protobuf( scope_metrics = metrics[0]["resource_metrics"][0]["scope_metrics"] assert scope_metrics is not None + @missing_feature(context.library == "php", reason="otel php does not follow this", force_skip=True) @pytest.mark.parametrize( ("library_env", "endpoint_env", "test_agent_otlp_grpc_port"), [ @@ -1541,6 +1547,7 @@ class Test_Otel_Metrics_Host_Name: **DEFAULT_ENVVARS, "DD_HOSTNAME": "ddhostname", "DD_TRACE_REPORT_HOSTNAME": "true", + "OTEL_PHP_DETECTORS": "all", }, ], ) @@ -1553,7 +1560,12 @@ def test_hostname_from_dd_hostname(self, test_agent: TestAgentAPI, test_library: metrics_data = test_agent.wait_for_num_otlp_metrics(num=1) resource = metrics_data[0]["resource_metrics"][0]["resource"] - actual_attributes = {item["key"]: item["value"]["string_value"] for item in resource["attributes"]} + # Only extract attributes that have string_value + actual_attributes = { + item["key"]: item["value"]["string_value"] + for item in resource["attributes"] + if "string_value" in item["value"] + } assert actual_attributes.get("host.name") == "ddhostname" @@ -1582,7 +1594,12 @@ def test_hostname_from_otel_resources( metrics_data = test_agent.wait_for_num_otlp_metrics(num=1) resource = metrics_data[0]["resource_metrics"][0]["resource"] - actual_attributes = {item["key"]: item["value"]["string_value"] for item in resource["attributes"]} + # Only extract attributes that have string_value + actual_attributes = { + item["key"]: item["value"]["string_value"] + for item in resource["attributes"] + if "string_value" in item["value"] + } assert actual_attributes.get(host_attribute) == "otelenv-host" @@ -1611,7 +1628,12 @@ def test_hostname_omitted(self, test_agent: TestAgentAPI, test_library: APMLibra metrics_data = test_agent.wait_for_num_otlp_metrics(num=1) resource = metrics_data[0]["resource_metrics"][0]["resource"] - actual_attributes = {item["key"]: item["value"]["string_value"] for item in resource["attributes"]} + # Only extract attributes that have string_value (skip non-string attributes like telemetry.distro.version) + actual_attributes = { + item["key"]: item["value"]["string_value"] + for item in resource["attributes"] + if "string_value" in item["value"] + } assert "host.name" not in actual_attributes @@ -1652,7 +1674,12 @@ def test_otel_resource_attributes(self, test_agent: TestAgentAPI, test_library: # Assert that the ResourceMetrics has the expected resources resource = metrics_data[0]["resource_metrics"][0]["resource"] - actual_attributes = {item["key"]: item["value"]["string_value"] for item in resource["attributes"]} + # Only extract attributes that have string_value (skip non-string attributes like telemetry.distro.version) + actual_attributes = { + item["key"]: item["value"]["string_value"] + for item in resource["attributes"] + if "string_value" in item["value"] + } assert expected_attributes.items() <= actual_attributes.items() # Add separate assertion for the DD_ENV mapping, whose semantic convention was updated in 1.27.0 @@ -1713,7 +1740,12 @@ def test_otel_resource_attributes_populated_by_dd_otel_envs( # Assert that the ResourceMetrics has the expected resources resource = metrics_data[0]["resource_metrics"][0]["resource"] - actual_attributes = {item["key"]: item["value"]["string_value"] for item in resource["attributes"]} + # Only extract attributes that have string_value (skip non-string attributes like telemetry.distro.version) + actual_attributes = { + item["key"]: item["value"]["string_value"] + for item in resource["attributes"] + if "string_value" in item["value"] + } assert expected_attributes.items() <= actual_attributes.items() # Add separate assertion for the DD_ENV mapping, whose semantic convention was updated in 1.27.0 @@ -1751,7 +1783,12 @@ def test_dd_env_vars_override_otel(self, test_agent: TestAgentAPI, test_library: # Assert that the ResourceMetrics has the expected resources resource = metrics_data[0]["resource_metrics"][0]["resource"] - actual_attributes = {item["key"]: item["value"]["string_value"] for item in resource["attributes"]} + # Only extract attributes that have string_value (skip non-string attributes like telemetry.distro.version) + actual_attributes = { + item["key"]: item["value"]["string_value"] + for item in resource["attributes"] + if "string_value" in item["value"] + } assert expected_attributes.items() <= actual_attributes.items() # Add separate assertion for the DD_ENV mapping, whose semantic convention was updated in 1.27.0 diff --git a/utils/build/docker/php/parametric/Dockerfile b/utils/build/docker/php/parametric/Dockerfile index 7a9c3a5157a..b40c3f8c723 100644 --- a/utils/build/docker/php/parametric/Dockerfile +++ b/utils/build/docker/php/parametric/Dockerfile @@ -1,10 +1,10 @@ -FROM datadog/dd-trace-ci:php-8.2_buster +FROM datadog/dd-trace-ci:php-8.2_bookworm-5 RUN switch-php nts WORKDIR /binaries ENV DD_TRACE_CLI_ENABLED=1 ADD utils/build/docker/php/parametric/composer.json . -ADD utils/build/docker/php/parametric/composer.lock . +RUN echo "extension=grpc" > "$(php-config --ini-dir)/grpc.ini" RUN composer install ADD utils/build/docker/php/parametric/../common/install_ddtrace.sh . COPY binaries /binaries diff --git a/utils/build/docker/php/parametric/composer.json b/utils/build/docker/php/parametric/composer.json index 38a79500f95..88544354441 100644 --- a/utils/build/docker/php/parametric/composer.json +++ b/utils/build/docker/php/parametric/composer.json @@ -2,16 +2,19 @@ "minimum-stability":"dev", "require": { "league/uri-components": "^2", - "amphp/http-server": "3.x-dev", - "amphp/http-server-router": "2.x-dev", - "amphp/log": "2.x-dev", - "open-telemetry/sdk": "^1.0.0", - "symfony/http-client": "6.4.x-dev", + "amphp/http-server": "^3", + "amphp/http-server-router": "^2", + "amphp/log": "^2", + "open-telemetry/sdk": "2.x-dev", + "open-telemetry/exporter-otlp": "2.x-dev", + "open-telemetry/transport-grpc": "2.x-dev", + "symfony/http-client": "^6.4", "nyholm/psr7": "^1.8@dev" }, "config": { "allow-plugins": { - "php-http/discovery": true + "php-http/discovery": true, + "tbachert/spi": true } } } diff --git a/utils/build/docker/php/parametric/composer.lock b/utils/build/docker/php/parametric/composer.lock deleted file mode 100644 index 2131c837ac9..00000000000 --- a/utils/build/docker/php/parametric/composer.lock +++ /dev/null @@ -1,3146 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "9596c1fae76bc9b026bb905fa7915420", - "packages": [ - { - "name": "amphp/amp", - "version": "3.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "b6e3a6a63dc87a6926bc61a42500573408441931" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/b6e3a6a63dc87a6926bc61a42500573408441931", - "reference": "b6e3a6a63dc87a6926bc61a42500573408441931", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Future/functions.php", - "src/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/3.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-18T18:40:59+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "3a4a0faa5aa63d0d76f41b1665d7a8a9137139ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/3a4a0faa5aa63d0d76f41b1665d7a8a9137139ce", - "reference": "3a4a0faa5aa63d0d76f41b1665d7a8a9137139ce", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/parser": "^1.1", - "amphp/pipeline": "^1", - "amphp/serialization": "^1", - "amphp/sync": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2.3" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "https://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/2.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-09-03T22:18:50+00:00" - }, - { - "name": "amphp/cache", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/cache.git", - "reference": "218bb3888d380eb9dd926cd06f803573c84391d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/cache/zipball/218bb3888d380eb9dd926cd06f803573c84391d3", - "reference": "218bb3888d380eb9dd926cd06f803573c84391d3", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/serialization": "^1", - "amphp/sync": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Cache\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - } - ], - "description": "A fiber-aware cache API based on Amp and Revolt.", - "homepage": "https://amphp.org/cache", - "support": { - "issues": "https://github.com/amphp/cache/issues", - "source": "https://github.com/amphp/cache/tree/v2.0.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-01-09T21:04:12+00:00" - }, - { - "name": "amphp/dns", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/dns.git", - "reference": "e42876aa8306c754abd1b3e71a44e13066909fd1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/dns/zipball/e42876aa8306c754abd1b3e71a44e13066909fd1", - "reference": "e42876aa8306c754abd1b3e71a44e13066909fd1", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/cache": "^2", - "amphp/parser": "^1", - "amphp/windows-registry": "^1", - "daverandom/libdns": "^2.0.2", - "ext-filter": "*", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Dns\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Chris Wright", - "email": "addr@daverandom.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "Async DNS resolution for Amp.", - "homepage": "https://github.com/amphp/dns", - "keywords": [ - "amp", - "amphp", - "async", - "client", - "dns", - "resolve" - ], - "support": { - "issues": "https://github.com/amphp/dns/issues", - "source": "https://github.com/amphp/dns/tree/v2.0.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-01-21T16:00:09+00:00" - }, - { - "name": "amphp/hpack", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/amphp/hpack.git", - "reference": "95895d29ae577a3a5995b46d16def04e11e39947" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/hpack/zipball/95895d29ae577a3a5995b46d16def04e11e39947", - "reference": "95895d29ae577a3a5995b46d16def04e11e39947", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "http2jp/hpack-test-case": "^1", - "nikic/php-fuzzer": "^0.0.10", - "phpunit/phpunit": "^7 | ^8 | ^9" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\Http\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "HTTP/2 HPack implementation.", - "homepage": "https://github.com/amphp/hpack", - "keywords": [ - "headers", - "hpack", - "http-2" - ], - "support": { - "issues": "https://github.com/amphp/hpack/issues", - "source": "https://github.com/amphp/hpack/tree/v3.2.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-09-05T19:59:20+00:00" - }, - { - "name": "amphp/http", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/http.git", - "reference": "9f3500bef4bb15cf41987f21136539c0a06555a3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/http/zipball/9f3500bef4bb15cf41987f21136539c0a06555a3", - "reference": "9f3500bef4bb15cf41987f21136539c0a06555a3", - "shasum": "" - }, - "require": { - "amphp/hpack": "^3", - "amphp/parser": "^1.1", - "league/uri-components": "^2.4.2 | ^7.1", - "php": ">=8.1", - "psr/http-message": "^1 | ^2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "league/uri": "^6.8 | ^7.1", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/constants.php" - ], - "psr-4": { - "Amp\\Http\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "Basic HTTP primitives which can be shared by servers and clients.", - "support": { - "issues": "https://github.com/amphp/http/issues", - "source": "https://github.com/amphp/http/tree/v2.1.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-22T19:50:46+00:00" - }, - { - "name": "amphp/http-server", - "version": "3.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/http-server.git", - "reference": "e984728667de7394629618e4f603a962981a4f91" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/http-server/zipball/e984728667de7394629618e4f603a962981a4f91", - "reference": "e984728667de7394629618e4f603a962981a4f91", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/cache": "^2", - "amphp/hpack": "^3", - "amphp/http": "^2", - "amphp/pipeline": "^1", - "amphp/socket": "^2.1", - "amphp/sync": "^2", - "league/uri": "^6.8 | ^7.1", - "league/uri-interfaces": "^2.3 | ^7.1", - "php": ">=8.1", - "psr/http-message": "^1 | ^2", - "psr/log": "^1 | ^2 | ^3", - "revolt/event-loop": "^1" - }, - "require-dev": { - "amphp/http-client": "^5", - "amphp/log": "^2", - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "league/uri-components": "^2.4.2 | ^7.1", - "monolog/monolog": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "suggest": { - "ext-zlib": "Allows GZip compression of response bodies" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/Driver/functions.php", - "src/Middleware/functions.php", - "src/functions.php" - ], - "psr-4": { - "Amp\\Http\\Server\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "A non-blocking HTTP application server for PHP based on Amp.", - "homepage": "https://github.com/amphp/http-server", - "keywords": [ - "amp", - "amphp", - "async", - "http", - "non-blocking", - "server" - ], - "support": { - "issues": "https://github.com/amphp/http-server/issues", - "source": "https://github.com/amphp/http-server/tree/3.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-09-04T04:43:25+00:00" - }, - { - "name": "amphp/http-server-router", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/http-server-router.git", - "reference": "8a166efa10bc3fc887a7a42b8a55c7b16bc9fc61" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/http-server-router/zipball/8a166efa10bc3fc887a7a42b8a55c7b16bc9fc61", - "reference": "8a166efa10bc3fc887a7a42b8a55c7b16bc9fc61", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/cache": "^2", - "amphp/http": "^2", - "amphp/http-server": "^3", - "amphp/socket": "^2", - "nikic/fast-route": "^1", - "php": ">=8.1", - "psr/log": "^1|^2|^3" - }, - "require-dev": { - "amphp/log": "^2", - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "colinodell/psr-testlogger": "^1.2", - "league/uri": "^6", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.6" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Http\\Server\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "Routes to request handlers based on HTTP method and path for amphp/http-server.", - "homepage": "https://github.com/amphp/http-server-router", - "keywords": [ - "http", - "router", - "server" - ], - "support": { - "issues": "https://github.com/amphp/http-server-router/issues", - "source": "https://github.com/amphp/http-server-router/tree/v2.0.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-05T19:16:57+00:00" - }, - { - "name": "amphp/log", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/log.git", - "reference": "bf1562b8a18a3f30efa069ed740f412ac70a8a6c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/log/zipball/bf1562b8a18a3f30efa069ed740f412ac70a8a6c", - "reference": "bf1562b8a18a3f30efa069ed740f412ac70a8a6c", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "monolog/monolog": "^3|^2|^1.23", - "php": ">=8.1", - "psr/log": "^3|^2|^1" - }, - "require-dev": { - "amphp/file": "^3", - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.6" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Non-blocking logging for PHP based on Amp, Revolt, and Monolog.", - "homepage": "https://github.com/amphp/log", - "keywords": [ - "amp", - "amphp", - "async", - "log", - "logger", - "logging", - "non-blocking" - ], - "support": { - "issues": "https://github.com/amphp/log/issues", - "source": "https://github.com/amphp/log/tree/v2.0.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-05T18:59:54+00:00" - }, - { - "name": "amphp/parser", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/parser.git", - "reference": "ff1de4144726c5dad5fab97f66692ebe8de3e151" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/parser/zipball/ff1de4144726c5dad5fab97f66692ebe8de3e151", - "reference": "ff1de4144726c5dad5fab97f66692ebe8de3e151", - "shasum": "" - }, - "require": { - "php": ">=7.4" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Parser\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A generator parser to make streaming parsers simple.", - "homepage": "https://github.com/amphp/parser", - "keywords": [ - "async", - "non-blocking", - "parser", - "stream" - ], - "support": { - "issues": "https://github.com/amphp/parser/issues", - "source": "https://github.com/amphp/parser/tree/v1.1.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-12-30T18:08:47+00:00" - }, - { - "name": "amphp/pipeline", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/pipeline.git", - "reference": "f4df01bd6fe5403472f07668d1cde29da4a59094" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/pipeline/zipball/f4df01bd6fe5403472f07668d1cde29da4a59094", - "reference": "f4df01bd6fe5403472f07668d1cde29da4a59094", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Pipeline\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Asynchronous iterators and operators.", - "homepage": "https://amphp.org/pipeline", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "iterator", - "non-blocking" - ], - "support": { - "issues": "https://github.com/amphp/pipeline/issues", - "source": "https://github.com/amphp/pipeline/tree/1.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-12-28T04:34:25+00:00" - }, - { - "name": "amphp/process", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/process.git", - "reference": "943352b1c12e19ed14b9def671a98197e0121d0e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/process/zipball/943352b1c12e19ed14b9def671a98197e0121d0e", - "reference": "943352b1c12e19ed14b9def671a98197e0121d0e", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/sync": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Process\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A fiber-aware process manager based on Amp and Revolt.", - "homepage": "https://amphp.org/process", - "support": { - "issues": "https://github.com/amphp/process/issues", - "source": "https://github.com/amphp/process/tree/2.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-22T21:49:13+00:00" - }, - { - "name": "amphp/serialization", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/serialization.git", - "reference": "21116dcd1221e0d1817e02a6e2b0c52a9a317327" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/serialization/zipball/21116dcd1221e0d1817e02a6e2b0c52a9a317327", - "reference": "21116dcd1221e0d1817e02a6e2b0c52a9a317327", - "shasum": "" - }, - "require": { - "php": ">=7.4" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "ext-json": "*", - "ext-zlib": "*", - "phpunit/phpunit": "^9", - "psalm/phar": "5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Serialization\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Serialization tools for IPC and data storage in PHP.", - "homepage": "https://github.com/amphp/serialization", - "keywords": [ - "async", - "asynchronous", - "serialization", - "serialize" - ], - "support": { - "issues": "https://github.com/amphp/serialization/issues", - "source": "https://github.com/amphp/serialization/tree/1.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-29T20:22:27+00:00" - }, - { - "name": "amphp/socket", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/socket.git", - "reference": "3418a0c5c0d4978b0e8e0619ce1da0851c4053d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/socket/zipball/3418a0c5c0d4978b0e8e0619ce1da0851c4053d3", - "reference": "3418a0c5c0d4978b0e8e0619ce1da0851c4053d3", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/dns": "^2", - "ext-openssl": "*", - "kelunik/certificate": "^1.1", - "league/uri": "^6.5 | ^7", - "league/uri-interfaces": "^2.3 | ^7", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "amphp/process": "^2", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/functions.php", - "src/SocketAddress/functions.php" - ], - "psr-4": { - "Amp\\Socket\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@gmail.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", - "homepage": "https://github.com/amphp/socket", - "keywords": [ - "amp", - "async", - "encryption", - "non-blocking", - "sockets", - "tcp", - "tls" - ], - "support": { - "issues": "https://github.com/amphp/socket/issues", - "source": "https://github.com/amphp/socket/tree/v2.2.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-08-19T15:28:34+00:00" - }, - { - "name": "amphp/sync", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/sync.git", - "reference": "c10c5f86afa0a043d82709e2d84831ade1e22304" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/sync/zipball/c10c5f86afa0a043d82709e2d84831ade1e22304", - "reference": "c10c5f86afa0a043d82709e2d84831ade1e22304", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/pipeline": "^1", - "amphp/serialization": "^1", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Sync\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Stephen Coakley", - "email": "me@stephencoakley.com" - } - ], - "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", - "homepage": "https://github.com/amphp/sync", - "keywords": [ - "async", - "asynchronous", - "mutex", - "semaphore", - "synchronization" - ], - "support": { - "issues": "https://github.com/amphp/sync/issues", - "source": "https://github.com/amphp/sync/tree/2.x" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-09-07T22:00:32+00:00" - }, - { - "name": "amphp/windows-registry", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/amphp/windows-registry.git", - "reference": "8248247a41af7f97b88e4716c0f8de39696ef111" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/windows-registry/zipball/8248247a41af7f97b88e4716c0f8de39696ef111", - "reference": "8248247a41af7f97b88e4716c0f8de39696ef111", - "shasum": "" - }, - "require": { - "amphp/byte-stream": "^2", - "amphp/process": "^2", - "php": ">=8.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "psalm/phar": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\WindowsRegistry\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Windows Registry Reader.", - "support": { - "issues": "https://github.com/amphp/windows-registry/issues", - "source": "https://github.com/amphp/windows-registry/tree/v1.0.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2023-01-09T22:29:20+00:00" - }, - { - "name": "daverandom/libdns", - "version": "2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/DaveRandom/LibDNS.git", - "reference": "42c2d700d1178c9f9e78664793463f7f1aea248c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/42c2d700d1178c9f9e78664793463f7f1aea248c", - "reference": "42c2d700d1178c9f9e78664793463f7f1aea248c", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": ">=7.0" - }, - "suggest": { - "ext-intl": "Required for IDN support" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "LibDNS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "DNS protocol implementation written in pure PHP", - "keywords": [ - "dns" - ], - "support": { - "issues": "https://github.com/DaveRandom/LibDNS/issues", - "source": "https://github.com/DaveRandom/LibDNS/tree/2.x" - }, - "time": "2022-09-20T18:15:38+00:00" - }, - { - "name": "kelunik/certificate", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/kelunik/certificate.git", - "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", - "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "php": ">=7.0" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "phpunit/phpunit": "^6 | 7 | ^8 | ^9" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Kelunik\\Certificate\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Access certificate details and transform between different formats.", - "keywords": [ - "DER", - "certificate", - "certificates", - "openssl", - "pem", - "x509" - ], - "support": { - "issues": "https://github.com/kelunik/certificate/issues", - "source": "https://github.com/kelunik/certificate/tree/v1.1.3" - }, - "time": "2023-02-03T21:26:53+00:00" - }, - { - "name": "league/uri", - "version": "6.8.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/uri.git", - "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/a700b4656e4c54371b799ac61e300ab25a2d1d39", - "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39", - "shasum": "" - }, - "require": { - "ext-json": "*", - "league/uri-interfaces": "^2.3", - "php": "^8.1", - "psr/http-message": "^1.0.1" - }, - "conflict": { - "league/uri-schemes": "^1.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.9.5", - "nyholm/psr7": "^1.5.1", - "php-http/psr7-integration-tests": "^1.1.1", - "phpbench/phpbench": "^1.2.6", - "phpstan/phpstan": "^1.8.5", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.1.1", - "phpstan/phpstan-strict-rules": "^1.4.3", - "phpunit/phpunit": "^9.5.24", - "psr/http-factory": "^1.0.1" - }, - "suggest": { - "ext-fileinfo": "Needed to create Data URI from a filepath", - "ext-intl": "Needed to improve host validation", - "league/uri-components": "Needed to easily manipulate URI objects", - "psr/http-factory": "Needed to use the URI factory" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Uri\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" - } - ], - "description": "URI manipulation library", - "homepage": "https://uri.thephpleague.com", - "keywords": [ - "data-uri", - "file-uri", - "ftp", - "hostname", - "http", - "https", - "middleware", - "parse_str", - "parse_url", - "psr-7", - "query-string", - "querystring", - "rfc3986", - "rfc3987", - "rfc6570", - "uri", - "uri-template", - "url", - "ws" - ], - "support": { - "docs": "https://uri.thephpleague.com", - "forum": "https://thephpleague.slack.com", - "issues": "https://github.com/thephpleague/uri/issues", - "source": "https://github.com/thephpleague/uri/tree/6.8.0" - }, - "funding": [ - { - "url": "https://github.com/sponsors/nyamsprod", - "type": "github" - } - ], - "time": "2022-09-13T19:58:47+00:00" - }, - { - "name": "league/uri-components", - "version": "2.4.x-dev", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/uri-components.git", - "reference": "c93837294fe9021d518fd3ea4c5f3fbba8b8ddeb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/c93837294fe9021d518fd3ea4c5f3fbba8b8ddeb", - "reference": "c93837294fe9021d518fd3ea4c5f3fbba8b8ddeb", - "shasum": "" - }, - "require": { - "ext-json": "*", - "league/uri-interfaces": "^2.3", - "php": "^7.4 || ^8.0", - "psr/http-message": "^1.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.22.0", - "guzzlehttp/psr7": "^2.2", - "laminas/laminas-diactoros": "^2.11", - "league/uri": "^6.0", - "phpstan/phpstan": "^1.10.28", - "phpstan/phpstan-deprecation-rules": "^1.1.4", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^9.6.10" - }, - "suggest": { - "ext-fileinfo": "Needed to create Data URI from a filepath", - "ext-gmp": "to improve handle IPV4 parsing", - "ext-intl": "to handle IDN host", - "jeremykendall/php-domain-parser": "Public Suffix and Top Level Domain parsing implemented in PHP", - "league/uri": "to allow manipulating URI objects", - "php-64bit": "to improve handle IPV4 parsing", - "psr/http-message-implementation": "to allow manipulating PSR-7 Uri objects" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Uri\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" - } - ], - "description": "URI components manipulation library", - "homepage": "http://uri.thephpleague.com", - "keywords": [ - "authority", - "components", - "fragment", - "host", - "path", - "port", - "query", - "rfc3986", - "scheme", - "uri", - "url", - "userinfo" - ], - "support": { - "source": "https://github.com/thephpleague/uri-components/tree/2.4.x" - }, - "funding": [ - { - "url": "https://github.com/nyamsprod", - "type": "github" - } - ], - "time": "2023-08-13T19:53:57+00:00" - }, - { - "name": "league/uri-interfaces", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", - "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.19", - "phpstan/phpstan": "^0.12.90", - "phpstan/phpstan-phpunit": "^0.12.19", - "phpstan/phpstan-strict-rules": "^0.12.9", - "phpunit/phpunit": "^8.5.15 || ^9.5" - }, - "suggest": { - "ext-intl": "to use the IDNA feature", - "symfony/intl": "to use the IDNA feature via Symfony Polyfill" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Uri\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" - } - ], - "description": "Common interface for URI representation", - "homepage": "http://github.com/thephpleague/uri-interfaces", - "keywords": [ - "rfc3986", - "rfc3987", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/thephpleague/uri-interfaces/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0" - }, - "funding": [ - { - "url": "https://github.com/sponsors/nyamsprod", - "type": "github" - } - ], - "time": "2021-06-28T04:27:21+00:00" - }, - { - "name": "monolog/monolog", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "c412c2e0d6c98525e55746294dc40413f6ffebf3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c412c2e0d6c98525e55746294dc40413f6ffebf3", - "reference": "c412c2e0d6c98525e55746294dc40413f6ffebf3", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" - }, - "provide": { - "psr/log-implementation": "3.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^3.0", - "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^7 || ^8", - "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2.0", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", - "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.1", - "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", - "symfony/mailer": "^5.4 || ^6", - "symfony/mime": "^5.4 || ^6" - }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", - "ext-mbstring": "Allow to work properly with unicode symbols", - "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", - "ext-openssl": "Required to send log messages using SSL", - "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Monolog\\": "src/Monolog" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" - } - ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "https://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], - "support": { - "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/main" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", - "type": "tidelift" - } - ], - "time": "2023-11-10T12:29:35+00:00" - }, - { - "name": "nikic/fast-route", - "version": "v1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/nikic/FastRoute.git", - "reference": "4012884e0b916e1bd895a5061d4abc3c99e283a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/FastRoute/zipball/4012884e0b916e1bd895a5061d4abc3c99e283a4", - "reference": "4012884e0b916e1bd895a5061d4abc3c99e283a4", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35|~5.7" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "FastRoute\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov", - "email": "nikic@php.net" - } - ], - "description": "Fast request router for PHP", - "keywords": [ - "router", - "routing" - ], - "support": { - "issues": "https://github.com/nikic/FastRoute/issues", - "source": "https://github.com/nikic/FastRoute/tree/v1.x" - }, - "time": "2019-12-20T12:15:33+00:00" - }, - { - "name": "nyholm/psr7", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/Nyholm/psr7.git", - "reference": "aa5fc277a4f5508013d571341ade0c3886d4d00e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7/zipball/aa5fc277a4f5508013d571341ade0c3886d4d00e", - "reference": "aa5fc277a4f5508013d571341ade0c3886d4d00e", - "shasum": "" - }, - "require": { - "php": ">=7.2", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0" - }, - "provide": { - "php-http/message-factory-implementation": "1.0", - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "http-interop/http-factory-tests": "^0.9", - "php-http/message-factory": "^1.0", - "php-http/psr7-integration-tests": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", - "symfony/error-handler": "^4.4" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Nyholm\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com" - }, - { - "name": "Martijn van der Ven", - "email": "martijn@vanderven.se" - } - ], - "description": "A fast PHP7 implementation of PSR-7", - "homepage": "https://tnyholm.se", - "keywords": [ - "psr-17", - "psr-7" - ], - "support": { - "issues": "https://github.com/Nyholm/psr7/issues", - "source": "https://github.com/Nyholm/psr7/tree/1.8.1" - }, - "funding": [ - { - "url": "https://github.com/Zegnat", - "type": "github" - }, - { - "url": "https://github.com/nyholm", - "type": "github" - } - ], - "time": "2023-11-13T09:31:12+00:00" - }, - { - "name": "open-telemetry/api", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/api.git", - "reference": "d577d732333d38a9a6c16936363ee25f1e3f1c3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/d577d732333d38a9a6c16936363ee25f1e3f1c3c", - "reference": "d577d732333d38a9a6c16936363ee25f1e3f1c3c", - "shasum": "" - }, - "require": { - "open-telemetry/context": "^1.0", - "php": "^7.4 || ^8.0", - "psr/log": "^1.1|^2.0|^3.0", - "symfony/polyfill-php80": "^1.26", - "symfony/polyfill-php81": "^1.26", - "symfony/polyfill-php82": "^1.26" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - } - }, - "autoload": { - "files": [ - "Trace/functions.php" - ], - "psr-4": { - "OpenTelemetry\\API\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "API for OpenTelemetry PHP.", - "keywords": [ - "Metrics", - "api", - "apm", - "logging", - "opentelemetry", - "otel", - "tracing" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2023-09-27T23:15:51+00:00" - }, - { - "name": "open-telemetry/context", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/context.git", - "reference": "99f3d54fa9f9ff67421774feeef5e5b1f209ea21" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/99f3d54fa9f9ff67421774feeef5e5b1f209ea21", - "reference": "99f3d54fa9f9ff67421774feeef5e5b1f209ea21", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "symfony/polyfill-php80": "^1.26", - "symfony/polyfill-php81": "^1.26", - "symfony/polyfill-php82": "^1.26" - }, - "suggest": { - "ext-ffi": "To allow context switching in Fibers" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - } - }, - "autoload": { - "files": [ - "fiber/initialize_fiber_handler.php" - ], - "psr-4": { - "OpenTelemetry\\Context\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "Context implementation for OpenTelemetry PHP.", - "keywords": [ - "Context", - "opentelemetry", - "otel" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2023-09-05T03:38:44+00:00" - }, - { - "name": "open-telemetry/sdk", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "a6ba62857154ff7207711e9dcb3f5cda73c8c3e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/a6ba62857154ff7207711e9dcb3f5cda73c8c3e8", - "reference": "a6ba62857154ff7207711e9dcb3f5cda73c8c3e8", - "shasum": "" - }, - "require": { - "ext-json": "*", - "open-telemetry/api": "^1.0", - "open-telemetry/context": "^1.0", - "open-telemetry/sem-conv": "^1.0", - "php": "^7.4 || ^8.0", - "php-http/discovery": "^1.14", - "psr/http-client": "^1.0", - "psr/http-client-implementation": "^1.0", - "psr/http-factory-implementation": "^1.0", - "psr/http-message": "^1.0.1|^2.0", - "psr/log": "^1.1|^2.0|^3.0", - "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php80": "^1.26", - "symfony/polyfill-php81": "^1.26", - "symfony/polyfill-php82": "^1.26" - }, - "suggest": { - "ext-gmp": "To support unlimited number of synchronous metric readers", - "ext-mbstring": "To increase performance of string operations" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - } - }, - "autoload": { - "files": [ - "Common/Util/functions.php", - "Logs/Exporter/_register.php", - "Metrics/MetricExporter/_register.php", - "Propagation/_register.php", - "Trace/SpanExporter/_register.php", - "Common/Dev/Compatibility/_load.php", - "_autoload.php" - ], - "psr-4": { - "OpenTelemetry\\SDK\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "SDK for OpenTelemetry PHP.", - "keywords": [ - "Metrics", - "apm", - "logging", - "opentelemetry", - "otel", - "sdk", - "tracing" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2023-11-13T22:04:22+00:00" - }, - { - "name": "open-telemetry/sem-conv", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "211039aa4667f3fbf56f970fad8bf78b6c7d5b33" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/211039aa4667f3fbf56f970fad8bf78b6c7d5b33", - "reference": "211039aa4667f3fbf56f970fad8bf78b6c7d5b33", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "OpenTelemetry\\SemConv\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "Semantic conventions for OpenTelemetry PHP.", - "keywords": [ - "Metrics", - "apm", - "logging", - "opentelemetry", - "otel", - "semantic conventions", - "semconv", - "tracing" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2023-11-07T23:26:31+00:00" - }, - { - "name": "php-http/discovery", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/php-http/discovery.git", - "reference": "57f3de01d32085fea20865f9b16fb0e69347c39e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/57f3de01d32085fea20865f9b16fb0e69347c39e", - "reference": "57f3de01d32085fea20865f9b16fb0e69347c39e", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0|^2.0", - "php": "^7.1 || ^8.0" - }, - "conflict": { - "nyholm/psr7": "<1.0", - "zendframework/zend-diactoros": "*" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "*", - "psr/http-factory-implementation": "*", - "psr/http-message-implementation": "*" - }, - "require-dev": { - "composer/composer": "^1.0.2|^2.0", - "graham-campbell/phpspec-skip-example-extension": "^5.0", - "php-http/httplug": "^1.0 || ^2.0", - "php-http/message-factory": "^1.0", - "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", - "symfony/phpunit-bridge": "^6.2" - }, - "default-branch": true, - "type": "composer-plugin", - "extra": { - "class": "Http\\Discovery\\Composer\\Plugin", - "plugin-optional": true - }, - "autoload": { - "psr-4": { - "Http\\Discovery\\": "src/" - }, - "exclude-from-classmap": [ - "src/Composer/Plugin.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" - } - ], - "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", - "homepage": "http://php-http.org", - "keywords": [ - "adapter", - "client", - "discovery", - "factory", - "http", - "message", - "psr17", - "psr7" - ], - "support": { - "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.19.1" - }, - "time": "2023-07-11T07:02:26+00:00" - }, - { - "name": "psr/container", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "707984727bd5b2b670e59559d3ed2500240cf875" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", - "reference": "707984727bd5b2b670e59559d3ed2500240cf875", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container" - }, - "time": "2023-09-22T11:11:30+00:00" - }, - { - "name": "psr/http-client", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "support": { - "source": "https://github.com/php-fig/http-client" - }, - "time": "2023-09-23T14:17:50+00:00" - }, - { - "name": "psr/http-factory", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/7037f4b0950474e9d1350e8df89b15f1842085f6", - "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, - "time": "2023-09-22T11:16:44+00:00" - }, - { - "name": "psr/http-message", - "version": "1.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" - }, - "time": "2023-04-04T09:50:52+00:00" - }, - { - "name": "psr/log", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "time": "2021-07-14T16:46:02+00:00" - }, - { - "name": "revolt/event-loop", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/revoltphp/event-loop.git", - "reference": "136e9736450e1ae6dc58e93c486e2c21a11a1214" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/136e9736450e1ae6dc58e93c486e2c21a11a1214", - "reference": "136e9736450e1ae6dc58e93c486e2c21a11a1214", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^9", - "psalm/phar": "^4.7" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Revolt\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "ceesjank@gmail.com" - }, - { - "name": "Christian Lück", - "email": "christian@clue.engineering" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Rock-solid event loop for concurrent PHP applications.", - "keywords": [ - "async", - "asynchronous", - "concurrency", - "event", - "event-loop", - "non-blocking", - "scheduler" - ], - "support": { - "issues": "https://github.com/revoltphp/event-loop/issues", - "source": "https://github.com/revoltphp/event-loop/tree/main" - }, - "time": "2023-10-31T12:54:14+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-23T14:45:45+00:00" - }, - { - "name": "symfony/http-client", - "version": "6.4.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "2e2dff5212ab9834f331060a126e7564ed7f3722" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/2e2dff5212ab9834f331060a126e7564ed7f3722", - "reference": "2e2dff5212ab9834f331060a126e7564ed7f3722", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.3" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/6.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-07T10:18:57+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "1ee70e699b41909c209a0c930f11034b93578654" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1ee70e699b41909c209a0c930f11034b93578654", - "reference": "1ee70e699b41909c209a0c930f11034b93578654", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-30T20:28:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php82", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php82.git", - "reference": "b74818475a404db4219d49aca4ea8a1626b22a6b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/b74818475a404db4219d49aca4ea8a1626b22a6b", - "reference": "b74818475a404db4219d49aca4ea8a1626b22a6b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php82\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php82/tree/1.x" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-08-28T10:07:24+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-30T20:28:31+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "amphp/http-server": 20, - "amphp/http-server-router": 20, - "amphp/log": 20, - "symfony/http-client": 20, - "nyholm/psr7": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.6.0" -} diff --git a/utils/build/docker/php/parametric/server.php b/utils/build/docker/php/parametric/server.php index 5d87f161db5..acbebf8072f 100644 --- a/utils/build/docker/php/parametric/server.php +++ b/utils/build/docker/php/parametric/server.php @@ -3,6 +3,9 @@ ini_set("datadog.trace.generate_root_span", "0"); ini_set("datadog.trace.revolt_enabled", "0"); +// Set metrics exporter before autoload +putenv('OTEL_PHP_AUTOLOAD_ENABLED=true'); + require __DIR__ . "/vendor/autoload.php"; use Amp\ByteStream; @@ -27,6 +30,8 @@ use OpenTelemetry\Context\ScopeInterface; use OpenTelemetry\SDK\Trace as SDK; use OpenTelemetry\SDK\Trace\TracerProvider; +use OpenTelemetry\API\Globals; +use OpenTelemetry\SDK\Metrics\ObserverInterface; use function Amp\trapSignal; $logHandler = new StreamHandler(ByteStream\getStdout()); @@ -108,6 +113,19 @@ function remappedSpanKind($spanKind) { $activeSpan = null; /** @var array[] $spansDistributedTracingHeaders */ $spansDistributedTracingHeaders = []; +/** @var array $otelMeters */ +$otelMeters = []; +/** @var array $otelMeterInstruments */ +$otelMeterInstruments = []; + +function normalizeInstrumentName($name) { + // Instrument names are case-insensitive per OpenTelemetry spec + return strtolower(trim($name)); +} + +function createInstrumentKey($meterName, $name, $kind, $unit, $description) { + return implode(',', [$meterName, normalizeInstrumentName($name), $kind, $unit, $description]); +} $router = new Router($server, $logger, $errorHandler); $router->addRoute('POST', '/trace/span/start', new ClosureRequestHandler(function (Request $req) use (&$spans, &$activeSpan, &$spansDistributedTracingHeaders) { @@ -546,6 +564,319 @@ function remappedSpanKind($spanKind) { return jsonResponse([]); })); +// OpenTelemetry Metrics API endpoints +$router->addRoute('POST', '/metrics/otel/get_meter', new ClosureRequestHandler(function (Request $req) use (&$otelMeters) { + $name = arg($req, 'name'); + $version = arg($req, 'version'); + $schemaUrl = arg($req, 'schema_url'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$name])) { + $meterProvider = Globals::meterProvider(); + $otelMeters[$name] = $meterProvider->getMeter( + $name, + $version, + $schemaUrl, + $attributes + ); + } + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_counter', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $counter = $meter->createCounter($normalizedName, $unit, $description); + + $instrumentKey = createInstrumentKey($meterName, $name, 'counter', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $counter; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/counter_add', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $unit = arg($req, 'unit'); + $description = arg($req, 'description'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $instrumentKey = createInstrumentKey($meterName, $name, 'counter', $unit, $description); + + if (!isset($otelMeterInstruments[$instrumentKey])) { + throw new \Exception("Instrument with identifying fields Name=$name,Kind=Counter,Unit=$unit,Description=$description not found in registered instruments for Meter=$meterName"); + } + + $counter = $otelMeterInstruments[$instrumentKey]; + $counter->add($value, $attributes); + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_updowncounter', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $counter = $meter->createUpDownCounter($normalizedName, $unit, $description); + + $instrumentKey = createInstrumentKey($meterName, $name, 'updowncounter', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $counter; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/updowncounter_add', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $unit = arg($req, 'unit'); + $description = arg($req, 'description'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $instrumentKey = createInstrumentKey($meterName, $name, 'updowncounter', $unit, $description); + + if (!isset($otelMeterInstruments[$instrumentKey])) { + throw new \Exception("Instrument with identifying fields Name=$name,Kind=UpDownCounter,Unit=$unit,Description=$description not found in registered instruments for Meter=$meterName"); + } + + $counter = $otelMeterInstruments[$instrumentKey]; + $counter->add($value, $attributes); + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_gauge', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $gauge = $meter->createGauge($normalizedName, $unit, $description); + + $instrumentKey = createInstrumentKey($meterName, $name, 'gauge', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $gauge; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/gauge_record', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $unit = arg($req, 'unit'); + $description = arg($req, 'description'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $instrumentKey = createInstrumentKey($meterName, $name, 'gauge', $unit, $description); + + if (!isset($otelMeterInstruments[$instrumentKey])) { + throw new \Exception("Instrument with identifying fields Name=$name,Kind=Gauge,Unit=$unit,Description=$description not found in registered instruments for Meter=$meterName"); + } + + $gauge = $otelMeterInstruments[$instrumentKey]; + $gauge->record($value, $attributes); + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_histogram', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $histogram = $meter->createHistogram($normalizedName, $unit, $description); + + $instrumentKey = createInstrumentKey($meterName, $name, 'histogram', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $histogram; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/histogram_record', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $unit = arg($req, 'unit'); + $description = arg($req, 'description'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $instrumentKey = createInstrumentKey($meterName, $name, 'histogram', $unit, $description); + + if (!isset($otelMeterInstruments[$instrumentKey])) { + throw new \Exception("Instrument with identifying fields Name=$name,Kind=Histogram,Unit=$unit,Description=$description not found in registered instruments for Meter=$meterName"); + } + + $histogram = $otelMeterInstruments[$instrumentKey]; + $histogram->record($value, $attributes); + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_asynchronous_counter', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + + // Create a callback function that returns the constant value + // Note: The observer parameter is not type-hinted to avoid type mismatch with MultiObserver + $callback = function ($observer) use ($value, $attributes) { + $observer->observe($value, $attributes); + }; + + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $observableCounter = $meter->createObservableCounter($normalizedName, $unit, $description, [], $callback); + + $instrumentKey = createInstrumentKey($meterName, $name, 'observable_counter', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $observableCounter; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_asynchronous_updowncounter', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + + // Create a callback function that returns the constant value + // Note: The observer parameter is not type-hinted to avoid type mismatch with MultiObserver + $callback = function ($observer) use ($value, $attributes) { + $observer->observe($value, $attributes); + }; + + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $observableUpDownCounter = $meter->createObservableUpDownCounter($normalizedName, $unit, $description, [], $callback); + + $instrumentKey = createInstrumentKey($meterName, $name, 'observable_updowncounter', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $observableUpDownCounter; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/create_asynchronous_gauge', new ClosureRequestHandler(function (Request $req) use (&$otelMeters, &$otelMeterInstruments) { + $meterName = arg($req, 'meter_name'); + $name = arg($req, 'name'); + $description = arg($req, 'description'); + $unit = arg($req, 'unit'); + $value = arg($req, 'value'); + $attributes = arg($req, 'attributes'); + + if (!isset($otelMeters[$meterName])) { + throw new \Exception("Meter name $meterName not found in registered meters"); + } + + $meter = $otelMeters[$meterName]; + + // Create a callback function that returns the constant value + // Note: The observer parameter is not type-hinted to avoid type mismatch with MultiObserver + $callback = function ($observer) use ($value, $attributes) { + $observer->observe($value, $attributes); + }; + + // Normalize instrument name (case-insensitive per OpenTelemetry spec) + $normalizedName = normalizeInstrumentName($name); + $observableGauge = $meter->createObservableGauge($normalizedName, $unit, $description, [], $callback); + + $instrumentKey = createInstrumentKey($meterName, $name, 'observable_gauge', $unit, $description); + $otelMeterInstruments[$instrumentKey] = $observableGauge; + + return jsonResponse([]); +})); + +$router->addRoute('POST', '/metrics/otel/force_flush', new ClosureRequestHandler(function (Request $req) { + $meterProvider = Globals::meterProvider(); + + // Since force_flush is not part of the public API, we check if the + // meter provider has a forceFlush method. + // If OpenTelemetry metrics is disabled, the meter provider will be + // a default proxy provided by the API which does not have the method. + try { + if (method_exists($meterProvider, 'forceFlush')) { + error_log("flushing metrics"); + $meterProvider->forceFlush(); + } + + // Also flush telemetry (including OTel configurations) + // PHP telemetry is sent at request shutdown, so we need to manually trigger it + \dd_trace_internal_fn('finalize_telemetry'); + + return jsonResponse(['success' => true]); + } catch (exception $e) { + print $e; + } +})); + $middleware = new class implements Middleware { public function handleRequest(Request $request, RequestHandler $next): Response { $response = $next->handleRequest($request);