diff --git a/backend.php b/backend.php index 5b1587741..9fa30db38 100644 --- a/backend.php +++ b/backend.php @@ -145,8 +145,8 @@ $b_scope->close(); if ($before) { + $m_scope = Tracer::start("method/$method"); if ($method && method_exists($handler, $method)) { - $m_scope = Tracer::start("method/$method"); $reflection = new ReflectionMethod($handler, $method); if ($reflection->getNumberOfRequiredParameters() == 0) { @@ -154,17 +154,21 @@ } else { user_error("Refusing to invoke method $method of handler $op which has required parameters.", E_USER_WARNING); header("Content-Type: text/json"); + + $m_scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED); print Errors::to_json(Errors::E_UNAUTHORIZED); } - $m_scope->close(); } else { if (method_exists($handler, "catchall")) { $handler->catchall($method); } else { header("Content-Type: text/json"); + + $m_scope->getSpan()->setTag('error', Errors::E_UNKNOWN_METHOD); print Errors::to_json(Errors::E_UNKNOWN_METHOD, ["info" => get_class($handler) . "->$method"]); } } + $m_scope->close(); $a_scope = Tracer::start("after/$method"); $handler->after(); @@ -176,6 +180,7 @@ header("Content-Type: text/json"); print Errors::to_json(Errors::E_UNAUTHORIZED); + $scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED); $scope->close(); return; } @@ -184,6 +189,7 @@ header("Content-Type: text/json"); print Errors::to_json(Errors::E_UNAUTHORIZED); + $scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED); $scope->close(); return; } @@ -193,4 +199,5 @@ header("Content-Type: text/json"); print Errors::to_json(Errors::E_UNKNOWN_METHOD, [ "info" => (isset($handler) ? get_class($handler) : "UNKNOWN:".$op) . "->$method"]); + $scope->getSpan()->setTag('error', Errors::E_UNKNOWN_METHOD); $scope->close(); diff --git a/classes/config.php b/classes/config.php index dee6caa38..a9c75ae7b 100644 --- a/classes/config.php +++ b/classes/config.php @@ -192,6 +192,9 @@ class Config { /** delay updates for this feed if received HTTP 429 (Too Many Requests) for this amount of seconds (base value, actual delay is base...base*2) */ const HTTP_429_THROTTLE_INTERVAL = "HTTP_429_THROTTLE_INTERVAL"; + /** host running Jaeger collector to receive traces (disabled if empty) */ + const JAEGER_REPORTING_HOST = "JAEGER_REPORTING_HOST"; + /** default values for all global configuration options */ private const _DEFAULTS = [ Config::DB_TYPE => [ "pgsql", Config::T_STRING ], @@ -249,6 +252,7 @@ class Config { Config::HTTP_USER_AGENT => [ 'Tiny Tiny RSS/%s (https://tt-rss.org/)', Config::T_STRING ], Config::HTTP_429_THROTTLE_INTERVAL => [ 3600, Config::T_INT ], + Config::JAEGER_REPORTING_HOST => [ "", Config::T_STRING ], ]; /** @var Config|null */ diff --git a/classes/feeds.php b/classes/feeds.php index 1ce19b098..9707d5e45 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -987,7 +987,7 @@ class Feeds extends Handler_Protected { * @throws PDOException */ static function _get_counters($feed, bool $is_cat = false, bool $unread_only = false, ?int $owner_uid = null): int { - $scope = Tracer::start(__FUNCTION__, ['tags' => ['args' => json_encode(func_get_args())]]); + $scope = Tracer::start(__FUNCTION__, [], func_get_args()); $n_feed = (int) $feed; $need_entries = false; diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index 00d26d4f6..42adf23ca 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -1104,7 +1104,7 @@ class Pref_Feeds extends Handler_Protected { * @return array */ private function feedlist_init_feed(int $feed_id, ?string $title = null, bool $unread = false, string $error = '', string $updated = ''): array { - $scope = Tracer::start(__FUNCTION__, ['tags' => ['args' => json_encode(func_get_args())]]); + $scope = Tracer::start(__FUNCTION__, [], func_get_args()); if (!$title) $title = Feeds::_get_title($feed_id, false); diff --git a/classes/tracer.php b/classes/tracer.php index fde99927d..1326f4344 100644 --- a/classes/tracer.php +++ b/classes/tracer.php @@ -3,39 +3,59 @@ use OpenTracing\GlobalTracer; use OpenTracing\Scope; class Tracer { + /** @var Tracer $instance */ private static $instance; public function __construct() { - $config = new \Jaeger\Config( - [ - 'sampler' => [ - 'type' => \Jaeger\SAMPLER_TYPE_CONST, - 'param' => true, - ], - 'logging' => true, - "local_agent" => [ - "reporting_host" => "172.17.172.39", - "reporting_port" => 6832 - ], - 'dispatch_mode' => \Jaeger\Config::JAEGER_OVER_BINARY_UDP, - ], - 'tt-rss' - ); + $jaeger_host = Config::get(Config::JAEGER_REPORTING_HOST); - $config->initializeTracer(); + if ($jaeger_host) { + $config = new \Jaeger\Config( + [ + 'sampler' => [ + 'type' => \Jaeger\SAMPLER_TYPE_CONST, + 'param' => true, + ], + 'logging' => true, + "local_agent" => [ + "reporting_host" => $jaeger_host, + "reporting_port" => 6832 + ], + 'dispatch_mode' => \Jaeger\Config::JAEGER_OVER_BINARY_UDP, + ], + 'tt-rss' + ); - register_shutdown_function(function() { - $tracer = GlobalTracer::get(); - $tracer->flush(); - }); + $config->initializeTracer(); + + register_shutdown_function(function() { + $tracer = GlobalTracer::get(); + $tracer->flush(); + }); + } } - private function _start(string $name, array $options = []) { + /** + * @param string $name + * @param array $options + * @param array $args + * @return Scope + */ + private function _start(string $name, array $options = [], array $args = []): Scope { $tracer = GlobalTracer::get(); + + $options['tags']['args'] = json_encode($args); + return $tracer->startActiveSpan($name, $options); } - public static function start(string $name, array $options = []) : Scope { + /** + * @param string $name + * @param array $options + * @param array $args + * @return Scope + */ + public static function start(string $name, array $options = [], array $args = []) : Scope { return self::get_instance()->_start($name, $options); }