1
0
mirror of https://github.com/beestat/app.git synced 2025-05-23 18:04:14 -04:00
beestat/api/logger.php
2019-05-22 21:22:24 -04:00

137 lines
4.2 KiB
PHP

<?php
/**
* Log stuff to an Influx database. Does all the hard work so you don't have
* to.
*
* @author Jon Ziebell
*/
class logger extends cora\api {
/**
* Log something to InfluxDB. This will fire off the insert query as a
* background process and allow PHP to continue without blocking.
*
* @param string $measurement The measurement.
* @param array $tags Zero to many tags. These are indexed and searchable.
* Use these for things that need where clauses outside of timestamp.
* @param array $fields At least one field. These are not indexed.
* @param string $timestamp The timestamp in microseconds.
*/
public function log_influx($measurement, $tags, $fields, $timestamp) {
// If this is not configured, do not log.
if(
$this->setting->get('influx_database_host') === null ||
$this->setting->get('influx_database_port') === null ||
$this->setting->get('influx_database_name') === null ||
$this->setting->get('influx_database_username') === null ||
$this->setting->get('influx_database_password') === null
) {
return;
}
$tag_string = $this->get_tag_string($tags);
$field_string = $this->get_field_string($fields);
$data_binary =
$measurement .
($tag_string !== '' ? ',' : '') .
$tag_string . ' ' .
$field_string . ' ' .
$timestamp;
$url =
$this->setting->get('influx_database_host') .
':' .
$this->setting->get('influx_database_port') .
'/write' .
'?db=' . $this->setting->get('influx_database_name') .
'&precision=u';
exec(
'curl ' .
'-u ' . $this->setting->get('influx_database_username') . ':' . $this->setting->get('influx_database_password') . ' ' .
'-POST "' . $url . '" ' .
'--max-time 10 ' .
'--connect-timeout 5 ' .
'--data-binary \'' . $data_binary . '\' > /dev/null &'
);
}
/**
* Convert an array into a key/value string.
*
* @param array $array The input array. Null values are removed.
*
* @return string A string like "k1=v1,k2=v2". If no non-null values are
* present this will be an empty string.
*/
private function get_field_string($fields) {
$parts = [];
foreach($fields as $key => $value) {
if($value === null) {
continue;
} else if(is_bool($value) === true) {
$value = ($value === true) ? 'true' : 'false';
} else if(is_int($value) === true) {
$value = $value . 'i';
} else if(is_float($value) === true) {
$value = $value;
} else {
$value = $this->escape_field_value($value);
}
$parts[] = $key . '=' . $value;
}
return implode(',', $parts);
}
/**
* Convert a tag array into a key/value string. Tags are always strings in
* Influx.
*
* @param array $array The input array. Null values are removed.
*
* @return string A string like "k1=v1,k2=v2". If no non-null values are
* present this will be an empty string.
*/
private function get_tag_string($tags) {
$parts = [];
foreach($tags as $key => $value) {
if($value === null) {
continue;
} else {
$parts[] = $this->escape_tag_key_value($key) . '=' . $this->escape_tag_key_value($value);
}
}
return implode(',', $parts);
}
/**
* Add slashes where necessary to prevent injection attacks. Tag values just
* sit there unquoted (you can't quote them or the quote gets included as
* part of the value) so we have to escape other special characters in that
* context.
*
* @param string $value The value to escape.
*/
private function escape_tag_key_value($value) {
return str_replace([' ', ',', '='], ['\ ', '\,', '\='], $value);
}
/**
* Add slashes where necessary to prevent injection attacks. Field values
* sit inside of "", so escape any " characters. At a higher level they sit
* inside of a ' from the cURL body. Escape these as well.
*
* @param string $value The value to escape.
*/
private function escape_field_value($value) {
return '"' . str_replace(['"', "'"], ['\"', "'\''"], $value) . '"';
}
}