1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
<?php
declare(strict_types=1);
namespace OpenTelemetry\Context;
use function basename;
use function count;
use function debug_backtrace;
use const DEBUG_BACKTRACE_IGNORE_ARGS;
use function sprintf;
use function trigger_error;
/**
* @internal
*/
final class DebugScope implements ScopeInterface
{
private const DEBUG_TRACE_CREATE = '__debug_trace_create';
private const DEBUG_TRACE_DETACH = '__debug_trace_detach';
private ContextStorageScopeInterface $scope;
public function __construct(ContextStorageScopeInterface $node)
{
$this->scope = $node;
$this->scope[self::DEBUG_TRACE_CREATE] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
}
public function detach(): int
{
$this->scope[self::DEBUG_TRACE_DETACH] ??= debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$flags = $this->scope->detach();
if (($flags & ScopeInterface::DETACHED) !== 0) {
trigger_error(sprintf(
'Scope: unexpected call to Scope::detach() for scope #%d, scope was already detached %s',
spl_object_id($this),
self::formatBacktrace($this->scope[self::DEBUG_TRACE_DETACH]),
));
} elseif (($flags & ScopeInterface::MISMATCH) !== 0) {
trigger_error(sprintf(
'Scope: unexpected call to Scope::detach() for scope #%d, scope successfully detached but another scope should have been detached first',
spl_object_id($this),
));
} elseif (($flags & ScopeInterface::INACTIVE) !== 0) {
trigger_error(sprintf(
'Scope: unexpected call to Scope::detach() for scope #%d, scope successfully detached from different execution context',
spl_object_id($this),
));
}
return $flags;
}
public function __destruct()
{
if (!isset($this->scope[self::DEBUG_TRACE_DETACH])) {
trigger_error(sprintf(
'Scope: missing call to Scope::detach() for scope #%d, created %s',
spl_object_id($this->scope),
self::formatBacktrace($this->scope[self::DEBUG_TRACE_CREATE]),
));
}
}
private static function formatBacktrace(array $trace): string
{
$s = '';
for ($i = 0, $n = count($trace) + 1; ++$i < $n;) {
$s .= "\n\t";
$s .= 'at ';
if (isset($trace[$i]['class'])) {
$s .= strtr($trace[$i]['class'], ['\\' => '.']);
$s .= '.';
}
$s .= strtr($trace[$i]['function'] ?? '{main}', ['\\' => '.']);
$s .= '(';
if (isset($trace[$i - 1]['file'])) {
$s .= basename($trace[$i - 1]['file']);
if (isset($trace[$i - 1]['line'])) {
$s .= ':';
$s .= $trace[$i - 1]['line'];
}
} else {
$s .= 'Unknown Source';
}
$s .= ')';
}
return $s . "\n";
}
}
|