Skip to content

Commit 10d2347

Browse files
authored
feat: add runtime context to improve support for FrankenPHP and RoadRunner (#2011)
1 parent 9f8eff4 commit 10d2347

34 files changed

Lines changed: 1595 additions & 38 deletions

.github/workflows/ci.yml

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ on:
1010
permissions:
1111
contents: read
1212

13+
env:
14+
FRANKENPHP_VERSION: v1.11.2
15+
ROADRUNNER_VERSION: v2025.1.7
16+
1317
# Cancel in progress workflows on pull_requests.
1418
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value
1519
concurrency:
@@ -71,6 +75,10 @@ jobs:
7175
- name: Remove unused dependencies
7276
run: composer remove vimeo/psalm phpstan/phpstan friendsofphp/php-cs-fixer --dev --no-interaction --no-update
7377

78+
- name: Remove RoadRunner dependencies on unsupported PHP versions
79+
if: ${{ matrix.os == 'windows-latest' || matrix.php.version == '7.2' || matrix.php.version == '7.3' || matrix.php.version == '7.4' || matrix.php.version == '8.0' }}
80+
run: composer remove spiral/roadrunner-http spiral/roadrunner-worker --dev --no-interaction --no-update
81+
7482
- name: Set phpunit/phpunit version constraint
7583
run: composer require phpunit/phpunit:'${{ matrix.php.phpunit }}' --dev --no-interaction --no-update
7684

@@ -96,3 +104,138 @@ jobs:
96104
- name: Check benchmarks
97105
run: vendor/bin/phpbench run --revs=1 --iterations=1
98106
if: ${{ matrix.dependencies == 'highest' && matrix.php.version == '8.4' }}
107+
108+
runtime-tests-frankenphp:
109+
name: Runtime tests (FrankenPHP)
110+
runs-on: ubuntu-latest
111+
112+
steps:
113+
- name: Checkout
114+
uses: actions/checkout@v6
115+
with:
116+
fetch-depth: 2
117+
118+
- name: Setup PHP
119+
uses: shivammathur/setup-php@v2
120+
with:
121+
php-version: '8.4'
122+
coverage: none
123+
124+
- name: Determine Composer cache directory
125+
id: composer-cache
126+
run: echo "directory=$(composer config cache-dir)" >> "$GITHUB_OUTPUT"
127+
shell: bash
128+
129+
- name: Cache Composer dependencies
130+
uses: actions/cache@v5
131+
with:
132+
path: ${{ steps.composer-cache.outputs.directory }}
133+
key: ${{ runner.os }}-runtime-frankenphp-composer-${{ hashFiles('**/composer.lock') }}
134+
restore-keys: ${{ runner.os }}-runtime-frankenphp-composer-
135+
136+
- name: Install dependencies
137+
run: composer install --no-progress --no-interaction --prefer-dist
138+
139+
- name: Install FrankenPHP
140+
env:
141+
GH_TOKEN: ${{ github.token }}
142+
run: |
143+
set -euo pipefail
144+
145+
case "$(uname -m)" in
146+
x86_64) asset="frankenphp-linux-x86_64" ;;
147+
aarch64|arm64) asset="frankenphp-linux-aarch64" ;;
148+
*) echo "Unsupported architecture: $(uname -m)"; exit 1 ;;
149+
esac
150+
151+
digest="$(gh api "repos/php/frankenphp/releases/tags/${FRANKENPHP_VERSION}" --jq ".assets[] | select(.name == \"${asset}\") | .digest")"
152+
153+
if [ -z "${digest}" ]; then
154+
echo "Unable to resolve digest for ${asset} (${FRANKENPHP_VERSION})."
155+
exit 1
156+
fi
157+
158+
gh release download "${FRANKENPHP_VERSION}" \
159+
--repo php/frankenphp \
160+
--pattern "${asset}" \
161+
--output "${asset}"
162+
163+
echo "${digest#sha256:} ${asset}" | sha256sum --check --
164+
mkdir -p "${RUNNER_TEMP}/bin"
165+
install -m 0755 "${asset}" "${RUNNER_TEMP}/bin/frankenphp"
166+
echo "${RUNNER_TEMP}/bin" >> "${GITHUB_PATH}"
167+
"${RUNNER_TEMP}/bin/frankenphp" version
168+
shell: bash
169+
170+
- name: Run PHPUnit tests (excluding PHPT)
171+
run: vendor/bin/phpunit tests --test-suffix Test.php --verbose
172+
173+
runtime-tests-roadrunner:
174+
name: Runtime tests (RoadRunner)
175+
runs-on: ubuntu-latest
176+
177+
steps:
178+
- name: Checkout
179+
uses: actions/checkout@v6
180+
with:
181+
fetch-depth: 2
182+
183+
- name: Setup PHP
184+
uses: shivammathur/setup-php@v2
185+
with:
186+
php-version: '8.4'
187+
coverage: none
188+
189+
- name: Determine Composer cache directory
190+
id: composer-cache
191+
run: echo "directory=$(composer config cache-dir)" >> "$GITHUB_OUTPUT"
192+
shell: bash
193+
194+
- name: Cache Composer dependencies
195+
uses: actions/cache@v5
196+
with:
197+
path: ${{ steps.composer-cache.outputs.directory }}
198+
key: ${{ runner.os }}-runtime-roadrunner-composer-${{ hashFiles('**/composer.lock') }}
199+
restore-keys: ${{ runner.os }}-runtime-roadrunner-composer-
200+
201+
- name: Install dependencies
202+
run: composer install --no-progress --no-interaction --prefer-dist
203+
204+
- name: Install RoadRunner
205+
env:
206+
GH_TOKEN: ${{ github.token }}
207+
run: |
208+
set -euo pipefail
209+
210+
case "$(uname -m)" in
211+
x86_64) arch="amd64" ;;
212+
aarch64|arm64) arch="arm64" ;;
213+
*) echo "Unsupported architecture: $(uname -m)"; exit 1 ;;
214+
esac
215+
216+
version_no_prefix="${ROADRUNNER_VERSION#v}"
217+
asset="roadrunner-${version_no_prefix}-linux-${arch}.tar.gz"
218+
219+
digest="$(gh api "repos/roadrunner-server/roadrunner/releases/tags/${ROADRUNNER_VERSION}" --jq ".assets[] | select(.name == \"${asset}\") | .digest")"
220+
221+
if [ -z "${digest}" ]; then
222+
echo "Unable to resolve digest for ${asset} (${ROADRUNNER_VERSION})."
223+
exit 1
224+
fi
225+
226+
gh release download "${ROADRUNNER_VERSION}" \
227+
--repo roadrunner-server/roadrunner \
228+
--pattern "${asset}" \
229+
--output "${asset}"
230+
231+
echo "${digest#sha256:} ${asset}" | sha256sum --check --
232+
tar -xzf "${asset}" --strip-components=1 "${asset%.tar.gz}/rr"
233+
mkdir -p "${RUNNER_TEMP}/bin"
234+
install -m 0755 rr "${RUNNER_TEMP}/bin/rr"
235+
echo "${RUNNER_TEMP}/bin" >> "${GITHUB_PATH}"
236+
"${RUNNER_TEMP}/bin/rr" --version
237+
shell: bash
238+
239+
- name: Run PHPUnit tests (excluding PHPT)
240+
run: vendor/bin/phpunit tests --test-suffix Test.php --verbose
241+

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
"guzzlehttp/promises": "^2.0.3",
3737
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
3838
"monolog/monolog": "^1.6|^2.0|^3.0",
39+
"nyholm/psr7": "^1.8",
3940
"phpbench/phpbench": "^1.0",
4041
"phpstan/phpstan": "^1.3",
4142
"phpunit/phpunit": "^8.5.52|^9.6.34",
43+
"spiral/roadrunner-http": "^3.6",
44+
"spiral/roadrunner-worker": "^3.6",
4245
"vimeo/psalm": "^4.17"
4346
},
4447
"suggest": {

src/Logs/Logs.php

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Sentry\Logs;
66

77
use Sentry\EventId;
8+
use Sentry\SentrySdk;
89

910
class Logs
1011
{
@@ -13,14 +14,8 @@ class Logs
1314
*/
1415
private static $instance;
1516

16-
/**
17-
* @var LogsAggregator
18-
*/
19-
private $aggregator;
20-
2117
private function __construct()
2218
{
23-
$this->aggregator = new LogsAggregator();
2419
}
2520

2621
public static function getInstance(): self
@@ -39,7 +34,7 @@ public static function getInstance(): self
3934
*/
4035
public function trace(string $message, array $values = [], array $attributes = []): void
4136
{
42-
$this->aggregator->add(LogLevel::trace(), $message, $values, $attributes);
37+
$this->aggregator()->add(LogLevel::trace(), $message, $values, $attributes);
4338
}
4439

4540
/**
@@ -49,7 +44,7 @@ public function trace(string $message, array $values = [], array $attributes = [
4944
*/
5045
public function debug(string $message, array $values = [], array $attributes = []): void
5146
{
52-
$this->aggregator->add(LogLevel::debug(), $message, $values, $attributes);
47+
$this->aggregator()->add(LogLevel::debug(), $message, $values, $attributes);
5348
}
5449

5550
/**
@@ -59,7 +54,7 @@ public function debug(string $message, array $values = [], array $attributes = [
5954
*/
6055
public function info(string $message, array $values = [], array $attributes = []): void
6156
{
62-
$this->aggregator->add(LogLevel::info(), $message, $values, $attributes);
57+
$this->aggregator()->add(LogLevel::info(), $message, $values, $attributes);
6358
}
6459

6560
/**
@@ -69,7 +64,7 @@ public function info(string $message, array $values = [], array $attributes = []
6964
*/
7065
public function warn(string $message, array $values = [], array $attributes = []): void
7166
{
72-
$this->aggregator->add(LogLevel::warn(), $message, $values, $attributes);
67+
$this->aggregator()->add(LogLevel::warn(), $message, $values, $attributes);
7368
}
7469

7570
/**
@@ -79,7 +74,7 @@ public function warn(string $message, array $values = [], array $attributes = []
7974
*/
8075
public function error(string $message, array $values = [], array $attributes = []): void
8176
{
82-
$this->aggregator->add(LogLevel::error(), $message, $values, $attributes);
77+
$this->aggregator()->add(LogLevel::error(), $message, $values, $attributes);
8378
}
8479

8580
/**
@@ -89,15 +84,15 @@ public function error(string $message, array $values = [], array $attributes = [
8984
*/
9085
public function fatal(string $message, array $values = [], array $attributes = []): void
9186
{
92-
$this->aggregator->add(LogLevel::fatal(), $message, $values, $attributes);
87+
$this->aggregator()->add(LogLevel::fatal(), $message, $values, $attributes);
9388
}
9489

9590
/**
9691
* Flush the captured logs and send them to Sentry.
9792
*/
9893
public function flush(): ?EventId
9994
{
100-
return $this->aggregator->flush();
95+
return $this->aggregator()->flush();
10196
}
10297

10398
/**
@@ -107,6 +102,6 @@ public function flush(): ?EventId
107102
*/
108103
public function aggregator(): LogsAggregator
109104
{
110-
return $this->aggregator;
105+
return SentrySdk::getCurrentRuntimeContext()->getLogsAggregator();
111106
}
112107
}

src/Logs/LogsAggregator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,13 @@ public function add(
154154
$this->logs[] = $log;
155155
}
156156

157-
public function flush(): ?EventId
157+
public function flush(?HubInterface $hub = null): ?EventId
158158
{
159159
if (empty($this->logs)) {
160160
return null;
161161
}
162162

163-
$hub = SentrySdk::getCurrentHub();
163+
$hub = $hub ?? SentrySdk::getCurrentHub();
164164
$event = Event::createLogs()->setLogs($this->logs);
165165

166166
$this->logs = [];

src/Metrics/MetricsAggregator.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Sentry\Metrics\Types\GaugeMetric;
1313
use Sentry\Metrics\Types\Metric;
1414
use Sentry\SentrySdk;
15+
use Sentry\State\HubInterface;
1516
use Sentry\State\Scope;
1617
use Sentry\Unit;
1718
use Sentry\Util\RingBuffer;
@@ -134,13 +135,13 @@ public function add(
134135
$this->metrics->push($metric);
135136
}
136137

137-
public function flush(): ?EventId
138+
public function flush(?HubInterface $hub = null): ?EventId
138139
{
139140
if ($this->metrics->isEmpty()) {
140141
return null;
141142
}
142143

143-
$hub = SentrySdk::getCurrentHub();
144+
$hub = $hub ?? SentrySdk::getCurrentHub();
144145
$event = Event::createMetrics()->setMetrics($this->metrics->drain());
145146

146147
return $hub->captureEvent($event);

src/Metrics/TraceMetrics.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Sentry\Metrics\Types\CounterMetric;
99
use Sentry\Metrics\Types\DistributionMetric;
1010
use Sentry\Metrics\Types\GaugeMetric;
11+
use Sentry\SentrySdk;
1112
use Sentry\Unit;
1213

1314
class TraceMetrics
@@ -17,14 +18,8 @@ class TraceMetrics
1718
*/
1819
private static $instance;
1920

20-
/**
21-
* @var MetricsAggregator
22-
*/
23-
private $aggregator;
24-
2521
public function __construct()
2622
{
27-
$this->aggregator = new MetricsAggregator();
2823
}
2924

3025
public static function getInstance(): self
@@ -46,7 +41,7 @@ public function count(
4641
array $attributes = [],
4742
?Unit $unit = null
4843
): void {
49-
$this->aggregator->add(
44+
$this->aggregator()->add(
5045
CounterMetric::TYPE,
5146
$name,
5247
$value,
@@ -65,7 +60,7 @@ public function distribution(
6560
array $attributes = [],
6661
?Unit $unit = null
6762
): void {
68-
$this->aggregator->add(
63+
$this->aggregator()->add(
6964
DistributionMetric::TYPE,
7065
$name,
7166
$value,
@@ -84,7 +79,7 @@ public function gauge(
8479
array $attributes = [],
8580
?Unit $unit = null
8681
): void {
87-
$this->aggregator->add(
82+
$this->aggregator()->add(
8883
GaugeMetric::TYPE,
8984
$name,
9085
$value,
@@ -95,6 +90,11 @@ public function gauge(
9590

9691
public function flush(): ?EventId
9792
{
98-
return $this->aggregator->flush();
93+
return $this->aggregator()->flush();
94+
}
95+
96+
private function aggregator(): MetricsAggregator
97+
{
98+
return SentrySdk::getCurrentRuntimeContext()->getMetricsAggregator();
9999
}
100100
}

0 commit comments

Comments
 (0)