'e', LoggingVerbosity::Warning => 'w', LoggingVerbosity::Info => 'i', LoggingVerbosity::Debug => 'd' }; } const COLOR_RESET = "\033[0m"; static function getVerbosityColorMarker(int $verbosity) { // See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors for reference. return match($verbosity) { LoggingVerbosity::Error => "\033[31m", LoggingVerbosity::Warning => "\033[93m", LoggingVerbosity::Debug => "\033[90m", default => '' }; } } /** * Calculate process runtime as [s, ns]. * @return int[] Seconds and nanoseconds. */ function hrtime_interval() { global $hrtime_start, $NANOSEC; list($s, $ns) = hrtime(); list($s0, $ns0) = $hrtime_start; // Borrow if ($ns < $ns0) { $s--; $ns += $NANOSEC; } return [$s - $s0, $ns - $ns0]; } /** * Format process runtime to milisecond precision. */ function runtime_str() { list($s, $ns) = hrtime_interval(); return ( date('i:s.', $s) . str_pad(intdiv($ns, 1E6), 3, "0", STR_PAD_LEFT) ); } function _log_message(string $msg, int $message_verbosity) { global $LOGGING_VERBOSITY; if ($message_verbosity > $LOGGING_VERBOSITY) return; $runtime = runtime_str(); $marker = LoggingVerbosity::getVerbosityMarker($message_verbosity); $color_marker = LoggingVerbosity::getVerbosityColorMarker($message_verbosity); $color_reset = LoggingVerbosity::COLOR_RESET; // Need to concatenate marker to avoid interpolated array member syntax. fwrite(STDERR, $color_marker . "[$runtime] [$marker] $msg$color_reset" . PHP_EOL); } function log_error(string $msg) { _log_message($msg, LoggingVerbosity::Error); } function log_warning(string $msg) { _log_message($msg, LoggingVerbosity::Warning); } function log_info(string $msg) { _log_message($msg, LoggingVerbosity::Info); } function log_debug(string $msg) { _log_message($msg, LoggingVerbosity::Debug); } function log_value(mixed $value) { log_debug(var_export($value, true)); } $LOGGING_VERBOSITY = LoggingVerbosity::Info; ?>