Odyssey
health.prg
1 <?php
2 // vim: tabstop=2 expandtab syn=php
3 /*
4  * Perform basic sanity tests here to ensure this instance is healthy.
5  * Returning a non 200 result (throwing an exception) will cause the
6  * cluster to deprecate this node.
7  */
8 
9 
10 require_once 'hcuEnv.i';
11 
12 
13 function check_database($env) {
14  $db = $env['db'];
15  $connect_to = sprintf('host=%s port=%d dbname=%s', $db['host'],
16  $db['port'], $db['dbname']);
17  if (!is_null($db['user'])) {
18  $connect_to .= ' user=' . $db['user'];
19  }
20  if (!is_null($db['connect_timeout'])) {
21  $connect_to .= ' connect_timeout=' . $db['connect_timeout'];
22  }
23  if (!is_null($db['password'])) {
24  $connect_to .= ' password=' . $db['password'];
25  }
26  $r = @pg_connect($connect_to);
27  if (!$r) {
28  throw new Exception('DB connect error');
29  }
30  if (pg_connection_status($r) !== PGSQL_CONNECTION_OK) {
31  throw new Exception('DB status error');
32  }
33  if (!pg_ping($r)) {
34  throw new Exception('DB ping error');
35  }
36 }
37 
38 
39 function check_disk_usage($env) {
40  $cwd_free = disk_free_space(".");
41  $root_free = disk_free_space("/");
42  if ($cwd_free < 1024 * 1024 * 500 or
43  $root_free < 1024 * 1024 * 500) {
44  throw new Exception('Disk(s) too full');
45  }
46  return [
47  "cwd_free" => $cwd_free,
48  "root_free" => $root_free
49  ];
50 }
51 
52 function check_mem_usage($env) {
53  $mem = memory_get_usage(TRUE);
54  if ($mem > (1024 * 1024 * 100)) {
55  throw new Exception('Memory usage too high');
56  }
57  return [
58  "usage" => $mem
59  ];
60 }
61 
62 function wrap_check($checkfunc, $env) {
63  $res = [];
64  try {
65  return [TRUE, $checkfunc($env)];
66  } catch (Exception $e) {
67  return [FALSE, $e];
68  }
69 }
70 
71 function run_checks() {
72  $env = LoadSystemEnv('health');
73 
74  $logger = $env['logger'];
75  $checks = [
76  "check_disk_usage",
77  "check_mem_usage",
78  "check_database"
79  ];
80  $results = [];
81  $start_ts = microtime(TRUE);
82  $overall_success = TRUE;
83  foreach ($checks as $fn) {
84  $check_ts = microtime(TRUE);
85  list($success, $info_or_exc) = wrap_check($fn, $env);
86  $time = microtime(TRUE) - $start_ts;
87  $results[$fn] = ["time" => $time];
88  if ($success) {
89  $results[$fn]["success"] = TRUE;
90  $results[$fn]["info"] = $info_or_exc;
91  } else {
92  if (!$env['devmode']) {
93  http_response_code(500);
94  } else {
95  $logger->warning("DEVMODE preventing negative health response");
96  }
97  $msg = $info_or_exc->getMessage();
98  $logger->error("%s: FAIL (%s)", $fn, $msg);
99  $results[$fn]["success"] = FALSE;
100  $results[$fn]["exception"] = $msg;
101  $overall_success = FALSE;
102  if (!$env['devmode']) {
103  break; // No point in continuing
104  }
105  }
106  }
107  $total_time = microtime(TRUE) - $start_ts;
108  $resp = [
109  "time" => $total_time,
110  "success" => $overall_success,
111  ];
112 
113  // ** Always print results
114  $resp["checks"] = $results;
115  header('Content-Type: text/json');
116  echo json_encode($resp);
117 }
118 
119 run_checks();
120 
121 ?>