SeekquarrySeekquarry - Yioop Repo - Seekquarry

/ src / library / AnalyticsManager.php⤓
<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\library;

use seekquarry\yioop\library\CrawlConstants;

/**
 * AnalyticsManager holds the timings and counts a process gathers as it
 * runs, so that the code that reports them, such as the query statistics
 * of a search or the indexer's log, can read what code far below it
 * measured. Models and index bundle iterators store timings here by
 * name. Steps that read or write index files are counted and timed by
 * kind with addTiming, and timingsReport turns those counts into lines
 * for a person to read.
 *
 * @author Chris Pollett
 */
class AnalyticsManager
{
    /**
     * TIMINGS is the name under which addTiming keeps, for each kind of
     * step, how many steps were taken and how many seconds they took
     */
    const TIMINGS = "TIMINGS";
    /**
     * $data holds each stored value under the name it was stored with
     * @var array
     */
    private static $data = [];
    /**
     * get gives the value stored under a name, such as the time a search
     * spent on another machine
     *
     * @param string $attribute name the value was stored under
     * @return mixed the value, or null if nothing is stored under the name
     */
    public static function get($attribute)
    {
        return isset(self::$data[$attribute]) ? self::$data[$attribute] : null;
    }
    /**
     * set stores a value under a name, replacing what was there
     *
     * @param string $attribute name to store the value under
     * @param mixed $value the timing or count to store
     */
    public static function set($attribute, $value)
    {
        self::$data[$attribute] = $value;
    }
    /**
     * addTiming adds to the count and the time of one kind of step, such
     * as reading a dictionary file from disk or compressing a page before
     * it is stored. The caller takes the time with microtime(true) before
     * the step and passes it in after, and the time since then is added.
     * The current time is given back, so a caller timing several steps in
     * a row can start the next one from it. The code that reports the
     * timings empties them with set(self::TIMINGS, []) when a search or
     * an indexed file starts, as one process handles many of them.
     *
     * @param string $kind words saying what the step does, used as the
     *      report's label
     * @param float $start_time when the step started, from microtime(true)
     * @param int $count how many steps to add
     * @return float the current time, from microtime(true)
     */
    public static function addTiming($kind, $start_time, $count = 1)
    {
        $now = microtime(true);
        $steps = self::$data[self::TIMINGS][$kind] ?? [0, 0];
        self::$data[self::TIMINGS][$kind] = [$steps[0] + $count,
            $steps[1] + $now - $start_time];
        return $now;
    }
    /**
     * timingsReport gives one line for each kind of step addTiming has
     * counted since the timings were last emptied: the kind, how many
     * steps were taken and the seconds they took. The kinds are listed in
     * the order they were first counted.
     *
     * @return array lines such as "postings reads: 594 in 0.043 s"
     */
    public static function timingsReport()
    {
        $lines = [];
        foreach (self::$data[self::TIMINGS] ?? [] as $kind => $steps) {
            $lines[] = "$kind: {$steps[0]} in " .
                number_format($steps[1], 3) . " s";
        }
        return $lines;
    }
}