loki.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. /**
  3. * dolphin. Collection of useful PHP skeletons.
  4. * Copyright (C) 2024 Johannes 'Banana' Keßler
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
  8. *
  9. * You should have received a copy of the
  10. * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
  11. * along with this program. If not, see http://www.sun.com/cddl/cddl.html
  12. */
  13. /**
  14. * Send log messages with optional structured data to Loki using the http api
  15. * https://grafana.com/docs/loki/latest/reference/loki-http-api/
  16. */
  17. class Loki {
  18. /**
  19. * @var string The host Loki runs on
  20. */
  21. private string $_host;
  22. /**
  23. * @var int The port number from the Loki installation
  24. */
  25. private int $_port;
  26. /**
  27. * @var array The stream lables. See Loki http api
  28. */
  29. private array $_stream = array();
  30. /**
  31. * @var array The log messages as an array to be send with send()
  32. */
  33. private array $_values = array();
  34. /**
  35. * @var string basic auth for endpoint
  36. */
  37. private string $_auth;
  38. /**
  39. * @param string $host Loki host
  40. * @param int $port Loko host port
  41. * @param array $stream Stream array with labels to send with
  42. */
  43. public function __construct(string $host, int $port, array $stream) {
  44. $this->_stream = $stream;
  45. $this->_host = $host;
  46. $this->_port = $port;
  47. if(defined("LOKI_USER") && !empty(LOKI_USER)) {
  48. $this->_auth = base64_encode(LOKI_USER.":".LOKI_USER_PW);
  49. }
  50. }
  51. /**
  52. * Add a log message with optional structured data to the values to be send()
  53. *
  54. * @param string $msg The log message
  55. * @param array $structuredData Additional structured data to be processed from Loki if configured
  56. * @return void
  57. */
  58. public function log(string $msg, array $structuredData=array()): void {
  59. $_nanosec = strval(shell_exec("date +%s%9N")-1);
  60. if(!empty($structuredData)) {
  61. $this->_values[] = array($_nanosec, $msg, $structuredData);
  62. } else {
  63. $this->_values[] = array($_nanosec, $msg);
  64. }
  65. }
  66. /**
  67. * Send the collected messages from log() to the loki installation
  68. * The messages to be send will be resetted after
  69. *
  70. * @return string Non empty on error
  71. */
  72. public function send(): string {
  73. $ret = "";
  74. if(!LOKI_ENABLE) return $ret;
  75. $data = array(
  76. "streams" => array(
  77. array(
  78. "stream" => $this->_stream,
  79. "values" => $this->_values
  80. )
  81. )
  82. );
  83. $data = json_encode($data);
  84. $out = "POST ".LOKI_PUSH_API." HTTP/1.1\r\n";
  85. $out .= "Host: $this->_host\r\n";
  86. if(!empty($this->_auth)) {
  87. $out .= "Authorization: Basic $this->_auth\r\n";
  88. }
  89. $out .= "Content-Type: application/json\r\n";
  90. $out .= "Content-Length: ".strlen($data)."\r\n";
  91. $out .= "Connection: Close\r\n\r\n";
  92. $fp = fsockopen($this->_host, $this->_port, $errno, $errstr, 5);
  93. if($fp) {
  94. fwrite($fp, $out);
  95. fwrite($fp, $data."\r\n");
  96. fclose($fp);
  97. } else {
  98. $ret = $errno.' '.$errstr;
  99. }
  100. # reset
  101. $this->_values = array();
  102. return $ret;
  103. }
  104. }