clearMarks(); $this->setLogger( isset( $params['logger'] ) ? $params['logger'] : new NullLogger() ); } /** * Sets a logger instance on the object. * * @param LoggerInterface $logger * @return null */ public function setLogger( LoggerInterface $logger ) { $this->logger = $logger; } /** * Store a timestamp with the associated name (a "mark") * * @param string $markName The name associated with the timestamp. * If there already exists an entry by that name, it is overwritten. * @return array The mark that has been created. */ public function mark( $markName ) { $this->entries[$markName] = [ 'name' => $markName, 'entryType' => 'mark', 'startTime' => microtime( true ), 'duration' => 0, ]; return $this->entries[$markName]; } /** * @param string $markName The name of the mark that should * be cleared. If not specified, all marks will be cleared. */ public function clearMarks( $markName = null ) { if ( $markName !== null ) { unset( $this->entries[$markName] ); } else { $this->entries = [ 'requestStart' => [ 'name' => 'requestStart', 'entryType' => 'mark', 'startTime' => $_SERVER['REQUEST_TIME_FLOAT'], 'duration' => 0, ], ]; } } /** * This method stores the duration between two marks along with * the associated name (a "measure"). * * If neither the startMark nor the endMark argument is specified, * measure() will store the duration from $_SERVER['REQUEST_TIME_FLOAT'] to * the current time. * If the startMark argument is specified, but the endMark argument is not * specified, measure() will store the duration from the most recent * occurrence of the start mark to the current time. * If both the startMark and endMark arguments are specified, measure() * will store the duration from the most recent occurrence of the start * mark to the most recent occurrence of the end mark. * * @param string $measureName * @param string $startMark * @param string $endMark * @return array|bool The measure that has been created, or false if either * the start mark or the end mark do not exist. */ public function measure( $measureName, $startMark = 'requestStart', $endMark = null ) { $start = $this->getEntryByName( $startMark ); if ( $start === null ) { $this->logger->error( __METHOD__ . ": The mark '$startMark' does not exist" ); return false; } $startTime = $start['startTime']; if ( $endMark ) { $end = $this->getEntryByName( $endMark ); if ( $end === null ) { $this->logger->error( __METHOD__ . ": The mark '$endMark' does not exist" ); return false; } $endTime = $end['startTime']; } else { $endTime = microtime( true ); } $this->entries[$measureName] = [ 'name' => $measureName, 'entryType' => 'measure', 'startTime' => $startTime, 'duration' => $endTime - $startTime, ]; return $this->entries[$measureName]; } /** * Sort entries in chronological order with respect to startTime. */ private function sortEntries() { uasort( $this->entries, function ( $a, $b ) { return 10000 * ( $a['startTime'] - $b['startTime'] ); } ); } /** * @return array[] All entries in chronological order. */ public function getEntries() { $this->sortEntries(); return $this->entries; } /** * @param string $entryType * @return array[] Entries (in chronological order) that have the same value * for the entryType attribute as the $entryType parameter. */ public function getEntriesByType( $entryType ) { $this->sortEntries(); $entries = []; foreach ( $this->entries as $entry ) { if ( $entry['entryType'] === $entryType ) { $entries[] = $entry; } } return $entries; } /** * @param string $name * @return array|null Entry named $name or null if it does not exist. */ public function getEntryByName( $name ) { return isset( $this->entries[$name] ) ? $this->entries[$name] : null; } }