Passed
Push — master ( f0ea8d...957864 )
by Simon
04:01
created

MetricsAction::runApiPage()   B

Complexity

Conditions 6
Paths 32

Size

Total Lines 66
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
dl 0
loc 66
rs 8.8817
c 1
b 0
f 0
cc 6
nc 32
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 * ACC Development Team. Please see team.json for a list of contributors.     *
5
 *                                                                            *
6
 * This is free and unencumbered software released into the public domain.    *
7
 * Please see LICENSE.md for the full licencing statement.                    *
8
 ******************************************************************************/
9
10
namespace Waca\API\Actions;
11
12
use PDO;
13
use Waca\API\IApiAction;
14
use Waca\Tasks\TextApiPageBase;
15
16
/**
17
 * API Metrics action
18
 */
19
class MetricsAction extends TextApiPageBase implements IApiAction
20
{
21
    private array $metrics = [];
22
23
    private function defineMetric(string $name, string $help, string $type = 'gauge'): void
24
    {
25
        $this->metrics[$name] = ['help' => $help, 'type' => $type, 'values' => []];
26
    }
27
28
    private function setMetric(string $name, array $labels = [], int $value = 0): void
29
    {
30
        $calculatedLabel = '';
31
32
        if (count($labels) > 0) {
33
            ksort($labels);
34
35
            $labelData = [];
36
            foreach ($labels as $label => $labelValue) {
37
                $labelData[] = $label . '="' . $labelValue . '"';
38
            }
39
40
            $calculatedLabel = '{' . implode(',', $labelData) . '}';
41
        }
42
43
        $this->metrics[$name]['values'][$calculatedLabel] = $value;
44
    }
45
46
    public function runApiPage(): string
47
    {
48
        $this->defineMetric('acc_users', 'Number of users');
49
        $statement = $this->getDatabase()->query('SELECT status, COUNT(*) AS count FROM user GROUP BY status;');
50
51
        foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) {
52
            $this->setMetric('acc_users', ['status' => $row['status']], $row['count']);
53
        }
54
        $statement->closeCursor();
55
56
        $this->defineMetric('acc_active_domain_users', 'Number of active users in each domain');
57
        $statement = $this->getDatabase()->query('
58
            SELECT d.shortname, COUNT(1) AS count FROM userdomain ud 
59
            INNER JOIN user u ON ud.user = u.id
60
            INNER JOIN domain d on ud.domain = d.id
61
            WHERE u.status = \'Active\'
62
            GROUP BY d.shortname;');
63
64
        foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) {
65
            $this->setMetric('acc_active_domain_users', ['domain' => $row['shortname']], $row['count']);
66
        }
67
        $statement->closeCursor();
68
69
70
        $this->defineMetric('acc_active_domain_roles', 'Number of active users in each role');
71
        $statement = $this->getDatabase()->query('
72
            SELECT coalesce(d.shortname, \'\') AS domain, ur.role, COUNT(1) AS count
73
            FROM userrole ur
74
            INNER JOIN user u ON ur.user = u.id
75
            LEFT JOIN domain d ON ur.domain = d.id
76
            WHERE u.status = \'Active\' AND ur.role <> \'user\'
77
            GROUP BY d.shortname, ur.role;');
78
79
        foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) {
80
            $this->setMetric('acc_active_domain_roles', ['domain' => $row['domain'], 'role' => $row['role']], $row['count']);
81
        }
82
        $statement->closeCursor();
83
84
85
        $this->defineMetric('acc_active_domain_bans', 'Number of active bans in each domain');
86
        $statement = $this->getDatabase()->query('
87
            SELECT coalesce(d.shortname, \'\') AS domain, COUNT(1) AS count
88
            FROM ban b LEFT JOIN domain d ON b.domain = d.id
89
            WHERE (b.duration > UNIX_TIMESTAMP() OR b.duration is null) AND b.active = 1
90
            GROUP BY d.shortname;');
91
92
        foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) {
93
            $this->setMetric('acc_active_domain_bans', ['domain' => $row['domain'], 'role' => $row['role']], $row['count']);
94
        }
95
        $statement->closeCursor();
96
97
98
        $this->defineMetric('acc_queued_requests', 'Number of requests in each queue');
99
        $statement = $this->getDatabase()->query('
100
            SELECT r.status, d.shortname, rq.header, COUNT(1) as count FROM request r
101
            INNER JOIN domain d on r.domain = d.id
102
            LEFT JOIN waca.requestqueue rq ON r.queue = rq.id
103
            WHERE r.status <> \'Closed\' AND r.emailconfirm = \'Confirmed\'
104
            GROUP BY r.status, d.shortname, rq.header;');
105
106
        foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) {
107
            $this->setMetric('acc_queued_requests', ['status' => $row['status'], 'shortname' => $row['shortname'], 'queue' => $row['header']], $row['count']);
108
        }
109
        $statement->closeCursor();
110
111
        return $this->writeMetrics();
112
    }
113
114
    private function writeMetrics() : string
115
    {
116
        $data = '';
117
118
        foreach ($this->metrics as $name => $metricData) {
119
            $data .= "# HELP {$name} {$metricData['help']}\n";
120
            $data .= "# TYPE {$name} {$metricData['type']}\n";
121
            foreach ($metricData['values'] as $label => $value) {
122
                $data .= "{$name}{$label} {$value}\n";
123
            }
124
        }
125
126
        return $data;
127
    }
128
}
129