summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Scheller <igor.scheller@igorshp.de>2018-12-18 04:43:13 +0100
committermsquare <msquare@notrademark.de>2018-12-19 22:36:42 +0100
commit9a2f2465116387880282df505e3d3230516604dd (patch)
treed7003c84aa77a0578c4316708a673e6040665359
parentc5621b82cfeddee23b81871a53035fde747f73a9 (diff)
metrics: Added more stats
-rw-r--r--src/Controllers/Metrics/Controller.php39
-rw-r--r--src/Controllers/Metrics/Stats.php132
-rw-r--r--tests/Unit/Controllers/Metrics/ControllerTest.php40
-rw-r--r--tests/Unit/Controllers/Metrics/StatsTest.php60
4 files changed, 271 insertions, 0 deletions
diff --git a/src/Controllers/Metrics/Controller.php b/src/Controllers/Metrics/Controller.php
index 01fe1d6a..0fd26396 100644
--- a/src/Controllers/Metrics/Controller.php
+++ b/src/Controllers/Metrics/Controller.php
@@ -7,6 +7,7 @@ use Engelsystem\Controllers\BaseController;
use Engelsystem\Http\Exceptions\HttpForbidden;
use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
+use Psr\Log\LogLevel;
class Controller extends BaseController
{
@@ -62,6 +63,15 @@ class Controller extends BaseController
['labels' => ['state' => 'arrived', 'working' => 'no'], 'value' => $this->stats->arrivedUsers(false)],
['labels' => ['state' => 'arrived', 'working' => 'yes'], 'value' => $this->stats->arrivedUsers(true)],
],
+ 'licenses' => [
+ 'type' => 'gauge',
+ 'help' => 'The total number of licenses',
+ ['labels' => ['type' => 'forklift'], 'value' => $this->stats->licenses('forklift')],
+ ['labels' => ['type' => 'car'], 'value' => $this->stats->licenses('car')],
+ ['labels' => ['type' => '3.5t'], 'value' => $this->stats->licenses('3.5t')],
+ ['labels' => ['type' => '7.5t'], 'value' => $this->stats->licenses('7.5t')],
+ ['labels' => ['type' => '12.5t'], 'value' => $this->stats->licenses('12.5t')],
+ ],
'users_working' => [
'type' => 'gauge',
['labels' => ['freeloader' => false], $this->stats->currentlyWorkingUsers(false)],
@@ -73,7 +83,36 @@ class Controller extends BaseController
['labels' => ['state' => 'planned'], 'value' => $this->stats->workSeconds(false, false)],
['labels' => ['state' => 'freeloaded'], 'value' => $this->stats->workSeconds(null, true)],
],
+ 'worklog_seconds' => ['type' => 'gauge', $this->stats->worklogSeconds()],
+ 'shifts' => ['type' => 'gauge', $this->stats->shifts()],
+ 'announcements' => [
+ 'type' => 'gauge',
+ ['labels' => ['type' => 'news'], 'value' => $this->stats->announcements(false)],
+ ['labels' => ['type' => 'meeting'], 'value' => $this->stats->announcements(true)],
+ ],
+ 'questions' => [
+ 'type' => 'gauge',
+ ['labels' => ['answered' => true], 'value' => $this->stats->questions(true)],
+ ['labels' => ['answered' => false], 'value' => $this->stats->questions(false)],
+ ],
+ 'messages' => ['type' => 'gauge', $this->stats->messages()],
+ 'password_resets' => ['type' => 'gauge', $this->stats->passwordResets()],
'registration_enabled' => ['type' => 'gauge', $this->config->get('registration_enabled')],
+ 'sessions' => ['type' => 'gauge', $this->stats->sessions()],
+ 'log_entries' => [
+ 'type' => 'counter',
+ [
+ 'labels' => ['level' => LogLevel::EMERGENCY],
+ 'value' => $this->stats->logEntries(LogLevel::EMERGENCY)
+ ],
+ ['labels' => ['level' => LogLevel::ALERT], 'value' => $this->stats->logEntries(LogLevel::ALERT)],
+ ['labels' => ['level' => LogLevel::CRITICAL], 'value' => $this->stats->logEntries(LogLevel::CRITICAL)],
+ ['labels' => ['level' => LogLevel::ERROR], 'value' => $this->stats->logEntries(LogLevel::ERROR)],
+ ['labels' => ['level' => LogLevel::WARNING], 'value' => $this->stats->logEntries(LogLevel::WARNING)],
+ ['labels' => ['level' => LogLevel::NOTICE], 'value' => $this->stats->logEntries(LogLevel::NOTICE)],
+ ['labels' => ['level' => LogLevel::INFO], 'value' => $this->stats->logEntries(LogLevel::INFO)],
+ ['labels' => ['level' => LogLevel::DEBUG], 'value' => $this->stats->logEntries(LogLevel::DEBUG)],
+ ],
];
$data['scrape_duration_seconds'] = [
diff --git a/src/Controllers/Metrics/Stats.php b/src/Controllers/Metrics/Stats.php
index 891f8c80..838411d1 100644
--- a/src/Controllers/Metrics/Stats.php
+++ b/src/Controllers/Metrics/Stats.php
@@ -97,6 +97,31 @@ class Stats
}
/**
+ * @param string $vehicle
+ * @return int
+ * @codeCoverageIgnore
+ */
+ public function licenses($vehicle = null)
+ {
+ $mapping = [
+ 'forklift' => 'has_license_forklift',
+ 'car' => 'has_license_car',
+ '3.5t' => 'has_license_3_5t_transporter',
+ '7.5t' => 'has_license_7_5t_truck',
+ '12.5t' => 'has_license_12_5t_truck',
+ ];
+
+ $query = $this
+ ->getQuery('UserDriverLicenses');
+
+ if (!is_null($vehicle)) {
+ $query->where($mapping[$vehicle], '=', true);
+ }
+
+ return $query->count();
+ }
+
+ /**
* The number of worked shifts
*
* @param bool|null $done
@@ -122,6 +147,113 @@ class Stats
}
/**
+ * @return int
+ * @codeCoverageIgnore
+ */
+ public function worklogSeconds()
+ {
+ return round($this
+ ->getQuery('UserWorkLog')
+ ->sum($this->raw('work_hours * 60*60')));
+ }
+
+ /**
+ * @return int
+ * @codeCoverageIgnore
+ */
+ public function shifts()
+ {
+ return $this
+ ->getQuery('Shifts')
+ ->count();
+ }
+
+ /**
+ * @param bool $meeting
+ * @return int
+ * @codeCoverageIgnore
+ */
+ public function announcements($meeting = null)
+ {
+ $query = $this
+ ->getQuery('News');
+
+ if (!is_null($meeting)) {
+ $query->where('Treffen', '=', $meeting);
+ }
+
+ return $query->count();
+ }
+
+ /**
+ * @param bool $answered
+ * @return int
+ * @codeCoverageIgnore
+ */
+ public function questions($answered = null)
+ {
+ $query = $this
+ ->getQuery('Questions');
+
+ if (!is_null($answered)) {
+ if ($answered) {
+ $query->whereNotNull('AID');
+ } else {
+ $query->whereNull('AID');
+ }
+ }
+
+ return $query->count();
+ }
+
+ /**
+ * @return int
+ * @codeCoverageIgnore
+ */
+ public function messages()
+ {
+ return $this
+ ->getQuery('Messages')
+ ->count();
+ }
+
+ /**
+ * @return int
+ */
+ public function sessions()
+ {
+ return $this
+ ->getQuery('sessions')
+ ->count();
+ }
+
+ /**
+ * @param string $level
+ * @return int
+ */
+ public function logEntries($level = null)
+ {
+ $query = $this
+ ->getQuery('log_entries');
+
+ if (!is_null($level)) {
+ $query->where('level', '=', $level);
+ }
+
+ return $query->count();
+ }
+
+ /**
+ * @return int
+ */
+ public function passwordResets()
+ {
+ return $this
+ ->getQuery('password_resets')
+ ->count();
+ }
+
+ /**
* @param string $table
* @return QueryBuilder
*/
diff --git a/tests/Unit/Controllers/Metrics/ControllerTest.php b/tests/Unit/Controllers/Metrics/ControllerTest.php
index 013a3352..37310ddf 100644
--- a/tests/Unit/Controllers/Metrics/ControllerTest.php
+++ b/tests/Unit/Controllers/Metrics/ControllerTest.php
@@ -11,6 +11,7 @@ use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Test\Unit\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LogLevel;
use Symfony\Component\HttpFoundation\ServerBag;
class ControllerTest extends TestCase
@@ -36,9 +37,18 @@ class ControllerTest extends TestCase
->willReturnCallback(function ($path, $data) use ($response) {
$this->assertEquals('/metrics', $path);
$this->assertArrayHasKey('users', $data);
+ $this->assertArrayHasKey('licenses', $data);
$this->assertArrayHasKey('users_working', $data);
$this->assertArrayHasKey('work_seconds', $data);
+ $this->assertArrayHasKey('worklog_seconds', $data);
+ $this->assertArrayHasKey('shifts', $data);
+ $this->assertArrayHasKey('announcements', $data);
+ $this->assertArrayHasKey('questions', $data);
+ $this->assertArrayHasKey('messages', $data);
+ $this->assertArrayHasKey('password_resets', $data);
$this->assertArrayHasKey('registration_enabled', $data);
+ $this->assertArrayHasKey('sessions', $data);
+ $this->assertArrayHasKey('log_entries', $data);
$this->assertArrayHasKey('scrape_duration_seconds', $data);
return 'metrics return';
@@ -53,6 +63,10 @@ class ControllerTest extends TestCase
->with('metrics return')
->willReturn($response);
+ $stats->expects($this->exactly(5))
+ ->method('licenses')
+ ->withConsecutive(['forklift'], ['car'], ['3.5t'], ['7.5t'], ['12.5t'])
+ ->willReturnOnConsecutiveCalls(3, 15, 9, 7, 1);
$stats->expects($this->exactly(2))
->method('arrivedUsers')
->withConsecutive([false], [true])
@@ -65,7 +79,33 @@ class ControllerTest extends TestCase
->method('workSeconds')
->withConsecutive([true, false], [false, false], [null, true])
->willReturnOnConsecutiveCalls(60 * 37, 60 * 251, 60 * 3);
+ $stats->expects($this->exactly(2))
+ ->method('announcements')
+ ->withConsecutive([false], [true])
+ ->willReturnOnConsecutiveCalls(18, 7);
+ $stats->expects($this->exactly(2))
+ ->method('questions')
+ ->withConsecutive([true], [false])
+ ->willReturnOnConsecutiveCalls(5, 0);
+ $stats->expects($this->exactly(8))
+ ->method('logEntries')
+ ->withConsecutive(
+ [LogLevel::EMERGENCY],
+ [LogLevel::ALERT],
+ [LogLevel::CRITICAL],
+ [LogLevel::ERROR],
+ [LogLevel::WARNING],
+ [LogLevel::NOTICE],
+ [LogLevel::INFO],
+ [LogLevel::DEBUG]
+ )
+ ->willReturnOnConsecutiveCalls(0, 1, 0, 5, 999, 4, 55, 3);
$this->setExpects($stats, 'newUsers', null, 9);
+ $this->setExpects($stats, 'worklogSeconds', null, 39 * 60 * 60);
+ $this->setExpects($stats, 'shifts', null, 142);
+ $this->setExpects($stats, 'messages', null, 3);
+ $this->setExpects($stats, 'passwordResets', null, 1);
+ $this->setExpects($stats, 'sessions', null, 1234);
$config->set('registration_enabled', 1);
diff --git a/tests/Unit/Controllers/Metrics/StatsTest.php b/tests/Unit/Controllers/Metrics/StatsTest.php
index 1618b99b..2ebe52ae 100644
--- a/tests/Unit/Controllers/Metrics/StatsTest.php
+++ b/tests/Unit/Controllers/Metrics/StatsTest.php
@@ -2,12 +2,16 @@
namespace Engelsystem\Test\Unit\Controllers\Metrics;
+use Carbon\Carbon;
use Engelsystem\Controllers\Metrics\Stats;
+use Engelsystem\Models\LogEntry;
+use Engelsystem\Models\User\PasswordReset;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
use Engelsystem\Test\Unit\HasDatabase;
use Engelsystem\Test\Unit\TestCase;
use Illuminate\Support\Str;
+use Psr\Log\LogLevel;
class StatsTest extends TestCase
{
@@ -40,6 +44,62 @@ class StatsTest extends TestCase
}
/**
+ * @covers \Engelsystem\Controllers\Metrics\Stats::sessions
+ */
+ public function testSessions()
+ {
+ $this->initDatabase();
+
+ $this->database
+ ->getConnection()
+ ->table('sessions')
+ ->insert([
+ ['id' => 'asd', 'payload' => 'data', 'last_activity' => new Carbon('1 month ago')],
+ ['id' => 'efg', 'payload' => 'lorem', 'last_activity' => new Carbon('55 minutes ago')],
+ ['id' => 'hij', 'payload' => 'ipsum', 'last_activity' => new Carbon('3 seconds ago')],
+ ['id' => 'klm', 'payload' => 'dolor', 'last_activity' => new Carbon()],
+ ]);
+
+ $stats = new Stats($this->database);
+ $this->assertEquals(4, $stats->sessions());
+ }
+
+ /**
+ * @covers \Engelsystem\Controllers\Metrics\Stats::logEntries
+ */
+ public function testLogEntries()
+ {
+ $this->initDatabase();
+
+ (new LogEntry(['level' => LogLevel::INFO, 'message' => 'Some info']))->save();
+ (new LogEntry(['level' => LogLevel::INFO, 'message' => 'Another info']))->save();
+ (new LogEntry(['level' => LogLevel::CRITICAL, 'message' => 'A critical error!']))->save();
+ (new LogEntry(['level' => LogLevel::DEBUG, 'message' => 'Verbose output!']))->save();
+ (new LogEntry(['level' => LogLevel::INFO, 'message' => 'Shutdown initiated']))->save();
+ (new LogEntry(['level' => LogLevel::WARNING, 'message' => 'Please be cautious']))->save();
+
+ $stats = new Stats($this->database);
+ $this->assertEquals(6, $stats->logEntries());
+ $this->assertEquals(3, $stats->logEntries(LogLevel::INFO));
+ $this->assertEquals(1, $stats->logEntries(LogLevel::DEBUG));
+ }
+
+ /**
+ * @covers \Engelsystem\Controllers\Metrics\Stats::passwordResets
+ */
+ public function testPasswordResets()
+ {
+ $this->initDatabase();
+ $this->addUsers();
+
+ (new PasswordReset(['use_id' => 1, 'token' => 'loremIpsum123']))->save();
+ (new PasswordReset(['use_id' => 3, 'token' => '5omeR4nd0mTok3N']))->save();
+
+ $stats = new Stats($this->database);
+ $this->assertEquals(2, $stats->passwordResets());
+ }
+
+ /**
* Add some example users
*/
protected function addUsers()