From 1386c52137c290d721455816b6a9f429bd5f8b5c Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 17 Nov 2025 12:56:26 -0500 Subject: [PATCH 1/8] [PHP]: OpenTelemetry metrics support --- manifests/php.yml | 1 - tests/parametric/test_otel_metrics.py | 207 +- .../_scenarios/integration_frameworks.py | 2 +- utils/_context/_scenarios/parametric.py | 2 +- utils/_context/containers.py | 2 +- utils/build/docker/php/parametric/Dockerfile | 4 +- .../build/docker/php/parametric/composer.json | 15 +- .../build/docker/php/parametric/composer.lock | 3146 ----------------- utils/build/docker/php/parametric/server.php | 332 +- utils/docker_fixtures/_test_agent.py | 2 +- .../k8s_datadog_kubernetes.py | 2 +- utils/parametric/_library_client.py | 13 +- 12 files changed, 476 insertions(+), 3252 deletions(-) delete mode 100644 utils/build/docker/php/parametric/composer.lock diff --git a/manifests/php.yml b/manifests/php.yml index 5e21c05c2c0..6bd6b3ccf78 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -588,7 +588,6 @@ tests/: test_otel_env_vars.py: Test_Otel_Env_Vars: v1.1.0 test_otel_logs.py: missing_feature - test_otel_metrics.py: missing_feature test_otel_span_methods.py: Test_Otel_Span_Methods: v0.94.0 test_otel_span_with_baggage.py: diff --git a/tests/parametric/test_otel_metrics.py b/tests/parametric/test_otel_metrics.py index 956feb4cd7d..f87907e90bb 100644 --- a/tests/parametric/test_otel_metrics.py +++ b/tests/parametric/test_otel_metrics.py @@ -194,13 +194,13 @@ def get_expected_bucket_counts(entries: list[int], bucket_boundaries: list[float @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_Enabled: """Tests the enablement and disablement of the OTel Metrics API through the following configurations: - DD_METRICS_OTEL_ENABLED @@ -266,13 +266,13 @@ def test_otlp_metrics_disabled( @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Api_MeterProvider: """Tests the OpenTelemetry MeterProvider API functionality. @@ -340,13 +340,13 @@ def test_otel_get_meter_by_distinct( @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Api_Meter: """Tests the OpenTelemetry Meter API functionality. @@ -358,6 +358,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, library_env: dict[str, str] ): @@ -561,13 +562,13 @@ def test_otel_create_instruments_by_distinct( @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Api_Instrument: """Tests the OpenTelemetry Instrument API functionality. @@ -580,6 +581,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 ): @@ -874,6 +876,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 ): @@ -937,9 +940,8 @@ def test_otel_histogram_add_non_negative_and_negative_values( ) @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) - def test_otel_histogram_add_non_negative_values_with_different_tags( - self, test_agent: TestAgentAPI, test_library: APMLibrary - ): + @pytest.mark.skip(reason="but in min and max") + def test_otel_histogram_add_non_negative_values_with_different_tags(self, test_agent, test_library): non_negative_value1 = 42 non_negative_value2 = 21 name = f"histogram-{non_negative_value1}-{non_negative_value2}-different-tags" @@ -1105,13 +1107,13 @@ def test_otel_asynchronous_gauge_constant_callback_value(self, test_agent: TestA @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Bug in otel php sdk, #1766", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_Temporality_Preference: """Tests the OpenTelemetry metrics aggregation temporality preference configuration. @@ -1132,6 +1134,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 ): @@ -1298,13 +1301,13 @@ def test_otel_aggregation_temporality( @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_OTLP_Exporter_Metrics_Endpoint: """Tests the OpenTelemetry OTLP exporter metrics endpoint configuration. @@ -1419,6 +1422,7 @@ def test_otlp_metrics_custom_endpoint_http_protobuf( assert scope_metrics is not None @missing_feature(context.library == "nodejs", reason="Does not support grpc") + @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"), [ @@ -1457,13 +1461,13 @@ def test_otlp_metrics_custom_endpoint_grpc( @features.otel_metrics_api @scenarios.parametric -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_OTLP_Exporter_Metrics_Headers: """Tests the OpenTelemetry OTLP exporter metrics headers configuration. @@ -1540,13 +1544,13 @@ def test_custom_metrics_http_headers_included_in_otlp_export( @features.otel_metrics_api @scenarios.parametric -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_OTLP_Exporter_Metrics_Protocol: """Tests the OpenTelemetry OTLP exporter metrics protocol configuration. @@ -1618,14 +1622,14 @@ def test_otlp_protocol_grpc(self, test_agent: TestAgentAPI, test_library: APMLib @features.otel_metrics_api @scenarios.parametric -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "nodejs", reason="Does not support DD_HOSTNAME") -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "nodejs", reason="Does not support DD_HOSTNAME") +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Host_Name: """Tests the OpenTelemetry metrics host name configuration. @@ -1641,6 +1645,7 @@ class Test_Otel_Metrics_Host_Name: **DEFAULT_ENVVARS, "DD_HOSTNAME": "ddhostname", "DD_TRACE_REPORT_HOSTNAME": "true", + "OTEL_PHP_DETECTORS": "all", }, ], ) @@ -1655,7 +1660,12 @@ def test_hostname_from_dd_hostname( 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" @@ -1684,7 +1694,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" @@ -1713,20 +1728,25 @@ 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 @scenarios.parametric @features.otel_metrics_api -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Resource_Attributes: """Tests the OpenTelemetry metrics resource attributes configuration. @@ -1761,7 +1781,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 @@ -1822,7 +1847,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 @@ -1860,7 +1890,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 @@ -1872,13 +1907,13 @@ def test_dd_env_vars_override_otel(self, test_agent: TestAgentAPI, test_library: @features.otel_metrics_api @scenarios.parametric -@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Telemetry: """Tests the OpenTelemetry metrics telemetry configuration reporting. diff --git a/utils/_context/_scenarios/integration_frameworks.py b/utils/_context/_scenarios/integration_frameworks.py index 93876be47f1..a7538c9241e 100644 --- a/utils/_context/_scenarios/integration_frameworks.py +++ b/utils/_context/_scenarios/integration_frameworks.py @@ -21,7 +21,7 @@ def __init__(self, name: str, doc: str) -> None: name, doc=doc, github_workflow="endtoend", - agent_image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.36.0", + agent_image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.0", ) self.environment = { diff --git a/utils/_context/_scenarios/parametric.py b/utils/_context/_scenarios/parametric.py index f782e321cf2..679fc85722e 100644 --- a/utils/_context/_scenarios/parametric.py +++ b/utils/_context/_scenarios/parametric.py @@ -66,7 +66,7 @@ def __init__(self, name: str, doc: str) -> None: doc=doc, github_workflow="parametric", scenario_groups=(scenario_groups.parametric,), - agent_image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.32.0", + agent_image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.0", ) self._parametric_tests_confs = ParametricScenario.PersistentParametricTestConf(self) diff --git a/utils/_context/containers.py b/utils/_context/containers.py index cdeb2e00d55..e5b5acf9f99 100644 --- a/utils/_context/containers.py +++ b/utils/_context/containers.py @@ -1320,7 +1320,7 @@ def start(self, network: Network) -> Container: class APMTestAgentContainer(TestedContainer): def __init__(self, agent_port: int = 8126) -> None: super().__init__( - image_name="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.20.0", + image_name="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.0", name="ddapm-test-agent", environment={ "SNAPSHOT_CI": "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 2ff91ca0a5f..29ba3392166 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; @@ -26,6 +29,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()); @@ -107,6 +112,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) { @@ -535,10 +553,322 @@ 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); - dd_trace_internal_fn("finalize_telemetry"); return $response; } }; diff --git a/utils/docker_fixtures/_test_agent.py b/utils/docker_fixtures/_test_agent.py index 8d51da12a8f..37df43ad9b7 100644 --- a/utils/docker_fixtures/_test_agent.py +++ b/utils/docker_fixtures/_test_agent.py @@ -665,7 +665,7 @@ def wait_for_telemetry_metrics(self, metric_name: str | None = None, *, clear: b for _ in range(wait_loops): for event in self.telemetry(clear=False): telemetry_event = self._get_telemetry_event(event, "generate-metrics") - logger.debug("Found telemetry event: %s", telemetry_event) + # logger.debug("Found telemetry event: %s", telemetry_event) if telemetry_event is None: continue for series in telemetry_event["payload"]["series"]: diff --git a/utils/k8s_lib_injection/k8s_datadog_kubernetes.py b/utils/k8s_lib_injection/k8s_datadog_kubernetes.py index 37002b98ecc..fe56752f7af 100644 --- a/utils/k8s_lib_injection/k8s_datadog_kubernetes.py +++ b/utils/k8s_lib_injection/k8s_datadog_kubernetes.py @@ -44,7 +44,7 @@ def deploy_test_agent(self, namespace="default"): container = client.V1Container( name="trace-agent", - image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.31.1", + image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.1", image_pull_policy="Always", ports=[client.V1ContainerPort(container_port=8126, host_port=8126, name="traceport", protocol="TCP")], command=["ddapm-test-agent"], diff --git a/utils/parametric/_library_client.py b/utils/parametric/_library_client.py index 2df0e52a699..6035e4e5f99 100644 --- a/utils/parametric/_library_client.py +++ b/utils/parametric/_library_client.py @@ -278,14 +278,17 @@ def trace_extract_headers(self, http_headers: Iterable[tuple[str, str]]): return resp.json()["span_id"] def trace_flush(self) -> bool: - r = self._session.post(self._url("/trace/span/flush"), json={}) + try: + r = self._session.post(self._url("/trace/span/flush"), json={}) - if not HTTPStatus(r.status_code).is_success: - return False + if not HTTPStatus(r.status_code).is_success: + return False - r = self._session.post(self._url("/trace/stats/flush"), json={}) + r = self._session.post(self._url("/trace/stats/flush"), json={}) - return HTTPStatus(r.status_code).is_success + return HTTPStatus(r.status_code).is_success + except: + return True def write_log( self, message: str, level: LogLevel, logger_name: str = "test_logger", logger_type: int = 0, span_id: int = 0 From 7d087d9abeb777b4716f6464fcae2a2c633f2990 Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 17 Nov 2025 13:06:55 -0500 Subject: [PATCH 2/8] undo test agent files --- utils/_context/_scenarios/integration_frameworks.py | 2 +- utils/_context/containers.py | 2 +- utils/docker_fixtures/_test_agent.py | 2 +- utils/k8s_lib_injection/k8s_datadog_kubernetes.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/_context/_scenarios/integration_frameworks.py b/utils/_context/_scenarios/integration_frameworks.py index a7538c9241e..93876be47f1 100644 --- a/utils/_context/_scenarios/integration_frameworks.py +++ b/utils/_context/_scenarios/integration_frameworks.py @@ -21,7 +21,7 @@ def __init__(self, name: str, doc: str) -> None: name, doc=doc, github_workflow="endtoend", - agent_image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.0", + agent_image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.36.0", ) self.environment = { diff --git a/utils/_context/containers.py b/utils/_context/containers.py index e5b5acf9f99..cdeb2e00d55 100644 --- a/utils/_context/containers.py +++ b/utils/_context/containers.py @@ -1320,7 +1320,7 @@ def start(self, network: Network) -> Container: class APMTestAgentContainer(TestedContainer): def __init__(self, agent_port: int = 8126) -> None: super().__init__( - image_name="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.0", + image_name="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.20.0", name="ddapm-test-agent", environment={ "SNAPSHOT_CI": "0", diff --git a/utils/docker_fixtures/_test_agent.py b/utils/docker_fixtures/_test_agent.py index 37df43ad9b7..8d51da12a8f 100644 --- a/utils/docker_fixtures/_test_agent.py +++ b/utils/docker_fixtures/_test_agent.py @@ -665,7 +665,7 @@ def wait_for_telemetry_metrics(self, metric_name: str | None = None, *, clear: b for _ in range(wait_loops): for event in self.telemetry(clear=False): telemetry_event = self._get_telemetry_event(event, "generate-metrics") - # logger.debug("Found telemetry event: %s", telemetry_event) + logger.debug("Found telemetry event: %s", telemetry_event) if telemetry_event is None: continue for series in telemetry_event["payload"]["series"]: diff --git a/utils/k8s_lib_injection/k8s_datadog_kubernetes.py b/utils/k8s_lib_injection/k8s_datadog_kubernetes.py index fe56752f7af..37002b98ecc 100644 --- a/utils/k8s_lib_injection/k8s_datadog_kubernetes.py +++ b/utils/k8s_lib_injection/k8s_datadog_kubernetes.py @@ -44,7 +44,7 @@ def deploy_test_agent(self, namespace="default"): container = client.V1Container( name="trace-agent", - image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.37.1", + image="ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:v1.31.1", image_pull_policy="Always", ports=[client.V1ContainerPort(container_port=8126, host_port=8126, name="traceport", protocol="TCP")], command=["ddapm-test-agent"], From 93c55b1e1c1f8d4f96d918777cb5e531cae2b237 Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 17 Nov 2025 13:28:27 -0500 Subject: [PATCH 3/8] cleanup --- tests/parametric/test_otel_metrics.py | 144 ++++++++++++-------------- 1 file changed, 67 insertions(+), 77 deletions(-) diff --git a/tests/parametric/test_otel_metrics.py b/tests/parametric/test_otel_metrics.py index f87907e90bb..2116a3ed041 100644 --- a/tests/parametric/test_otel_metrics.py +++ b/tests/parametric/test_otel_metrics.py @@ -194,13 +194,12 @@ def get_expected_bucket_counts(entries: list[int], bucket_boundaries: list[float @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_Enabled: """Tests the enablement and disablement of the OTel Metrics API through the following configurations: - DD_METRICS_OTEL_ENABLED @@ -266,13 +265,12 @@ def test_otlp_metrics_disabled( @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Api_MeterProvider: """Tests the OpenTelemetry MeterProvider API functionality. @@ -340,13 +338,12 @@ def test_otel_get_meter_by_distinct( @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Api_Meter: """Tests the OpenTelemetry Meter API functionality. @@ -562,13 +559,12 @@ def test_otel_create_instruments_by_distinct( @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Api_Instrument: """Tests the OpenTelemetry Instrument API functionality. @@ -1107,13 +1103,12 @@ def test_otel_asynchronous_gauge_constant_callback_value(self, test_agent: TestA @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Bug in otel php sdk, #1766", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_Temporality_Preference: """Tests the OpenTelemetry metrics aggregation temporality preference configuration. @@ -1301,13 +1296,12 @@ def test_otel_aggregation_temporality( @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_OTLP_Exporter_Metrics_Endpoint: """Tests the OpenTelemetry OTLP exporter metrics endpoint configuration. @@ -1461,13 +1455,12 @@ def test_otlp_metrics_custom_endpoint_grpc( @features.otel_metrics_api @scenarios.parametric -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_OTLP_Exporter_Metrics_Headers: """Tests the OpenTelemetry OTLP exporter metrics headers configuration. @@ -1544,13 +1537,12 @@ def test_custom_metrics_http_headers_included_in_otlp_export( @features.otel_metrics_api @scenarios.parametric -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Configuration_OTLP_Exporter_Metrics_Protocol: """Tests the OpenTelemetry OTLP exporter metrics protocol configuration. @@ -1622,14 +1614,13 @@ def test_otlp_protocol_grpc(self, test_agent: TestAgentAPI, test_library: APMLib @features.otel_metrics_api @scenarios.parametric -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "nodejs", reason="Does not support DD_HOSTNAME") -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "nodejs", reason="Does not support DD_HOSTNAME") +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Host_Name: """Tests the OpenTelemetry metrics host name configuration. @@ -1740,13 +1731,12 @@ def test_hostname_omitted(self, test_agent: TestAgentAPI, test_library: APMLibra @scenarios.parametric @features.otel_metrics_api -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Resource_Attributes: """Tests the OpenTelemetry metrics resource attributes configuration. @@ -1907,13 +1897,13 @@ def test_dd_env_vars_override_otel(self, test_agent: TestAgentAPI, test_library: @features.otel_metrics_api @scenarios.parametric -# @missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "cpp", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "dotnet", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "golang", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "java", reason="Not yet implemented", force_skip=True) @missing_feature(context.library == "php", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) -# @missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "ruby", reason="Not yet implemented", force_skip=True) +@missing_feature(context.library == "rust", reason="Not yet implemented", force_skip=True) class Test_Otel_Metrics_Telemetry: """Tests the OpenTelemetry metrics telemetry configuration reporting. From 409e5bba57dd18558e90f17a9ae46afbeb3096e7 Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 17 Nov 2025 13:29:46 -0500 Subject: [PATCH 4/8] typo --- tests/parametric/test_otel_metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parametric/test_otel_metrics.py b/tests/parametric/test_otel_metrics.py index 2116a3ed041..5a023712317 100644 --- a/tests/parametric/test_otel_metrics.py +++ b/tests/parametric/test_otel_metrics.py @@ -936,7 +936,7 @@ def test_otel_histogram_add_non_negative_and_negative_values( ) @pytest.mark.parametrize("library_env", [{**DEFAULT_ENVVARS}]) - @pytest.mark.skip(reason="but in min and max") + @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, test_library): non_negative_value1 = 42 non_negative_value2 = 21 From 449d6bf44a53857f17e7801b46fb8197396016c9 Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 17 Nov 2025 13:57:57 -0500 Subject: [PATCH 5/8] linting errors --- tests/parametric/test_otel_metrics.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/parametric/test_otel_metrics.py b/tests/parametric/test_otel_metrics.py index 5a023712317..76bc58d2512 100644 --- a/tests/parametric/test_otel_metrics.py +++ b/tests/parametric/test_otel_metrics.py @@ -937,7 +937,9 @@ 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, test_library): + def test_otel_histogram_add_non_negative_values_with_different_tags( + self, test_agent: TestAgentAPI, test_library: APMLibrary + ): non_negative_value1 = 42 non_negative_value2 = 21 name = f"histogram-{non_negative_value1}-{non_negative_value2}-different-tags" From 2c5ed609978f7d79aff7d8578020895dd1917304 Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 12 Jan 2026 10:58:56 -0500 Subject: [PATCH 6/8] linting --- .../_test_clients/_test_client_parametric.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/utils/docker_fixtures/_test_clients/_test_client_parametric.py b/utils/docker_fixtures/_test_clients/_test_client_parametric.py index 11c1eb8fab9..0dd07dd207b 100644 --- a/utils/docker_fixtures/_test_clients/_test_client_parametric.py +++ b/utils/docker_fixtures/_test_clients/_test_client_parametric.py @@ -495,14 +495,12 @@ def dd_extract_headers(self, http_headers: Iterable[tuple[str, str]]): def dd_flush(self) -> bool: r = self._session.post(self._url("/trace/span/flush"), json={}) - if not HTTPStatus(r.status_code).is_success: - return False + if not HTTPStatus(r.status_code).is_success: + return False - r = self._session.post(self._url("/trace/stats/flush"), json={}) + r = self._session.post(self._url("/trace/stats/flush"), json={}) - return HTTPStatus(r.status_code).is_success - except: - return True + return HTTPStatus(r.status_code).is_success def write_log( self, message: str, level: LogLevel, logger_name: str = "test_logger", logger_type: int = 0, span_id: int = 0 From 53624f8befa84c26da6bdd4f3a79337766736337 Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Mon, 12 Jan 2026 16:26:05 -0500 Subject: [PATCH 7/8] fix failing tests --- utils/build/docker/php/parametric/server.php | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/build/docker/php/parametric/server.php b/utils/build/docker/php/parametric/server.php index 8e0fa6f97b9..acbebf8072f 100644 --- a/utils/build/docker/php/parametric/server.php +++ b/utils/build/docker/php/parametric/server.php @@ -880,6 +880,7 @@ function createInstrumentKey($meterName, $name, $kind, $unit, $description) { $middleware = new class implements Middleware { public function handleRequest(Request $request, RequestHandler $next): Response { $response = $next->handleRequest($request); + dd_trace_internal_fn("finalize_telemetry"); return $response; } }; From 23a01a8611c3c5ef495b2b5c830fa5828c571dbc Mon Sep 17 00:00:00 2001 From: Rachel Yang Date: Thu, 15 Jan 2026 12:30:37 -0500 Subject: [PATCH 8/8] lint issues --- tests/parametric/test_otel_metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parametric/test_otel_metrics.py b/tests/parametric/test_otel_metrics.py index a05ecdb547f..c6301f93fb1 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