From 94262f03774501309dcc74e4851013ccf78e4ed4 Mon Sep 17 00:00:00 2001 From: Lars Vierbergen Date: Thu, 2 Nov 2017 18:12:35 +0100 Subject: [PATCH] Add separate commands to generate a munin plugin and to provide munin data; split aggegrate and count login data --- Command/DumpStatsCommand.php | 38 +++++-------- Command/GenerateMuninCommand.php | 81 ++++++++++++++++++++++++++++ Command/MuninStatsCommand.php | 66 +++++++++++++++++++++++ EventListener/LoginStatsListener.php | 66 +++++++++++++---------- 4 files changed, 198 insertions(+), 53 deletions(-) create mode 100644 Command/GenerateMuninCommand.php create mode 100644 Command/MuninStatsCommand.php diff --git a/Command/DumpStatsCommand.php b/Command/DumpStatsCommand.php index 1ca768a..72f4401 100644 --- a/Command/DumpStatsCommand.php +++ b/Command/DumpStatsCommand.php @@ -31,9 +31,7 @@ class DumpStatsCommand extends Command protected function configure() { - $this->setName('stats:dump') - ->addOption('module', 'm', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Modules to fetch statistics for') - ->addOption('munin', null, InputOption::VALUE_OPTIONAL, 'Output data for consumption by munin', false); + $this->setName('stats:dump')->addOption('module', 'm', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Modules to fetch statistics for'); } protected function execute(InputInterface $input, OutputInterface $output) @@ -48,29 +46,17 @@ class DumpStatsCommand extends Command $event = new StatsEvent($input->getOption('module')); $eventDispatcher->dispatch(StatsEvent::class, $event); - if ($input->getOption('munin') !== false) { - foreach ($event->getModules() as $module) { - $output->writeln('multigraph authserver_' . $module, OutputInterface::OUTPUT_RAW); - if ($input->getOption('munin') === 'config') { - $stats = $event->getMuninConfig($module); - $suffix = ' '; - } else { - $stats = $event->getModuleStatistics($module); - $suffix = '.value '; - } - foreach ($stats as $k => $v) { - $output->writeln($k . $suffix . $v, OutputInterface::OUTPUT_RAW); - } - } - } else { - $table = new Table($output); - foreach ($event->getStatistics() as $name => $value) { - $table->addRow([ - $name, - $value - ]); - } - $table->render(); + $table = new Table($output); + $table->setHeaders([ + 'Statistic', + 'Value' + ]); + foreach ($event->getStatistics() as $name => $value) { + $table->addRow([ + $name, + $value + ]); } + $table->render(); } } \ No newline at end of file diff --git a/Command/GenerateMuninCommand.php b/Command/GenerateMuninCommand.php new file mode 100644 index 0000000..67a026d --- /dev/null +++ b/Command/GenerateMuninCommand.php @@ -0,0 +1,81 @@ +. + */ +namespace vierbergenlars\AuthserverStatsBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use vierbergenlars\AuthserverStatsBundle\Event\StatsEvent; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Process\PhpExecutableFinder; + +class GenerateMuninCommand extends Command +{ + + protected function configure() + { + $this->setName('stats:generate:munin-plugin') + ->addOption('module', 'm', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Modules to generate munin plugin for') + ->addOption('exclude', 'x', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Modules to exclude from munin graphing') + ->addOption('static-config', 's', InputOption::VALUE_NONE, 'Include a statically generated munin configuration'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $eventDispatcher = $this->getApplication() + ->getKernel() + ->getContainer() + ->get('event_dispatcher'); + + /* @var $eventDispatcher Symfony\Component\EventDispatcher\EventDispatcher */ + $event = new StatsEvent($input->getOption('module')); + $eventDispatcher->dispatch(StatsEvent::class, $event); + $modules = array_merge(array_diff($event->getModules(), $input->getOption('exclude')), $input->getOption('module')); + + $output->writeln('#!/bin/sh'); + if ($input->getOption('static-config')) { + $output->writeln([ + 'case $1 in', + 'config)', + 'cat <<\'EOM\'' + ]); + foreach ($modules as $module) { + $muninConfig = $event->getMuninConfig($module); + foreach ($muninConfig as $key => $value) { + $output->writeln($key . ' ' . $value, OutputInterface::OUTPUT_RAW); + } + } + $output->writeln([ + 'EOM', + 'exit 0;;', + 'esac' + ]); + } + + $modulesParameters = array_map(function ($module) { + return '-m ' . $module; + }, $modules); + $phpFinder = new PhpExecutableFinder(); + $kernel = $this->getApplication()->getKernel(); + /* @var $kernel \AppKernel */ + $output->writeln(sprintf('%s %s -e %s stats:munin "$1" %s', $phpFinder->find(), $kernel->getRootDir() . '/console', $kernel->getEnvironment(), implode(' ', $modulesParameters))); + } +} \ No newline at end of file diff --git a/Command/MuninStatsCommand.php b/Command/MuninStatsCommand.php new file mode 100644 index 0000000..556507f --- /dev/null +++ b/Command/MuninStatsCommand.php @@ -0,0 +1,66 @@ +. + */ +namespace vierbergenlars\AuthserverStatsBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use vierbergenlars\AuthserverStatsBundle\Event\StatsEvent; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; + +class MuninStatsCommand extends Command +{ + + protected function configure() + { + $this->setName('stats:munin') + ->addOption('module', 'm', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Modules to fetch statistics for') + ->addArgument('munin', InputArgument::OPTIONAL, 'munin arguments'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $eventDispatcher = $this->getApplication() + ->getKernel() + ->getContainer() + ->get('event_dispatcher'); + + /* @var $eventDispatcher Symfony\Component\EventDispatcher\EventDispatcher */ + + $event = new StatsEvent($input->getOption('module')); + $eventDispatcher->dispatch(StatsEvent::class, $event); + + foreach ($event->getModules() as $module) { + $output->writeln('multigraph authserver_' . $module, OutputInterface::OUTPUT_RAW); + if ($input->getArgument('munin') === 'config') { + $stats = $event->getMuninConfig($module); + $suffix = ' '; + } else { + $stats = $event->getModuleStatistics($module); + $suffix = '.value '; + } + foreach ($stats as $k => $v) { + $output->writeln($k . $suffix . $v, OutputInterface::OUTPUT_RAW); + } + } + } +} \ No newline at end of file diff --git a/EventListener/LoginStatsListener.php b/EventListener/LoginStatsListener.php index 3c44f47..f46ca46 100644 --- a/EventListener/LoginStatsListener.php +++ b/EventListener/LoginStatsListener.php @@ -64,38 +64,50 @@ class LoginStatsListener implements EventSubscriberInterface public function getLoginStats(StatsEvent $event) { - if (!$event->isEnabled('login')) - return; + if ($event->isEnabled('login')) { - $event->setMuninConfig('login', [ - 'graph_title' => 'Authserver logins', - 'graph_vlabel' => 'Number of logins', - 'graph_category' => 'authserver', - '5min.label' => 'Logins in past 5 minutes', - '1hour.label' => 'Logins in past hour', - '1day.label' => 'Logins in past day', - '1week.label' => 'Logins in past week', - 'total.label' => 'Logins per ${graph_period}', - 'total.type' => 'COUNTER' - ]); - $queryBuilder = $this->registry->getRepository(LoginEntry::class)->createQueryBuilder('e'); - /* @var $queryBuilder \Doctrine\ORM\QueryBuilder */ + $event->setMuninConfig('login', [ + 'graph_title' => 'Authserver logins', + 'graph_vlabel' => 'Number of logins', + 'graph_category' => 'authserver', + 'graph_period' => 'minute', + 'total.label' => 'Logins per ${graph_period}', + 'total.type' => 'COUNTER' + ]); - $queryBuilder->select('count(e)')->where('e.loginTime > :time'); + $queryBuilder = $this->registry->getRepository(LoginEntry::class)->createQueryBuilder('e'); + /* @var $queryBuilder \Doctrine\ORM\QueryBuilder */ - foreach ([ - '5min', - '1hour', - '1day', - '1week' - ] as $timeAgo) { - $event->addStatistic('login.' . $timeAgo, $queryBuilder->getQuery() - ->setParameter('time', new \DateTime($timeAgo . ' ago')) + $event->addStatistic('login.total', $queryBuilder->select('count(e)') + ->getQuery() ->getSingleScalarResult()); } - $event->addStatistic('login.total', $queryBuilder->resetDQLPart('where') - ->getQuery() - ->getSingleScalarResult()); + if ($event->isEnabled('login_aggregate')) { + $event->setMuninConfig('login_aggregate', [ + 'graph_title' => 'Authserver logins', + 'graph_vlabel' => 'Number of logins', + 'graph_category' => 'authserver', + '5min.label' => 'Logins in past 5 minutes', + '1hour.label' => 'Logins in past hour', + '1day.label' => 'Logins in past day', + '1week.label' => 'Logins in past week' + ]); + + $queryBuilder = $this->registry->getRepository(LoginEntry::class)->createQueryBuilder('e'); + /* @var $queryBuilder \Doctrine\ORM\QueryBuilder */ + $queryBuilder->select('count(e)')->where('e.loginTime > :time'); + + foreach ([ + '5min', + '1hour', + '1day', + '1week' + ] as $timeAgo) { + $event->addStatistic('login_aggregate.' . $timeAgo, $queryBuilder->getQuery() + ->setParameter('time', new \DateTime($timeAgo . ' ago')) + ->getSingleScalarResult()); + } + } } } \ No newline at end of file