Merge "Make it possible to sort on simple custom columns"
[ninja.git] / modules / reports / libraries / SingleStateCalculator.php
blobc175375a5d34c90369e763f6a09c1e051e917fff
1 <?php
3 /**
4 * State calculator for a single object - thus more of a state.. keeper?
5 */
6 class SingleStateCalculator extends StateCalculator
8 protected $st_last_dt_init = 1; /**< set to FALSE on nagios restart, and a timestamp on first DT start after restart, so we can exclude duplicate downtime_start */
9 protected $st_real_state = false; /**< The real state of the object */
10 public $st_log = false; /**< The log array, only used for treds, should use summary reports for this */
12 public function initialize($initial_state, $initial_depth, $is_running)
14 parent::initialize($initial_state, $initial_depth, $is_running);
16 # if user asked for it, we preserve the log
17 # TODO: noes :(
18 if ($this->options['include_trends']) {
19 $this->st_log = array();
22 $this->st_real_state = $initial_state;
23 # Warning: PHP sucks.
24 # In this particular instance, everything array-related breaks if the
25 # array is stored in an array object. Hence, recover and then call current()
26 if ($this->st_is_service) {
27 $arr = $this->options['service_description'];
28 $this->st_source = current($arr);
29 $srv = explode(';', $this->st_source);
30 $this->host_name = $srv[0];
31 $this->service_description = $srv[1];
32 } else {
33 $arr = $this->options['host_name'];
34 $this->host_name = $this->st_source = current($arr);
36 $this->calculate_object_state();
37 $this->prev_row['state'] = $this->st_obj_state;
40 /**
41 * Take a database row object, and parse it
42 * @param $row Database row
44 public function add_event($row = false)
46 $obj_name = $obj_type = false;
47 if (!empty($row['service_description'])) {
48 $obj_name = $row['host_name'] . ";" . $row['service_description'];
49 $obj_type = 'Service';
51 elseif (!empty($row['host_name'])) {
52 $obj_name = $row['host_name'];
53 $obj_type = 'Host';
56 if ($obj_name !== $this->st_source && ($obj_name !== $this->host_name || $row['event_type'] < Reports_Model::DOWNTIME_START) && $row['event_type'] > Reports_Model::PROCESS_SHUTDOWN)
57 return;
59 $this->st_update($row['the_time']);
61 switch($row['event_type']) {
62 case Reports_Model::PROCESS_START:
63 case Reports_Model::PROCESS_SHUTDOWN:
64 if ($row['event_type'] == Reports_Model::PROCESS_START) {
65 $row['output'] = 'Monitor started';
67 else {
68 $row['output'] = 'Monitor shut down';
70 $this->st_last_dt_init = false;
71 if ($row['event_type'] == Reports_Model::PROCESS_START) {
72 $row['state'] = $this->st_real_state;
73 $this->st_running = 1;
74 } else if ($this->options['assumestatesduringnotrunning']) {
75 $row['state'] = $this->st_real_state;
76 } else {
77 $row['state'] = -1;
78 $this->st_running = 0;
80 break;
81 case Reports_Model::DOWNTIME_START:
82 if(!isset($row['output']) || !$row['output']) {
83 $row['output'] = $obj_type . ' has entered a period of scheduled downtime';
85 $add = 0;
86 # we are always spammed with downtime events after restart, so
87 # don't increase the downtime depth if we're already in downtime
88 if (!$this->st_last_dt_init || $this->st_last_dt_init === $row['the_time']) {
89 $this->st_last_dt_init = $row['the_time'];
90 if (!$this->st_dt_depth) {
91 $add = 1;
94 else {
95 $add = 1;
97 if ($add) {
98 $this->st_dt_depth+=1;
100 break;
101 case Reports_Model::DOWNTIME_STOP:
102 if(!isset($row['output']) || !$row['output']) {
103 $row['output'] = $obj_type . ' has exited a period of scheduled downtime';
105 # old merlin versions created more end events than start events, so
106 # never decrement if we're already at 0.
107 if ($this->st_dt_depth) {
108 $this->st_dt_depth-=1;
110 break;
111 case Reports_Model::SERVICECHECK:
112 case Reports_Model::HOSTCHECK:
113 $state = $row['state'];
115 # update the real state of the object
116 if ($this->st_source === $obj_name) {
117 $this->st_real_state = $row['state'];
119 break;
120 default:
121 //ERROR
124 $this->calculate_object_state();
125 # TODO: Ahrm...
126 $this->st_update_log($row);
130 * Manually excluded states are excluded here.
132 * @param $state int
133 * @return int
135 protected function filter_excluded_state($state) {
136 if ($this->st_is_service && isset($this->options['service_filter_status'][$state]))
137 return $this->options['service_filter_status'][$state];
138 else if (isset($this->options['host_filter_status'][$state]))
139 return $this->options['host_filter_status'][$state];
140 return $state;
144 * Calculate the object state, based on the chosen state calculator.
146 * If there is sub reports, the argument will be ignored. Otherwise, use
147 * either the argument or the object's real state, according to magical
148 * properties inherent in the numbers themselves.
150 public function calculate_object_state()
152 $this->st_obj_state = $this->filter_excluded_state($this->st_real_state);
155 public function get_data()
157 $converted_state = $this->convert_state_table($this->st_raw, $this->st_text);
159 # state template array depends on what we are checking
160 $tpl = $this->state_tpl_host;
161 if ($this->st_is_service)
162 $tpl = $this->state_tpl_svc;
163 foreach ($tpl as $t => $discard)
164 if (!isset($converted_state[$t]))
165 $converted_state[$t] = 0;
167 $converted_state['HOST_NAME'] = $this->host_name;
168 if ($this->st_is_service)
169 $converted_state['SERVICE_DESCRIPTION'] = $this->service_description;
171 # now add the time we didn't count due
172 # to the selected timeperiod
173 $converted_state['TIME_INACTIVE'] = $this->st_inactive;
175 $total_time = $this->options['end_time'] - $this->options['start_time'];
177 return array('source' => $this->st_source, 'log' => $this->st_log, 'states' => $converted_state, 'tot_time' => $total_time);
181 * Deprecated method that keeps the log around for the benefit of the trend graph
183 protected function st_update_log($row = false)
185 if($row) {
186 $row['state'] = $this->st_obj_state;
188 if (!$this->options['include_trends']) {
189 $this->prev_row = $row;
190 return;
193 # called from finalize(), so bail out early
194 if (!$row) {
195 $this->prev_row['duration'] = $this->options['end_time'] - $this->prev_row['the_time'];
196 $active = $this->timeperiod->active_time($this->prev_row['the_time'], $this->options['end_time']);
197 if ($active > 0 || $active === $this->prev_row['duration'])
198 $this->st_log[] = $this->prev_row;
199 else
200 $this->st_log[] = array(
201 'output' => '(event outside of timeperiod)',
202 'the_time' => $this->prev_row['the_time'],
203 'duration' => $this->prev_row['duration'],
204 'state' => -2,
205 'hard' => 1
207 // This prevents the close event from being added multiple times
208 $this->prev_row['the_time']= $this->options['end_time'];
209 return;
212 # we mangle $row here, since $this->prev_row is always
213 # derived from it, except when it's the initial
214 # state which always has (faked) output
215 if (empty($row['output']))
216 $row['output'] = '(No output)';
218 if ($this->options['scheduleddowntimeasuptime'] && $this->st_dt_depth)
219 $row['state'] = Reports_Model::STATE_OK;
221 # don't save states without duration for master objects
222 $duration = $row['the_time'] - $this->prev_row['the_time'];
223 if ($duration) {
224 $this->prev_row['duration'] = $duration;
225 $active = $this->timeperiod->active_time($this->prev_row['the_time'], $row['the_time']);
226 if ($active > 0 || ($duration === $active))
227 $this->st_log[] = $this->prev_row;
228 else
229 $this->st_log[] = array(
230 'output' => '(event outside of timeperiod)',
231 'the_time' => $this->prev_row['the_time'],
232 'duration' => $this->prev_row['duration'],
233 'state' => -2,
234 'hard' => 1
238 $this->prev_row = $row;
241 public function finalize()
243 parent::finalize();
244 // TODO: Ahrm...
245 $this->st_update_log();