Skip to content

Commit c876789

Browse files
Add auto-instrumentation for PHP output buffering control functions (#437)
Add output buffering control functions in IO autinstrumentation hooks
1 parent cfc1674 commit c876789

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

src/Instrumentation/IO/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ following functions:
2222
- `file_put_contents`
2323
- `curl_init`
2424
- `curl_exec`
25+
- `ob_start`
26+
- `ob_clean`
27+
- `ob_flush`
28+
- `flush`
2529

2630
## Configuration
2731

2832
The extension can be disabled via [runtime configuration](https://opentelemetry.io/docs/instrumentation/php/sdk/#configuration):
2933

3034
```shell
3135
OTEL_PHP_DISABLED_INSTRUMENTATIONS=io
32-
```
36+
```

src/Instrumentation/IO/src/IOInstrumentation.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public static function register(): void
3333
self::_hook($instrumentation, null, 'file_get_contents', 'file_get_contents');
3434
self::_hook($instrumentation, null, 'file_put_contents', 'file_put_contents');
3535

36+
// Output buffer functions
37+
self::_hook($instrumentation, null, 'ob_start', 'ob_start');
38+
self::_hook($instrumentation, null, 'ob_clean', 'ob_clean');
39+
self::_hook($instrumentation, null, 'ob_flush', 'ob_flush');
40+
self::_hook($instrumentation, null, 'flush', 'flush');
41+
3642
self::_hook($instrumentation, null, 'curl_init', 'curl_init');
3743
self::_hook($instrumentation, null, 'curl_exec', 'curl_exec');
3844
}
@@ -109,6 +115,19 @@ private static function addParams(SpanBuilderInterface $builder, string $functio
109115
case 'file_put_contents':
110116
$builder->setAttribute('code.params.filename', $params[0]);
111117

118+
break;
119+
case 'ob_start':
120+
if (isset($params[0]) && is_callable($params[0])) {
121+
// We can't directly serialize the callback, so we'll just note that one was provided
122+
$builder->setAttribute('code.params.has_callback', true);
123+
}
124+
if (isset($params[1])) {
125+
$builder->setAttribute('code.params.chunk_size', $params[1]);
126+
}
127+
if (isset($params[2])) {
128+
$builder->setAttribute('code.params.flags', $params[2]);
129+
}
130+
112131
break;
113132
}
114133
}

src/Instrumentation/IO/tests/Integration/IOInstrumentationTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public function setUp(): void
3737
public function tearDown(): void
3838
{
3939
$this->scope->detach();
40+
// Clean up any output buffers that might have been started during tests
41+
while (ob_get_level() > 0) {
42+
ob_end_clean();
43+
}
4044
}
4145

4246
public function test_io_calls(): void
@@ -83,4 +87,44 @@ public function test_io_calls(): void
8387
$this->span = $this->storage->offsetGet(6);
8488
$this->assertSame('curl_exec', $this->span->getName());
8589
}
90+
91+
public function test_output_buffer_calls(): void
92+
{
93+
// Make sure we start with a clean state
94+
while (ob_get_level() > 0) {
95+
ob_end_clean();
96+
}
97+
// Test ob_start with parameters
98+
$callback = function ($buffer) {
99+
return $buffer;
100+
};
101+
ob_start($callback, 4096, PHP_OUTPUT_HANDLER_STDFLAGS);
102+
$this->assertCount(1, $this->storage);
103+
$this->span = $this->storage->offsetGet(0);
104+
$this->assertSame('ob_start', $this->span->getName());
105+
$this->assertTrue($this->span->getAttributes()->get('code.params.has_callback'));
106+
$this->assertSame(4096, $this->span->getAttributes()->get('code.params.chunk_size'));
107+
$this->assertSame(PHP_OUTPUT_HANDLER_STDFLAGS, $this->span->getAttributes()->get('code.params.flags'));
108+
109+
// Test ob_clean
110+
ob_clean();
111+
$this->assertCount(2, $this->storage);
112+
$this->span = $this->storage->offsetGet(1);
113+
$this->assertSame('ob_clean', $this->span->getName());
114+
115+
// Test ob_flush
116+
ob_flush();
117+
$this->assertCount(3, $this->storage);
118+
$this->span = $this->storage->offsetGet(2);
119+
$this->assertSame('ob_flush', $this->span->getName());
120+
121+
// Test flush
122+
flush();
123+
$this->assertCount(4, $this->storage);
124+
$this->span = $this->storage->offsetGet(3);
125+
$this->assertSame('flush', $this->span->getName());
126+
127+
// Clean up
128+
ob_end_clean();
129+
}
86130
}

0 commit comments

Comments
 (0)