Skip to content

NFR: Add trace() logging method and TRACE constant to Logger #17047

@Fenikkusu

Description

@Fenikkusu

Feature Request

Add a first-class trace() convenience method (and corresponding TRACE constant / level name) to Phalcon\Logger\Logger, Phalcon\Logger\LoggerInterface, and Phalcon\Logger\AbstractLogger.

Current Behaviour

AbstractLogger exposes a CUSTOM = 8 constant and maps it to the level name "custom" in getLevels(). No named trace() method exists on Logger or LoggerInterface. Consumers who need trace-level logging must either:

  • Subclass Logger, add a TRACE constant, override getLevels() to rename 8 → "trace", and add the trace() method themselves; or
  • Call $logger->log(8, $message) with a magic integer and receive log entries labelled "custom" rather than "trace".

Both workarounds are friction the framework should absorb.

Expected Behaviour

// Constant available on AbstractLogger
AbstractLogger::TRACE; // = 8

// Level name returned as "trace", not "custom"
$logger->trace('Detailed wire-level response', ['body' => $body]);
// → level name in output: "trace"

Proposed Changes

phalcon/Logger/AbstractLogger.zep

  1. Rename (or alias) CUSTOMTRACE:
    const TRACE  = 8;  // rename; keep CUSTOM as a deprecated alias if needed for BC
  2. Update getLevels() to map 8 → "trace":
    self::TRACE : "trace"
  3. Update setLogLevel() fallback (self::CUSTOMself::TRACE) and logLevel default comment.

phalcon/Logger/Logger.zep

Add the convenience method:

/**
 * Extra-verbose diagnostic output.
 *
 * Use for high-frequency, fine-grained events such as raw socket frames,
 * HTTP response bodies, or internal state transitions that are too noisy
 * for DEBUG.
 *
 * @param string $message
 * @param array  $context
 *
 * @return void
 * @throws Exception
 * @throws LoggerException
 */
public function trace(string message, array context = []) -> void
{
    this->addMessage(self::TRACE, message, context);
}

phalcon/Logger/LoggerInterface.zep

Add the corresponding interface method:

/**
 * Extra-verbose diagnostic output.
 *
 * @param string $message
 * @param array  $context
 *
 * @return void
 */
public function trace(string message, array context = []) -> void;

Motivation

  • Trace is a well-established level. Log4j, SLF4J, Monolog, and most mature logging frameworks reserve a level below DEBUG for extra-verbose output (raw frames, full HTTP bodies, tight-loop state). CUSTOM with no semantic name is not a substitute.
  • "custom" is not a usable level name in production. Structured log aggregators (e.g. Loki, ELK) filter by level string. "custom" cannot be mapped to any known severity in those systems; "trace" can.
  • Subclassing just to rename a level is unnecessary friction. The workaround requires overriding both getLevels() (to rename the label) and adding the trace() method, despite the underlying integer slot already existing in the framework.

Real-World Reference

The following is the exact override currently required in downstream projects (TwistersFury\Phalcon\Shared\Logger\Logger) to work around the missing native support:

class Logger extends PhalconLogger
{
    const TRACE = 8; // CUSTOM

    private levels = [
        2 : "alert",
        1 : "critical",
        7 : "debug",
        0 : "emergency",
        3 : "error",
        6 : "info",
        5 : "notice",
        4 : "warning",
        8 : "trace"    // rename CUSTOM → trace
    ];

    public function trace(string message, array context = []) -> void
    {
        this->addMessage(self::CUSTOM, message, context);
    }

    protected function getLevels() -> array
    {
        return this->levels;
    }
}

This override would become unnecessary if the three changes above were made to the framework.

Backwards Compatibility

Keeping CUSTOM = 8 as a deprecated alias alongside TRACE = 8 (both pointing to the same integer) avoids breaking any existing code that references AbstractLogger::CUSTOM. The only observable change in output is the level label in log entries changing from "custom" to "trace" — applications that currently rely on the literal string "custom" in log output would need to update their log-parsing rules, but that is expected for a meaningful rename.

Metadata

Metadata

Assignees

Labels

5.0The issues we want to solve in the 5.0 releasenew feature requestPlanned Feature or New Feature Request
No fields configured for Feature.

Projects

Status
Implemented

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions