summaryrefslogtreecommitdiff
path: root/vendor/open-telemetry/context/ZendObserverFiber.php
blob: 4d3d0c5efdf25d05272458f3085db090ca09ab54 (plain)
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
<?php

/** @noinspection PhpUndefinedMethodInspection */
/** @phan-file-suppress PhanUndeclaredClassCatch */
/** @phan-file-suppress PhanUndeclaredClassMethod */
/** @phan-file-suppress PhanUndeclaredMethod */

declare(strict_types=1);

namespace OpenTelemetry\Context;

use function extension_loaded;
use FFI;
use const FILTER_VALIDATE_BOOLEAN;
use function filter_var;
use function is_string;
use const PHP_VERSION_ID;
use const PHP_ZTS;
use function sprintf;
use function trigger_error;

/**
 * @internal
 */
final class ZendObserverFiber
{
    public static function isEnabled(): bool
    {
        $enabled = $_SERVER['OTEL_PHP_FIBERS_ENABLED'] ?? false;

        return is_string($enabled)
            ? filter_var($enabled, FILTER_VALIDATE_BOOLEAN)
            : (bool) $enabled;
    }

    public static function init(): bool
    {
        static $fibers;
        if ($fibers) {
            return true;
        }

        if (PHP_ZTS || PHP_VERSION_ID < 80100 || !extension_loaded('ffi')) {
            trigger_error('Context: Fiber context switching not supported, requires PHP >= 8.1, an NTS build, and the FFI extension');

            return false;
        }

        try {
            $fibers = FFI::scope('OTEL_ZEND_OBSERVER_FIBER');
        } catch (FFI\Exception $e) {
            try {
                $fibers = FFI::load(__DIR__ . '/fiber/zend_observer_fiber.h');
            } catch (FFI\Exception $e) {
                trigger_error(sprintf('Context: Fiber context switching not supported, %s', $e->getMessage()));

                return false;
            }
        }

        $fibers->zend_observer_fiber_init_register(static fn (int $initializing) => Context::storage()->fork($initializing)); //@phpstan-ignore-line
        $fibers->zend_observer_fiber_switch_register(static fn (int $from, int $to) => Context::storage()->switch($to)); //@phpstan-ignore-line
        $fibers->zend_observer_fiber_destroy_register(static fn (int $destroying) => Context::storage()->destroy($destroying)); //@phpstan-ignore-line

        return true;
    }
}