<?php namespace App\Http\Controllers; use Cylab\Mark\Client; class MarkController extends Controller { private $server; private function server() { if ($this->server === null) { $mark_url = 'http://' . config("app.mark_host") . ':' . config('app.mark_port'); $this->server = new Client($mark_url); // test we can connect to the server try { $this->server->test(); } catch (\JsonRPC\Exception\ConnectionFailureException $ex) { session()->flash('error', 'Failed to connect to MARK server at ' . $mark_url); abort(redirect('app/error')); } } return $this->server; } public function error() { return view('app.error', ["message" => session()->pull('error')]); } public function status() { $status = $this->server()->status(); $status_history = $this->server()->history(); $history_memory = $this->extractPoints($status_history, "memory_used"); $history_load = $this->extractPoints($status_history, "load"); $history_jobs_executed = $this->extractPoints($status_history, "executor_jobs_executed"); $history_jobs_execution_rate = $this->computeExecutionRate($history_jobs_executed); return view("app.status", [ "status" => $status, "history_memory" => $history_memory, "history_load" => $history_load, "history_jobs_execution_rate" => $history_jobs_execution_rate]); } public function pause() { $this->server()->pause(); return redirect(action('MarkController@status')); } public function resume() { $this->server()->resume(); return redirect(action('MarkController@status')); } public function reload() { $this->server()->reload(); return redirect(action('MarkController@status')); } public function ranking(string $label) { // find the detector corresponding to this label $detectors = $this->server()->activation(); $detector = null; foreach ($detectors as $d) { if ($d->label == $label) { $detector = $d; break; } } $evidences = $this->server()->findEvidence($label); $now = \Carbon\Carbon::now(); return view( "app.ranking", [ "label" => $label, "evidences" => $evidences, "detector" => $detector, "now" => $now] ); } public function rankingHome() { $activation_graph_elements = []; $detectors = $this->server()->activation(); // nodes foreach ($detectors as $detector) { // node $activation_graph_elements[] = ["data" => ["id" => $detector->label]]; // edges $sources = $this->findSources($detectors, $detector); foreach ($sources as $source) { $activation_graph_elements[] = ["data" => [ "id" => rand(), "source" => $source, "target" => $detector->label]]; } if (count($sources) == 0) { // the trigger_label for this detector is a data source // => create node + edge $activation_graph_elements[] = ["data" => ["id" => $detector->trigger_label]]; $activation_graph_elements[] = ["data" => [ "id" => rand(), "source" => $detector->trigger_label, "target" => $detector->label]]; } } return view("app.detectors", ["activation_graph_elements" => $activation_graph_elements]); } private function findSources(array $all_detectors, $detector) { $pattern = '/' . $detector->trigger_label . '/'; $sources = []; foreach ($all_detectors as $d) { if (preg_match($pattern, $d->label)) { $sources[] = $d->label; } } return $sources; } public function extractPoints(array $evidences, string $field) : array { $points = []; foreach ($evidences as $evidence) { // used by status history // this is dirty :-( // status history should return an array of objects if (is_array($evidence)) { $points[] = new \App\TimePoint( $evidence["time"], $evidence[$field] ); } else { $points[] = new \App\TimePoint( $evidence->time, $evidence->$field ); } } return $points; } public function evidence(string $id) { $time_window = 3600; // in seconds $ev = $this->server()->findEvidenceById($id); $since = $ev->time - $time_window * 1000; $references = []; foreach ($ev->references as $id) { $references[] = $this->server()->findEvidenceById($id); } $history = $this->server()->findEvidenceSince($ev->label, $ev->subject, $since); return view( 'app.evidence', [ "evidence" => $ev, "history" => $history, "history_points" => $this->extractPoints($history, "score"), "references" => $references] ); } public function evidenceData(string $id, $data_id) { $ev = $this->server()->findEvidenceById($id); $query = $ev->requests[$data_id]; $data = $this->server->findData($query); return view('app.data', [ "evidence" => $ev, "query" => $query, "data" => $data ]); } /** * Compute the number of jobs executed per minute. * * @param array $history_jobs_executed * @return array */ private function computeExecutionRate(array $history_jobs_executed) : array { if (count($history_jobs_executed) < 2) { // not enough points to compute execution rate... return []; } $points = []; $last_point_time = $history_jobs_executed[0]->t; $last_point_value = $history_jobs_executed[0]->y; foreach ($history_jobs_executed as $point) { // this point is less than a minute after the last computed point if (($point->t - $last_point_time) < 60000) { continue; } $points[] = new \App\TimePoint($point->t, $point->y - $last_point_value); $last_point_time = $point->t; $last_point_value = $point->y; } return $points; } }