File: TracerState.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (112 lines) | stat: -rw-r--r-- 2,891 bytes parent folder | download
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<?php
namespace Wikimedia\Telemetry;

use Wikimedia\Assert\Assert;

/**
 * Holds shared telemetry state, such as finished span data buffered for export.
 *
 * Since this data is tied to the lifetime of a given web request or process, this class is a singleton to
 * avoid discarding data in the case of MediaWiki service container resets.
 *
 * @since 1.43
 * @internal
 */
class TracerState {
	/**
	 * Shared tracer state for the current process or web request, `null` if uninitialized.
	 * @var TracerState|null
	 */
	private static ?TracerState $instance = null;

	/**
	 * List of already finished spans to be exported.
	 * @var SpanContext[]
	 */
	private array $finishedSpanContexts = [];

	/**
	 * Stack holding contexts for activated spans.
	 * @var SpanContext[]
	 */
	private array $activeSpanContextStack = [];

	/**
	 * Get or initialize the shared tracer state for the current process or web request.
	 * @return TracerState
	 */
	public static function getInstance(): TracerState {
		self::$instance ??= new self();
		return self::$instance;
	}

	/**
	 * Reset shared tracer state. Useful for testing.
	 * @return void
	 */
	public static function destroyInstance(): void {
		Assert::precondition(
			defined( 'MW_PHPUNIT_TEST' ),
			'This function can only be called in tests'
		);

		self::$instance = null;
	}

	/**
	 * Add the given span to the list of finished spans.
	 * @param SpanContext $context
	 * @return void
	 */
	public function addSpanContext( SpanContext $context ): void {
		$this->finishedSpanContexts[] = $context;
	}

	/**
	 * Get the list of finished spans.
	 * @return SpanContext[]
	 */
	public function getSpanContexts(): array {
		return $this->finishedSpanContexts;
	}

	/**
	 * Clear the list of finished spans.
	 */
	public function clearSpanContexts(): void {
		$this->finishedSpanContexts = [];
	}

	/**
	 * Make the given span the active span.
	 * @param SpanContext $spanContext Context of the span to activate
	 * @return void
	 */
	public function activateSpan( SpanContext $spanContext ): void {
		$this->activeSpanContextStack[] = $spanContext;
	}

	/**
	 * Deactivate the given span, if it was the active span.
	 * @param SpanContext $spanContext Context of the span to deactivate
	 * @return void
	 */
	public function deactivateSpan( SpanContext $spanContext ): void {
		$activeSpanContext = $this->getActiveSpanContext();

		Assert::invariant(
			$activeSpanContext !== null && $activeSpanContext->getSpanId() === $spanContext->getSpanId(),
			'Attempted to deactivate a span which is not the active span.'
		);

		array_pop( $this->activeSpanContextStack );
	}

	/**
	 * Get the context of the currently active span, or `null` if no span is active.
	 * @return SpanContext|null
	 */
	public function getActiveSpanContext(): ?SpanContext {
		return $this->activeSpanContextStack[count( $this->activeSpanContextStack ) - 1] ?? null;
	}
}