Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
LoggingContext
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
4 / 4
5
100.00% covered (success)
100.00%
1 / 1
 add
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addScoped
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 update
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace MediaWiki\Logger;
4
5use Wikimedia\ScopedCallback;
6
7/**
8 * A helper class for adding extra context to all logs, without the logging code having to be
9 * aware. (Sometimes called a "diagnostic context".)
10 *
11 * Use LoggerFactory::getContext() to obtain the active instance of this class.
12 * @since 1.44
13 */
14class LoggingContext {
15
16    /** Extra context to add to all log events. */
17    private array $baseContext = [];
18    /** List of extra contexts added to all log events while in scope. */
19    private array $scopedContexts = [];
20    /** The sum of all the contexts. */
21    private array $effectiveContext = [];
22
23    /**
24     * Add extra information to the PSR-3 context. All future log events in the current request
25     * will include it. In case of key conflict, the context passed to the logger and scoped
26     * contexts take priority over this method, and later calls take priority over earlier calls.
27     *
28     * It is recommended to make sure the fields added this way have a sufficiently unique name,
29     * and to prefix them with 'context.' (e.g. 'context.special_page_name').
30     */
31    public function add( array $context ): void {
32        $this->baseContext = array_merge( $this->baseContext, $context );
33        $this->update();
34    }
35
36    /**
37     * Add extra information to the PSR-3 context. All future log events within the scope will
38     * include it. In case of key conflict, the context passed to the logger takes priority over
39     * everything else, inner scopes take priority over outer scopes, and scopes take priority
40     * over addContext().
41     *
42     * The context is not inherited by callbacks which are scheduled in the scope but executed
43     * outside it (such as DeferrableUpdate).
44     *
45     * It is recommended to make sure the fields added this way have a sufficiently unique name,
46     * and to prefix them with 'context.' (e.g. 'context.special_page_name').
47     */
48    #[\NoDiscard]
49    public function addScoped( array $context ): ScopedCallback {
50        $this->scopedContexts[] = $context;
51        $scopeId = array_key_last( $this->scopedContexts );
52        $this->update();
53        return new ScopedCallback( function ( $scopeId ) {
54            unset( $this->scopedContexts[$scopeId] );
55            $this->update();
56        }, [ $scopeId ] );
57    }
58
59    /**
60     * Get the current logging context.
61     * @internal To be used by loggers only.
62     */
63    public function get(): array {
64        return $this->effectiveContext;
65    }
66
67    private function update(): void {
68        $this->effectiveContext = $this->baseContext;
69        foreach ( $this->scopedContexts as $context ) {
70            $this->effectiveContext = array_merge( $this->effectiveContext, $context );
71        }
72    }
73
74}