mirror of https://github.com/MISP/MISP
new: [benchmarking suite] added
- collect metrics about the usage of MISP - stored in redis - per endpoint / user / user-agent collection - collection of execution time, php memory use, sql execution time, sql query count - the collection happens on a daily basis - Searchable / filterable interface for the collected data - Dashboard widget for the collected datafeature/better-logic-for-merge-attribute-into-object
parent
4dd5d369b4
commit
4544ef2516
|
@ -18,6 +18,7 @@
|
|||
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('BackgroundJobsTool', 'Tools');
|
||||
App::uses('BenchmarkTool', 'Tools');
|
||||
|
||||
require_once dirname(__DIR__) . '/../Model/Attribute.php'; // FIXME workaround bug where Vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php is loaded instead
|
||||
|
||||
|
@ -38,7 +39,18 @@ abstract class AppShell extends Shell
|
|||
{
|
||||
$configLoad = $this->Tasks->load('ConfigLoad');
|
||||
$configLoad->execute();
|
||||
|
||||
if (Configure::read('Plugin.Benchmarking_enable')) {
|
||||
$Benchmark = new BenchmarkTool(ClassRegistry::init('User'));
|
||||
$start_time = $Benchmark->startBenchmark();
|
||||
register_shutdown_function(function () use ($start_time, $Benchmark) {
|
||||
$Benchmark->stopBenchmark([
|
||||
'user' => 0,
|
||||
'controller' => 'Shell::' . $this->modelClass,
|
||||
'action' => $this->command,
|
||||
'start_time' => $start_time
|
||||
]);
|
||||
});
|
||||
}
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,6 @@ class ServerShell extends AppShell
|
|||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['Pull'] . PHP_EOL);
|
||||
}
|
||||
|
||||
$userId = $this->args[0];
|
||||
$user = $this->getUser($userId);
|
||||
$serverId = $this->args[1];
|
||||
|
@ -166,7 +165,7 @@ class ServerShell extends AppShell
|
|||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['Push'] . PHP_EOL);
|
||||
}
|
||||
|
||||
|
||||
$userId = $this->args[0];
|
||||
$user = $this->getUser($userId);
|
||||
$serverId = $this->args[1];
|
||||
|
@ -370,7 +369,7 @@ class ServerShell extends AppShell
|
|||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['Fetch feeds as local data'] . PHP_EOL);
|
||||
}
|
||||
|
||||
|
||||
$userId = $this->args[0];
|
||||
$user = $this->getUser($userId);
|
||||
$feedId = $this->args[1];
|
||||
|
@ -426,7 +425,7 @@ class ServerShell extends AppShell
|
|||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['Cache server'] . PHP_EOL);
|
||||
}
|
||||
|
||||
|
||||
$userId = $this->args[0];
|
||||
$user = $this->getUser($userId);
|
||||
$scope = $this->args[1];
|
||||
|
@ -489,7 +488,7 @@ class ServerShell extends AppShell
|
|||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['Cache feeds for quick lookups'] . PHP_EOL);
|
||||
}
|
||||
|
||||
|
||||
$userId = $this->args[0];
|
||||
$user = $this->getUser($userId);
|
||||
$scope = $this->args[1];
|
||||
|
@ -735,6 +734,7 @@ class ServerShell extends AppShell
|
|||
|
||||
public function sendPeriodicSummaryToUsers()
|
||||
{
|
||||
|
||||
$periods = $this->__getPeriodsForToday();
|
||||
$start_time = time();
|
||||
echo __n('Started periodic summary generation for the %s period', 'Started periodic summary generation for periods: %s', count($periods), implode(', ', $periods)) . PHP_EOL;
|
||||
|
@ -800,7 +800,7 @@ class ServerShell extends AppShell
|
|||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['Push Taxii'] . PHP_EOL);
|
||||
}
|
||||
|
||||
|
||||
$userId = $this->args[0];
|
||||
$user = $this->getUser($userId);
|
||||
$serverId = $this->args[1];
|
||||
|
|
|
@ -40,6 +40,12 @@ class AppController extends Controller
|
|||
public $phptoonew = '8.0';
|
||||
private $isApiAuthed = false;
|
||||
|
||||
/** @var redis */
|
||||
private $redis = null;
|
||||
|
||||
/** @var benchmark_results */
|
||||
private $benchmark_results = null;
|
||||
|
||||
public $baseurl = '';
|
||||
|
||||
public $restResponsePayload = null;
|
||||
|
@ -57,9 +63,14 @@ class AppController extends Controller
|
|||
/** @var ACLComponent */
|
||||
public $ACL;
|
||||
|
||||
/** @var BenchmarkComponent */
|
||||
public $Benchmark;
|
||||
|
||||
/** @var RestResponseComponent */
|
||||
public $RestResponse;
|
||||
|
||||
public $start_time;
|
||||
|
||||
public function __construct($request = null, $response = null)
|
||||
{
|
||||
parent::__construct($request, $response);
|
||||
|
@ -97,6 +108,12 @@ class AppController extends Controller
|
|||
|
||||
public function beforeFilter()
|
||||
{
|
||||
$this->User = ClassRegistry::init('User');
|
||||
if (Configure::read('Plugin.Benchmarking_enable')) {
|
||||
App::uses('BenchmarkTool', 'Tools');
|
||||
$this->Benchmark = new BenchmarkTool($this->User);
|
||||
$this->start_time = $this->Benchmark->startBenchmark();
|
||||
}
|
||||
$controller = $this->request->params['controller'];
|
||||
$action = $this->request->params['action'];
|
||||
|
||||
|
@ -147,8 +164,6 @@ class AppController extends Controller
|
|||
Configure::write('Config.language', 'eng');
|
||||
}
|
||||
|
||||
$this->User = ClassRegistry::init('User');
|
||||
|
||||
if (!empty($this->request->params['named']['disable_background_processing'])) {
|
||||
Configure::write('MISP.background_jobs', 0);
|
||||
}
|
||||
|
@ -863,6 +878,21 @@ class AppController extends Controller
|
|||
|
||||
public function afterFilter()
|
||||
{
|
||||
// benchmarking
|
||||
if (Configure::read('Plugin.Benchmarking_enable')) {
|
||||
$this->Benchmark->stopBenchmark([
|
||||
'user' => $this->Auth->user('id'),
|
||||
'controller' => $this->request->params['controller'],
|
||||
'action' => $this->request->params['action'],
|
||||
'start_time' => $this->start_time
|
||||
]);
|
||||
|
||||
//if ($redis && !$redis->exists('misp:auth_fail_throttling:' . $key)) {
|
||||
//$redis->setex('misp:auth_fail_throttling:' . $key, 3600, 1);
|
||||
//return true;
|
||||
//}
|
||||
|
||||
}
|
||||
if ($this->isApiAuthed && $this->_isRest() && !Configure::read('Security.authkey_keep_session')) {
|
||||
$this->Session->destroy();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
|
||||
class BenchmarksController extends AppController
|
||||
{
|
||||
public $components = array('Session', 'RequestHandler');
|
||||
|
||||
public $paginate = [
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999,
|
||||
|
||||
];
|
||||
|
||||
public function beforeFilter()
|
||||
{
|
||||
parent::beforeFilter();
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->set('menuData', ['menuList' => 'admin', 'menuItem' => 'index']);
|
||||
$this->loadModel('User');
|
||||
App::uses('BenchmarkTool', 'Tools');
|
||||
$this->Benchmark = new BenchmarkTool($this->User);
|
||||
$passedArgs = $this->passedArgs;
|
||||
$this->paginate['order'] = 'value';
|
||||
$defaults = [
|
||||
'days' => null,
|
||||
'average' => false,
|
||||
'aggregate' => false,
|
||||
'scope' => null,
|
||||
'field' => null,
|
||||
'key' => null,
|
||||
'quickFilter' => null
|
||||
];
|
||||
$filters = $this->IndexFilter->harvestParameters(array_keys($defaults));
|
||||
foreach ($defaults as $key => $value) {
|
||||
if (!isset($filters[$key])) {
|
||||
$filters[$key] = $defaults[$key];
|
||||
}
|
||||
}
|
||||
$temp = $this->Benchmark->getAllTopLists(
|
||||
$filters['days'] ?? null,
|
||||
$filters['limit'] ?? 100,
|
||||
$filters['average'] ?? null,
|
||||
$filters['aggregate'] ?? null
|
||||
);
|
||||
$settings = $this->Benchmark->getSettings();
|
||||
$units = $this->Benchmark->getUnits();
|
||||
$this->set('settings', $settings);
|
||||
$data = [];
|
||||
$userLookup = [];
|
||||
foreach ($temp as $scope => $t) {
|
||||
if (!empty($filters['scope']) && $filters['scope'] !== 'all' && $scope !== $filters['scope']) {
|
||||
continue;
|
||||
}
|
||||
foreach ($t as $field => $t2) {
|
||||
if (!empty($filters['field']) && $filters['field'] !== 'all' && $field !== $filters['field']) {
|
||||
continue;
|
||||
}
|
||||
foreach ($t2 as $date => $t3) {
|
||||
foreach ($t3 as $key => $value) {
|
||||
if ($scope == 'user') {
|
||||
if ($key === 'SYSTEM') {
|
||||
$text = 'SYSTEM';
|
||||
} else if (isset($userLookup[$key])) {
|
||||
$text = $userLookup[$key];
|
||||
} else {
|
||||
$user = $this->User->find('first', [
|
||||
'fields' => ['User.id', 'User.email'],
|
||||
'recursive' => -1,
|
||||
'conditions' => ['User.id' => $key]
|
||||
]);
|
||||
if (empty($user)) {
|
||||
$text = '(' . $key . ') ' . __('Invalid user');
|
||||
} else {
|
||||
$text = '(' . $key . ') ' . $user['User']['email'];
|
||||
}
|
||||
$userLookup[$key] = $text;
|
||||
}
|
||||
} else {
|
||||
$text = $key;
|
||||
}
|
||||
if (!empty($filters['quickFilter'])) {
|
||||
$q = strtolower($filters['quickFilter']);
|
||||
if (
|
||||
strpos(strtolower($scope), $q) === false &&
|
||||
strpos(strtolower($field), $q) === false &&
|
||||
strpos(strtolower($key), $q) === false &&
|
||||
strpos(strtolower($value), $q) === false &&
|
||||
strpos(strtolower($date), $q) === false &&
|
||||
strpos(strtolower($text), $q) === false
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (empty($filters['key']) || $key == $filters['key']) {
|
||||
$data[] = [
|
||||
'scope' => $scope,
|
||||
'field' => $field,
|
||||
'date' => $date,
|
||||
'key' => $key,
|
||||
'text' => $text,
|
||||
'value' => $value,
|
||||
'unit' => $units[$field]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
}
|
||||
App::uses('CustomPaginationTool', 'Tools');
|
||||
$customPagination = new CustomPaginationTool();
|
||||
$customPagination->truncateAndPaginate($data, $this->params, $this->modelClass, true);
|
||||
$this->set('data', $data);
|
||||
$this->set('passedArgs', json_encode($passedArgs));
|
||||
$this->set('filters', $filters);
|
||||
}
|
||||
|
||||
}
|
|
@ -95,6 +95,9 @@ class ACLComponent extends Component
|
|||
'index' => ['perm_auth'],
|
||||
'view' => ['perm_auth'],
|
||||
],
|
||||
'benchmarks' => [
|
||||
'index' => []
|
||||
],
|
||||
'cerebrates' => [
|
||||
'add' => [],
|
||||
'delete' => [],
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
|
||||
class BenchmarkTopListWidget
|
||||
{
|
||||
public $title = 'Benchmark top list';
|
||||
public $render = 'MultiLineChart';
|
||||
public $width = 3;
|
||||
public $height = 3;
|
||||
public $description = 'A graph showing the top list for a given scope and field in the captured metrics.';
|
||||
public $cacheLifetime = false;
|
||||
public $autoRefreshDelay = 30;
|
||||
public $params = array(
|
||||
'days' => 'Number of days to consider for the graph. There will be a data entry for each day (assuming the benchmarking has been enabled). Defaults to returning all data.',
|
||||
'weeks' => 'Number of weeks to consider for the graph. There will be a data entry for each day (assuming the benchmarking has been enabled). Defaults to returning all data.',
|
||||
'months' => 'Number of months to consider for the graph. There will be a data entry for each day (assuming the benchmarking has been enabled). Defaults to returning all data.',
|
||||
'scope' => 'The scope of the benchmarking refers to what was being tracked. The following scopes are valid: user, endpoint, user_agent',
|
||||
'field' => 'The individual metric to be queried from the benchmark results. Valid values are: time, sql_time, sql_queries, memory, endpoint',
|
||||
'average' => 'If you wish to view the averages per scope/field, set this variable to true. It will divide the result by the number of executions recorded for the scope/field combination for the given day.'
|
||||
);
|
||||
public $Benchmark;
|
||||
public $User;
|
||||
|
||||
public $placeholder =
|
||||
'{
|
||||
"days": "30",
|
||||
"scope": "endpoints",
|
||||
"field": "sql_time"
|
||||
}';
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
$this->User = ClassRegistry::init('User');
|
||||
$currentTime = strtotime("now");
|
||||
$endOfDay = strtotime("tomorrow", $currentTime) - 1;
|
||||
if (!empty($options['days'])) {
|
||||
$limit = (int)($options['days']);
|
||||
$delta = 'day';
|
||||
} else if (!empty($options['weeks'])) {
|
||||
$limit = (int)($options['weeks']);
|
||||
$delta = 'week';
|
||||
} else if (!empty($options['months'])) {
|
||||
$limit = (int)($options['months']);
|
||||
$delta = 'month';
|
||||
} else {
|
||||
$limit = 30;
|
||||
$delta = 'day';
|
||||
}
|
||||
$axis_info = [
|
||||
'time' => 'Total time taken (ms)',
|
||||
'sql_time' => 'SQL time taken (ms)',
|
||||
'sql_queries' => 'Queries (#)',
|
||||
'memory' => 'Memory (MB)',
|
||||
'endpoint' => 'Queries to endpoint (#)'
|
||||
];
|
||||
$y_axis = $axis_info[isset($options['field']) ? $options['field'] : 'time'];
|
||||
$data = ['y-axis' => $y_axis];
|
||||
$data['data'] = array();
|
||||
// Add total users data for all timestamps
|
||||
|
||||
for ($i = 0; $i < $limit; $i++) {
|
||||
$itemTime = strtotime('- ' . $i . $delta, $endOfDay);
|
||||
$item = array();
|
||||
$date = strftime('%Y-%m-%d', $itemTime);
|
||||
$item = $this->getData($date, $options);
|
||||
if (!empty($item)) {
|
||||
$item['date'] = $date;
|
||||
$data['data'][] = $item;
|
||||
}
|
||||
}
|
||||
$keys = [];
|
||||
foreach ($data['data'] as $day_data) {
|
||||
foreach ($day_data as $key => $temp) {
|
||||
$keys[$key] = 1;
|
||||
}
|
||||
}
|
||||
$keys = array_keys($keys);
|
||||
foreach ($data['data'] as $k => $day_data) {
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($day_data[$key])) {
|
||||
$data['data'][$k][$key] = 0;
|
||||
}
|
||||
}
|
||||
foreach ($day_data as $key => $temp) {
|
||||
$keys[$key] = 1;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getData($time, $options)
|
||||
{
|
||||
$dates = [$time];
|
||||
$this->Benchmark = new BenchmarkTool($this->User);
|
||||
$result = $this->Benchmark->getTopList(
|
||||
isset($options['scope']) ? $options['scope'] : 'endpoint',
|
||||
isset($options['field']) ? $options['field'] : 'memory',
|
||||
$dates,
|
||||
isset($options['limit']) ? $options['limit'] : 5,
|
||||
isset($options['average']) ? $options['average'] : false,
|
||||
);
|
||||
if (!empty($result)) {
|
||||
return $result[$time];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkPermissions($user)
|
||||
{
|
||||
if (empty($user['Role']['perm_site_admin'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Get filter parameters from index searches
|
||||
*/
|
||||
|
||||
class BenchmarkTool
|
||||
{
|
||||
/** @var Model */
|
||||
public $Model;
|
||||
|
||||
/** @var redis */
|
||||
public $redis;
|
||||
|
||||
/** @var retention */
|
||||
private $retention = 0;
|
||||
|
||||
/** @var start_time */
|
||||
public $start_timexxx;
|
||||
|
||||
const BENCHMARK_SCOPES = ['user', 'endpoint', 'user_agent'];
|
||||
const BENCHMARK_FIELDS = ['time', 'sql_time', 'sql_queries', 'memory'];
|
||||
const BENCHMARK_UNITS = [
|
||||
'time' => 's',
|
||||
'sql_time' => 'ms',
|
||||
'sql_queries' => '',
|
||||
'memory' => 'MB'
|
||||
];
|
||||
|
||||
public $namespace = 'misp:benchmark:';
|
||||
|
||||
function __construct(Model $model) {
|
||||
$this->Model = $model;
|
||||
}
|
||||
|
||||
public function getSettings()
|
||||
{
|
||||
return [
|
||||
'scope' => self::BENCHMARK_SCOPES,
|
||||
'field' => self::BENCHMARK_FIELDS,
|
||||
'average' => [0, 1],
|
||||
'aggregate' => [0, 1]
|
||||
];
|
||||
}
|
||||
|
||||
public function getUnits()
|
||||
{
|
||||
return self::BENCHMARK_UNITS;
|
||||
}
|
||||
|
||||
public function startBenchmark()
|
||||
{
|
||||
$start_time = microtime(true);
|
||||
$this->redis = $this->Model->setupRedis();
|
||||
$this->retention = Configure::check('Plugin.benchmark_retention') ? Configure::read('Plugin.benchmark_retention') : 0;
|
||||
return $start_time;
|
||||
}
|
||||
|
||||
public function stopBenchmark(array $options)
|
||||
{
|
||||
$start_time = $options['start_time'];
|
||||
if (!empty($options['user'])) {
|
||||
$sql = $this->Model->getDataSource()->getLog(false, false);
|
||||
$benchmarkData = [
|
||||
'user' => $options['user'],
|
||||
'endpoint' => $options['controller'] . '/' . $options['action'],
|
||||
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
|
||||
'sql_queries' => $sql['count'],
|
||||
'sql_time' => $sql['time'],
|
||||
'time' => (microtime(true) - $start_time),
|
||||
'memory' => (int)(memory_get_peak_usage(true) / 1024 / 1024),
|
||||
//'date' => date('Y-m-d', strtotime("-3 days"))
|
||||
'date' => date('Y-m-d')
|
||||
];
|
||||
$this->pushBenchmarkDataToRedis($benchmarkData);
|
||||
} else {
|
||||
$sql = $this->Model->getDataSource()->getLog(false, false);
|
||||
$benchmarkData = [
|
||||
'user' => 'SYSTEM',
|
||||
'endpoint' => $options['controller'] . '/' . $options['action'],
|
||||
'user_agent' => 'CLI',
|
||||
'sql_queries' => $sql['count'],
|
||||
'sql_time' => $sql['time'],
|
||||
'time' => (microtime(true) - $start_time),
|
||||
'memory' => (int)(memory_get_peak_usage(true) / 1024 / 1024),
|
||||
//'date' => date('Y-m-d', strtotime("-3 days"))
|
||||
'date' => date('Y-m-d')
|
||||
];
|
||||
$this->pushBenchmarkDataToRedis($benchmarkData);
|
||||
}
|
||||
}
|
||||
|
||||
private function pushBenchmarkDataToRedis($benchmarkData)
|
||||
{
|
||||
$this->redis = $this->Model->setupRedis();
|
||||
$this->redis->pipeline();
|
||||
$this->redis->sAdd(
|
||||
$this->namespace . 'days',
|
||||
$benchmarkData['date']
|
||||
);
|
||||
foreach (self::BENCHMARK_SCOPES as $scope) {
|
||||
$this->redis->sAdd(
|
||||
$this->namespace . $scope . ':list',
|
||||
$benchmarkData[$scope]
|
||||
);
|
||||
$this->redis->zIncrBy(
|
||||
$this->namespace . $scope . ':count:' . $benchmarkData['date'],
|
||||
1,
|
||||
$benchmarkData[$scope]
|
||||
);
|
||||
foreach (self::BENCHMARK_FIELDS as $field) {
|
||||
$this->redis->zIncrBy(
|
||||
$this->namespace . $scope . ':' . $field . ':' . $benchmarkData['date'],
|
||||
$benchmarkData[$field],
|
||||
$benchmarkData[$scope]
|
||||
);
|
||||
}
|
||||
$this->redis->zIncrBy(
|
||||
$this->namespace . $scope . ':endpoint:' . $benchmarkData['date'] . ':' . $benchmarkData['user'],
|
||||
1,
|
||||
$benchmarkData['endpoint']
|
||||
);
|
||||
}
|
||||
$this->redis->exec();
|
||||
}
|
||||
|
||||
public function getTopList(string $scope, string $field, array $days = [], $limit = 10, $average = false, $aggregate = false)
|
||||
{
|
||||
if (empty($this->redis)) {
|
||||
$this->redis = $this->Model->setupRedis();
|
||||
}
|
||||
$results = [];
|
||||
if (is_string($days)) {
|
||||
$days = [$days];
|
||||
}
|
||||
foreach ($days as $day) {
|
||||
$temp = $this->redis->zrevrange($this->namespace . $scope . ':' . $field . ':' . $day, 0, $limit, true);
|
||||
foreach ($temp as $k => $v) {
|
||||
if ($average) {
|
||||
$divisor = $this->redis->zscore($this->namespace . $scope . ':count:' . $day, $k);
|
||||
if ($aggregate) {
|
||||
$results['aggregate'][$k] = empty($results['aggregate'][$k]) ? ($v / $divisor) : ($results['aggregate'][$k] + ($v / $divisor));
|
||||
} else {
|
||||
$results[$day][$k] = (int)($v / $divisor);
|
||||
}
|
||||
} else {
|
||||
if ($aggregate) {
|
||||
$results['aggregate'][$k] = empty($results['aggregate'][$k]) ? $v : ($results['aggregate'][$k] + $v);
|
||||
} else {
|
||||
$results[$day][$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($aggregate && $average) {
|
||||
$count_days = count($days);
|
||||
foreach ($results['aggregate'] as $k => $result) {
|
||||
$results['aggregate'][$k] = (int)($result / $count_days);
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function getAllTopLists(array $days = null, $limit = 10, $average = false, $aggregate = false, $scope_filter = [])
|
||||
{
|
||||
if (empty($this->redis)) {
|
||||
$this->redis = $this->Model->setupRedis();
|
||||
}
|
||||
if ($days === null) {
|
||||
$days = $this->redis->smembers($this->namespace . 'days');
|
||||
}
|
||||
foreach (self::BENCHMARK_SCOPES as $scope) {
|
||||
if (empty($scope_filter) || in_array($scope, $scope_filter)) {
|
||||
foreach (self::BENCHMARK_FIELDS as $field) {
|
||||
$results[$scope][$field] = $this->getTopList($scope, $field, $days, $limit, $average, $aggregate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
|
||||
class Benchmark extends AppModel
|
||||
{
|
||||
}
|
|
@ -7536,6 +7536,13 @@ class Server extends AppModel
|
|||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
),
|
||||
'Benchmarking_enable' => [
|
||||
'level' => 2,
|
||||
'description' => __('Enable the benchmarking functionalities to capture information about execution times, SQL query loads and more per user and per endpoint.'),
|
||||
'value' => false,
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
],
|
||||
'Enrichment_services_enable' => array(
|
||||
'level' => 0,
|
||||
'description' => __('Enable/disable the enrichment services'),
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
$passedArgsArray = json_decode($passedArgs, true);
|
||||
$fields = [
|
||||
[
|
||||
'name' => __('Date'),
|
||||
'sort' => 'date',
|
||||
'data_path' => 'date'
|
||||
],
|
||||
[
|
||||
'name' => __('scope'),
|
||||
'sort' => 'scope',
|
||||
'data_path' => 'scope'
|
||||
],
|
||||
[
|
||||
'name' => __('Key'),
|
||||
'sort' => 'key',
|
||||
'data_path' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => __('field'),
|
||||
'sort' => 'field',
|
||||
'data_path' => 'field'
|
||||
],
|
||||
[
|
||||
'name' => __('Value'),
|
||||
'element' => 'custom',
|
||||
'function' => function($row) {
|
||||
return empty($row['unit']) ? h($row['value']) : h($row['value'] . ' ' . $row['unit']);
|
||||
},
|
||||
'sort' => 'value'
|
||||
]
|
||||
];
|
||||
$quick_filters = [];
|
||||
foreach ($settings as $key => $setting_data) {
|
||||
$temp = $filters;
|
||||
$url = $baseurl . '/benchmarks/index';
|
||||
foreach ($temp as $s => $v) {
|
||||
if ($v && $s != $key) {
|
||||
if (is_array($v)) {
|
||||
foreach ($v as $multi_v) {
|
||||
$url .= '/' . $s . '[]:' . $multi_v;
|
||||
}
|
||||
} else {
|
||||
$url .= '/' . $s . ':' . $v;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if ($key != 'average' && $key != 'aggregate') {
|
||||
$quick_filters[$key]['all'] = [
|
||||
'url' => h($url),
|
||||
'text' => __('All'),
|
||||
'active' => !$filters[$key],
|
||||
'style' => 'display:inline;'
|
||||
];
|
||||
}
|
||||
foreach ($setting_data as $setting_element) {
|
||||
$text = $setting_element;
|
||||
if ($key == 'average') {
|
||||
$text = $setting_element ? 'average / request' : 'total';
|
||||
}
|
||||
if ($key == 'aggregate') {
|
||||
$text = $setting_element ? 'aggregate' : 'daily';
|
||||
}
|
||||
$quick_filters[$key][] = [
|
||||
'url' => h($url . '/' . $key . ':' . $setting_element),
|
||||
'text' => $text,
|
||||
'active' => $filters[$key] == $setting_element,
|
||||
'style' => 'display:inline;'
|
||||
];
|
||||
}
|
||||
}
|
||||
echo $this->element('genericElements/IndexTable/scaffold', [
|
||||
'scaffold_data' => [
|
||||
'passedArgsArray' => $passedArgsArray,
|
||||
'data' => [
|
||||
'persistUrlParams' => array_keys($settings),
|
||||
'data' => $data,
|
||||
'top_bar' => [
|
||||
'pull' => 'right',
|
||||
'children' => [
|
||||
[
|
||||
'children' => $quick_filters['scope']
|
||||
],
|
||||
[
|
||||
'children' => $quick_filters['field']
|
||||
],
|
||||
[
|
||||
'children' => $quick_filters['average']
|
||||
],
|
||||
[
|
||||
'children' => $quick_filters['aggregate']
|
||||
],
|
||||
[
|
||||
'type' => 'search',
|
||||
'button' => __('Filter'),
|
||||
'placeholder' => __('Enter value to search'),
|
||||
'data' => '',
|
||||
'searchKey' => 'quickFilter'
|
||||
]
|
||||
]
|
||||
],
|
||||
'fields' => $fields,
|
||||
'title' => empty($ajax) ? __('Benchmark results') : false,
|
||||
'description' => empty($ajax) ? __('Results of the collected benchmarks. You can filter it further by passing the limit, scope, field parameters.') : false,
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
?>
|
|
@ -6,6 +6,7 @@
|
|||
h($data['formula'])
|
||||
);
|
||||
}
|
||||
$y_axis = $data['y-axis'] ?? 'Count';
|
||||
?>
|
||||
<div id="chartContainer-<?= $seed ?>" style="flex-grow: 1; position:relative;"></div>
|
||||
<script>
|
||||
|
@ -50,7 +51,7 @@ function init<?= $seed ?>() { // variables and functions have their own scope (n
|
|||
show_legend: true,
|
||||
style: {
|
||||
xlabel: "Date",
|
||||
ylabel: "Count",
|
||||
ylabel: "<?= h($y_axis) ?>",
|
||||
hideXAxis: false,
|
||||
hideYAxis: false,
|
||||
},
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
if (!empty($data['persistUrlParams'])) {
|
||||
foreach ($data['persistUrlParams'] as $persistedParam) {
|
||||
if (!empty($passedArgsArray[$persistedParam])) {
|
||||
$data['paginatorOptions']['url'][] = $passedArgsArray[$persistedParam];
|
||||
$data['paginatorOptions']['url'][$persistedParam] = $passedArgsArray[$persistedParam];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1100,6 +1100,13 @@ $divider = '<li class="divider"></li>';
|
|||
'url' => $baseurl . '/servers/updateProgress',
|
||||
'text' => __('Update Progress')
|
||||
));
|
||||
if (Configure::read('Plugin.Benchmarking_enable')) {
|
||||
echo $divider;
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'url' => $baseurl . '/benchmarks/index',
|
||||
'text' => __('Benchmarks')
|
||||
));
|
||||
}
|
||||
echo $divider;
|
||||
if (Configure::read('MISP.background_jobs')) {
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
|
|
|
@ -408,6 +408,11 @@ if (!empty($me)) {
|
|||
'url' => $baseurl . '/servers/serverSettings',
|
||||
'requirement' => $isSiteAdmin
|
||||
),
|
||||
[
|
||||
'text' => __('Benchmarking'),
|
||||
'url' => $baseurl . '/benchmarks/index',
|
||||
'requirement' => $isSiteAdmin && Configure::read('Plugin.Benchmarking_enable')
|
||||
],
|
||||
array(
|
||||
'type' => 'separator',
|
||||
'requirement' => $isSiteAdmin
|
||||
|
|
|
@ -177,7 +177,7 @@ if ($isAdmin && $isTotp) {
|
|||
'js' => array('vis', 'jquery-ui.min', 'network-distribution-graph')
|
||||
));
|
||||
echo sprintf(
|
||||
'<div class="users view"><div class="row-fluid"><div class="span8" style="margin:0px;">%s</div></div>%s%s%s<div style="margin-top:20px;">%s%s</div></div>',
|
||||
'<div class="users view"><div class="row-fluid"><div class="span8" style="margin:0px;">%s</div></div>%s%s%s<div style="margin-top:20px;">%s%s%s</div></div>',
|
||||
sprintf(
|
||||
'<h2>%s</h2>%s',
|
||||
__('User %s', h($user['User']['email'])),
|
||||
|
@ -210,6 +210,15 @@ if ($isAdmin && $isTotp) {
|
|||
__('Review user logins')
|
||||
),
|
||||
$me['Role']['perm_auth'] ? $this->element('/genericElements/accordion', array('title' => __('Auth keys'), 'url' => '/auth_keys/index/' . h($user['User']['id']))) : '',
|
||||
$me['Role']['perm_site_admin'] ?
|
||||
$this->element(
|
||||
'/genericElements/accordion',
|
||||
[
|
||||
'title' => __('Benchmarks'),
|
||||
'url' => '/benchmarks/index/scope:user/average:1/aggregate:1/key:' . h($user['User']['id'])
|
||||
]
|
||||
) :
|
||||
'',
|
||||
$this->element('/genericElements/accordion', array('title' => 'Events', 'url' => '/events/index/searchemail:' . urlencode(h($user['User']['email']))))
|
||||
);
|
||||
$current_menu = [
|
||||
|
|
Loading…
Reference in New Issue