Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.67% covered (success)
91.67%
33 / 36
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
GetLagTimes
91.67% covered (success)
91.67%
33 / 36
50.00% covered (danger)
50.00%
1 / 2
10.06
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 execute
90.91% covered (success)
90.91%
30 / 33
0.00% covered (danger)
0.00%
0 / 1
9.06
1<?php
2/**
3 * Display replication lag times.
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 * @ingroup Maintenance
8 */
9
10// @codeCoverageIgnoreStart
11require_once __DIR__ . '/Maintenance.php';
12// @codeCoverageIgnoreEnd
13
14use MediaWiki\Maintenance\Maintenance;
15use Wikimedia\IPUtils;
16
17/**
18 * Maintenance script that displays replication lag times.
19 *
20 * @ingroup Maintenance
21 */
22class GetLagTimes extends Maintenance {
23    public function __construct() {
24        parent::__construct();
25        $this->addDescription( 'Dump replication lag times' );
26        $this->addOption( 'report', "Report the lag values to StatsD" );
27    }
28
29    public function execute() {
30        $services = $this->getServiceContainer();
31        $lbFactory = $services->getDBLoadBalancerFactory();
32        $stats = $services->getStatsFactory();
33        $lbsByType = [
34            'main' => $lbFactory->getAllMainLBs(),
35            'external' => $lbFactory->getAllExternalLBs()
36        ];
37
38        foreach ( $lbsByType as $type => $lbs ) {
39            foreach ( $lbs as $cluster => $lb ) {
40                if ( $lb->getServerCount() <= 1 ) {
41                    continue;
42                }
43                $lags = $lb->getLagTimes();
44                foreach ( $lags as $serverIndex => $lag ) {
45                    $host = $lb->getServerName( $serverIndex );
46                    if ( IPUtils::isValid( $host ) ) {
47                        $ip = $host;
48                        $host = gethostbyaddr( $host );
49                    } else {
50                        $ip = gethostbyname( $host );
51                    }
52
53                    if ( $lag === false ) {
54                        $stars = 'replication stopped or errored';
55                    } else {
56                        $starLen = min( intval( $lag ), 40 );
57                        $stars = str_repeat( '*', $starLen );
58                    }
59                    $this->output( sprintf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars ) );
60
61                    if ( $this->hasOption( 'report' ) ) {
62                        $group = ( $type === 'external' ) ? 'external' : $cluster;
63
64                        // $lag is the lag duration in seconds
65                        // emit milliseconds for backwards-compatibility
66                        $stats->getGauge( 'loadbalancer_lag_milliseconds' )
67                            ->setLabel( 'group', $group )
68                            ->setLabel( 'host', $host )
69                            ->set( (int)( $lag * 1e3 ) );
70
71                        // emit seconds also to align with Prometheus' recommendations
72                        $stats->getGauge( 'loadbalancer_lag_seconds' )
73                            ->setLabel( 'group', $group )
74                            ->setLabel( 'host', $host )
75                            ->set( (int)$lag );
76                    }
77                }
78            }
79        }
80    }
81}
82
83// @codeCoverageIgnoreStart
84$maintClass = GetLagTimes::class;
85require_once RUN_MAINTENANCE_IF_MAIN;
86// @codeCoverageIgnoreEnd