FRED™  3.0
FRED™: Framework for Rapid and Easy Development
Health.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Rsi\Fred;
4 
5 /**
6  * Health checks.
7  */
8 class Health extends Component{
9 
10  public $retentionPeriod = 28; //!< Number of days to keep data.
11  public $interval = 60; //!< Minimal mail interval (minutes).
12  public $from = null; //!< Sender (defaults to default From address).
13  public $to = null; //!< Send mail to this address (or array for multiple; defaults to default From address).
14  public $subject = 'Health warning for *'; //!< Subject for the mail (an asterisk is replaced with the host name).
15  public $template = null; //!< Template for mail message.
16 
17  public $graphFont = 3;
18  public $graphColors = [[200,0,0],[0,200,0],[0,0,200],[200,200,0],[0,200,200],[200,0,200],[100,0,0],[0,100,0],[0,0,100],[100,100,0],[0,100,100],[100,0,100]];
19  public $graphIntervalFactors = [2.5,2,2];
21 
22  protected $_checks = null; //!< Available checks (key = name, value = \\Rsi\\Fred\\Health\\Check).
23 
24  /**
25  * Save the check results.
26  * @param array $data Key = check name, value = check result.
27  */
28  protected function save($data){
29  }
30 
31  protected function send($messages){
32  $table = "<table>\n";
33  foreach($messages as $name => $message)
34  $table .= '<tr><td>' . htmlspecialchars($name) . '</td><td>' . htmlspecialchars($message) . "</td></tr>\n";
35  $table .= "</table>";
36  return $this->_log->component('mail')->send(
37  $this->from,
38  $this->to ?: ini_get('sendmail_from'),
39  str_replace('*',$host = \Rsi\Http::host(),$this->subject),
40  strtr($this->template,[
41  '[time]' => date('Y-m-d H:i:s'),
42  '[host]' => $host,
43  '[ip]' => $_SERVER['SERVER_ADDR'] ?? gethostbyname($host),
44  '[messages]' => $table
45  ]) ?: $table,
46  true
47  );
48  }
49  /**
50  * Perform all checks.
51  */
52  public function check(){
53  $messages = $data = [];
54  foreach($this->checks as $name => $check){
55  $data[$name] = $check->check($message);
56  if($message) $messages[$name] = $message;
57  }
58  $this->save($data);
59  if($messages) $this->send($messages);
60  }
61  /**
62  * Get available data.
63  * @param int $since Return data since this timestamp (empty = all).
64  * @return array Key = timestamp, value = record with key = check name, value = check result.
65  */
66  public function data($since = null){
67  return [];
68  }
69  /**
70  * Create a graph with all data points.
71  * @param int $width Width of image (pixels).
72  * @param int $height Height of image (pixels).
73  * @param int $since Use data since this timestamp (empty = all).
74  * @return resource Image resource.
75  */
76  public function graph($width = 640,$height = 480,$since = null){
77  $image = imagecreate($width,$height);
78  imagecolorallocate($image,255,255,255);
79  if(count($data = $this->data($since)) > 1){
80  $color_border = imagecolorallocate($image,0,0,0);
81  $color_grid = imagecolorallocate($image,200,200,200);
82 //TODO: bereik van waarden analyseren en dan (evt.) over 2 assen verdelen ("grote waarden" / "kleine waarden") (???)
83  $value_min = $value_max = 0;
84  $font_width = imagefontwidth($this->graphFont);
85  $font_height = imagefontheight($this->graphFont);
86  $names = [];
87  foreach($data as $record) foreach($record as $name => $value) $names[$name] = max($names[$name] ?? 0,$value);
88  $value_max = max($names);
89  $graph_height = $height - 2 * $font_height;
90  $interval_min = 2 * $font_height * ($value_max - $value_min) / $graph_height;
91  $index = 0;
92  $value_interval = 0.001;
93  while($value_interval < $interval_min) $value_interval *= $this->graphIntervalFactors[$index++ % count($this->graphIntervalFactors)];
94  $value_max = ceil($value_max / $value_interval) * $value_interval;
95  foreach($names as $name => $name_max) $names[$name] = $name_max <= $value_max / $this->graphSecondaryFactor;
96  $value_chars = max(5,strlen($value_max) + ($decimals = ($i = strpos($value_interval,'.')) ? strlen($value_interval) - $i : 0));
97  $graph_width = $width - $font_width * $value_chars;
98  if(($graph_width > 50) && ($graph_height > 50)){
99  $value = $value_min;
100  while(($value += $value_interval) < $value_max){
101  $y = round(($value_max - $value) / ($value_max - $value_min) * $graph_height);
102  imageline($image,$width - $graph_width,$y,$width,$y,$color_grid);
103  $value_str = number_format($value,max(0,$decimals - 1));
104  imagestring($image,$this->graphFont,$width - $graph_width - strlen($value_str) * $font_width,$y - $font_height / 2,$value_str,$color_border);
105  }
106  $times = array_keys($data);
107  $time_min = floor(min($times) / 86400) * 86400;
108  $time_max = ceil(max($times) / 86400) * 86400;
109  $time_interval = ceil(11 * $font_width * ($time_max - $time_min) / $graph_width / 86400) * 86400;
110  $time = $time_min;
111  do{
112  $x = $width - round(($time_max - $time) / ($time_max - $time_min) * $graph_width);
113  imageline($image,$x,0,$x,$graph_height,$color_grid);
114  if(!(($time - $time_min) % $time_interval)) imagestring($image,$this->graphFont,$x - 5 * $font_width,$graph_height,date('Y-m-d',$time),$color_border);
115  }
116  while(($time += 86400) < $time_max);
117  $legend_size = $font_height;
118  $legend_x = round((
119  $width -
120  (strlen(implode(array_keys($names))) + count(array_filter($names)) * (strlen($this->graphSecondaryFactor) + 1)) * $font_width -
121  count($names) * $legend_size * 2 - $legend_size
122  ) / 2);
123  $index = 0;
124  foreach($names as $name => $secondary){
125  $color = imagecolorallocate($image,...$this->graphColors[$index++ % count($this->graphColors)]);
126  $y = $height - $legend_size;
127  imagefilledrectangle($image,$legend_x ,$y + 2,$legend_x + $legend_size - 4,$height - 2,$color);
128  imagerectangle($image,$legend_x,$y + 2,$legend_x + $legend_size - 4,$height - 2,$color_border);
129  imagestring($image,$this->graphFont,$legend_x += $legend_size,$y,$name,$color_border);
130  $legend_x += strlen($name) * $font_width;
131  if($secondary){
132  imagestring($image,$this->graphFont,$legend_x,$y,$str = 'x' . $this->graphSecondaryFactor,$color_grid);
133  $legend_x += strlen($str) * $font_width;
134  }
135  $legend_x += $legend_size;
136  $prev_x = $prev_y = null;
137  foreach($data as $time => $record) if(array_key_exists($name,$record)){
138  $x = $width - round(($time_max - $time) / ($time_max - $time_min) * $graph_width);
139  $y = round(($value_max - $record[$name] * ($secondary ? $this->graphSecondaryFactor : 1)) / ($value_max - $value_min) * $graph_height);
140  if($prev_x !== null) imageline($image,$prev_x,$prev_y,$x,$y,$color);
141  $prev_x = $x;
142  $prev_y = $y;
143  }
144  else $prev_x = $prev_y = null;
145  }
146  imageline($image,$width - $graph_width,0,$width - $graph_width,$graph_height,$color_border);
147  imageline($image,$width - $graph_width,$graph_height,$width,$graph_height,$color_border);
148  }
149  }
150  return $image;
151  }
152 
153  protected function getChecks(){
154  if($this->_checks === null){
155  $this->_checks = [];
156  foreach($this->config('checks',[]) as $name => $config){
157  $class_name = \Rsi\Record::get($config,'className',__CLASS__ . '\\Check\\' . ucfirst($name));
158  $this->_checks[$name] = new $class_name($this->_fred,$config);
159  }
160  }
161  return $this->_checks;
162  }
163 
164 }
Rsi\Fred\Health\getChecks
getChecks()
Definition: Health.php:153
Rsi\Fred\Health\$to
$to
Send mail to this address (or array for multiple; defaults to default From address).
Definition: Health.php:13
Rsi
Rsi\Fred\Health
Health checks.
Definition: Health.php:8
Rsi\Fred\Health\graph
graph($width=640, $height=480, $since=null)
Create a graph with all data points.
Definition: Health.php:76
Rsi\Fred\Health\$template
$template
Template for mail message.
Definition: Health.php:15
Rsi\Fred\Health\$subject
$subject
Subject for the mail (an asterisk is replaced with the host name).
Definition: Health.php:14
Rsi\Fred\Health\$graphIntervalFactors
$graphIntervalFactors
Definition: Health.php:19
Rsi\Fred\Health\send
send($messages)
Definition: Health.php:31
Rsi\Fred\Health\$graphColors
$graphColors
Definition: Health.php:18
Rsi\Fred\Component
Basic component class.
Definition: Component.php:8
Rsi\Fred\Health\$_checks
$_checks
Available checks (key = name, value = \Rsi\Fred\Health\Check).
Definition: Health.php:22
Rsi\Fred\Health\check
check()
Perform all checks.
Definition: Health.php:52
Rsi\Fred\Component\config
config($key, $default=null)
Retrieve a config value.
Definition: Component.php:53
Rsi\Fred\Health\$graphFont
$graphFont
Definition: Health.php:17
Rsi\Fred\Health\$interval
$interval
Minimal mail interval (minutes).
Definition: Health.php:11
Rsi\Fred\Health\save
save($data)
Save the check results.
Definition: Health.php:28
Rsi\Fred\Health\$retentionPeriod
$retentionPeriod
Number of days to keep data.
Definition: Health.php:10
Rsi\Fred\Health\$graphSecondaryFactor
$graphSecondaryFactor
Definition: Health.php:20
Rsi\Fred\Health\$from
$from
Sender (defaults to default From address).
Definition: Health.php:12
Rsi\Fred\Health\data
data($since=null)
Get available data.
Definition: Health.php:66
Rsi\Fred
Definition: Alive.php:3