Skip to content

6.1 Time Module

Juan Morales edited this page Feb 19, 2021 · 2 revisions

Module: Time

Features

  • Able to calculate the total amount of time since Tracker->init() until Tracker->end()
  • Measures the time taken between every single log() call

Code analysis

Please check the comments

<?php declare(strict_types=1);

namespace Footprint\Modules;

//Necessary to implement the IModule interface in order to satisfy a module requirement
use Footprint\Interfaces\IModule;

//We reference the Tracker in order to use it as Tracker only
use Footprint\Tracker;

//The class must implement IModule
class Time implements IModule
{
    /*
     * A module needs to be identify by an ID.
     * By convention is better to declare a constant called MODULE_ID with the value that will make a module unique.
     */
    const MODULE_ID = "TIME";

    /*
     * The keys that will be use by the module when adding data to the log() record are also specified with constants here.
     * This is just a convention to have a better code, I strongly suggest you to follow this practice too.
     * This module will generate two values that will be log, one called "TIME_total" and "TIME_step", holding the total time spent since 
     * Tracker->init() until Tracker->end(), and the time spent between each Tracker->log() call respectively.
     */
    const KEY_TOTAL_TIME = self::MODULE_ID."_total"; //TIME_total
    const KEY_STEP_TIME = self::MODULE_ID."_step";   //TIME_step

    protected $totalTime = 0;
    protected $microtime = null;
    protected $previousStep = null;
    protected $currentStep = null;

    /**
     * Now we implement IModule
     */
    
    /*
     * This functions will return a value that will identify this module.
     * In this case we return the constant MODULE_ID.
     * The Tracker will use this value internally.
     */
    public function getId() {
        return self::MODULE_ID;
    }

    /*
     * When the Tracker->init() is called, right here we specify what are we going to do.
     */
    public function onInit(Tracker &$tracker) {
        //we store the current time in $microtime
        $this->microtime = microtime(true);
        //and also the previousStep variable is set to "now", as no log() call has been done at this point.
        $this->previousStep = $this->microtime;
    }

    /*
     * When Tracker->end() we do not do anything.
     * Even though this function is not doing anything we need to write it, because of IModule.
     */
    public function onEnd(Tracker &$tracker) {
        return;
    }

    /*
     * If we want to do something when the module is loaded into the Tracker
     * this is the place to specify that.
     * This module will not do anything the its loaded, but we have to implement IModule. 
     */
    public function onLoad(Tracker &$tracker) {
        return;
    }

    /*
     * If we want to do something when the module is unloaded into the Tracker
     * this is the place to specify that.
     * This module will not do anything the its unloaded, but we have to implement IModule. 
     */
    public function onUnload(Tracker &$tracker) {
        return;
    }

    /*
     * If we want to do something when Tracker->log() (log saving step)
     * this is the place to specify that.
     *
     * This module will not do anything, but we have to implement IModule. 
     */
    public function onLog(Tracker &$tracker) {
        return;
    }

    /*
     * As we know, we want to have the "time" values every time Tracker->log() happens,
     * but we don't want to do  anything when the log is already created (previous onLog()), but
     * we want this module to participate in the creation of the log data, inserting the values this module
     * is able to calculate; this logging phase is the "log build" phase, happens internally when Tracker->log()
     * is called. Remember that Tracker->log() is composed of two steps/phases
     *
     * 1) log building
     * 2) log recording
     *
     * Pay attention to the Tracker &$tracker parameter the method receives.
     * This gives the module the possibility to use the Tracker that is using this module.
     */
    public function onLogBuild(Tracker &$tracker) {
        //calculate now
        $now = microtime(true);
        
        //calculate the total so far
        $this->totalTime += round(($now - $this->microtime), 2);
        $this->microtime = $now;
        
        //calculate the time passed from the last log() until this one
        $this->currentStep = round(($now - $this->previousStep), 2);

        //the "the actual log()" will be the "previous log()" for the next log()
        $this->previousStep = $now;
        
        /*
         * Now we save the calculated values as part of the current log record.
         * Remember that the log is being generated (build) at this moment, and this module
         * is just contributing with some data to the log creation.
         */
        $tracker->addLogData(self::KEY_TOTAL_TIME, (string)$this->totalTime);
        $tracker->addLogData(self::KEY_STEP_TIME, (string)$this->currentStep);
    }

    /*
     * Because of IModule.
     * Basically this methods returns an array of the keys used by this module during log building.
     * You can see from method onLogBuild that we are calling $tracker->addLogData() two times,
     * each one using certain keys, well those are the keys this method needs to return.
     */
    public function getKeys() : array {
        return [
            self::KEY_TOTAL_TIME,
            self::KEY_STEP_TIME,
        ];
    }
}

And that's it, pretty simple don't you think?