VOOZH about

URL: https://deepwiki.com/hypervel/log/5.2-contextual-logging

⇱ Contextual Logging | hypervel/log | DeepWiki


Loading...
Menu

Contextual Logging

The logging system provides contextual logging through two mechanisms: per-logger context and shared context across all channels. Context data is stored in Hyperf\Context\Context for coroutine-safe, request-scoped storage. When logging a message, the system automatically merges per-logger context with message-specific context before writing to the underlying Monolog logger.

Related: See Event System for event-driven logging patterns.

Context Architecture

The system implements two context levels:

Context TypeStorage KeyScopeManaged By
Per-Logger Context__logger.contextSingle Logger instanceLogger::withContext()
Shared Context__logger.shared_contextAll Logger instancesLogManager::shareContext()

Context Merging Hierarchy


When Logger::writeLog() executes at src/Logger.php136-144 it calls getContext() to retrieve the per-logger context from __logger.context, then merges it with the message-specific context array before delegating to the underlying Monolog logger.

Sources: src/Logger.php136-144 src/Logger.php177-180 src/LogManager.php418-437

Per-Logger Context Management

Each Logger instance stores context in Hyperf\Context\Context under the key __logger.context. The context persists for the lifetime of the current coroutine/request.

Logger::withContext()

Method Signature: public function withContext(array $context = []): self

The withContext() method at src/Logger.php151-158 uses Context::override() to merge new context with existing context:


Sources: src/Logger.php151-158 src/Logger.php136-144

Logger::withoutContext()

Method Signature: public function withoutContext(): self


The withoutContext() method at src/Logger.php165-170 calls Context::destroy() to remove the __logger.context key entirely.

Sources: src/Logger.php165-170

Logger::getContext()

Method Signature: public function getContext(): array

Returns the current per-logger context by reading from Context::get('__logger.context', []). Called internally by writeLog() to retrieve context before merging.

Sources: src/Logger.php177-180 src/Logger.php136-144

Shared Context Management

The LogManager provides methods to share context across all logger channels. Shared context is stored in __logger.shared_context and is automatically applied to both existing and future logger instances.

LogManager::shareContext()

Method Signature: public function shareContext(array $context): self

Implementation at src/LogManager.php418-429

The shareContext() method performs two operations:

  1. Calls withContext() on all currently resolved logger instances in $this->channels
  2. Stores the context in Context::override('__logger.shared_context', mergeFn)

This dual approach ensures both existing and future channels receive the shared context.

Sources: src/LogManager.php418-429

LogManager::sharedContext()

Method Signature: public function sharedContext(): array

Returns the current shared context by reading Context::get('__logger.shared_context', []). This retrieves the context stored by shareContext() without modifying it.


Sources: src/LogManager.php434-437

LogManager::withoutContext()

Method Signature: public function withoutContext(): self

Calls withoutContext() on all currently resolved logger instances in $this->channels. This clears per-logger context but does NOT clear the shared context storage in __logger.shared_context.


Sources: src/LogManager.php444-453

LogManager::flushSharedContext()

Method Signature: public function flushSharedContext(): self

Completely removes the shared context by calling Context::destroy('__logger.shared_context'). This does not affect per-logger context already set on individual logger instances.

Sources: src/LogManager.php460-465

Context Resolution During Logging

Complete Logging Flow with Context Merging


Key Implementation Details:

  1. The writeLog() method at src/Logger.php136-144 performs the merge
  2. getContext() retrieves per-logger context from __logger.context
  3. Message-specific context takes precedence in the merge (rightmost array in array_merge())
  4. The merged context is passed to both the underlying Monolog logger and the MessageLogged event

Sources: src/Logger.php136-144 src/Logger.php177-180

Technical Implementation

Hyperf Context Storage

Both context types use Hyperf\Context\Context for storage, providing coroutine-safe, request-scoped data management:

BenefitDescription
Coroutine IsolationEach coroutine has independent context storage
Request ScopingContext automatically cleared when coroutine completes
No Global StateEliminates risk of context leakage between concurrent requests

Context Storage Keys:


Sources: src/Logger.php8 src/Logger.php151-180 src/LogManager.php9 src/LogManager.php418-465

Context::override() Merge Behavior

Both Logger::withContext() and LogManager::shareContext() use Context::override() with a merge function:


This pattern ensures:

  • New context is merged with existing context rather than replacing it
  • Calling withContext() multiple times accumulates context
  • Later values override earlier values for the same key

Sources: src/Logger.php153-155 src/LogManager.php424-426

Shared Context Propagation

How Shared Context Reaches Logger Instances:


The shareContext() implementation creates a point-in-time snapshot. Future channels created after shareContext() do NOT automatically receive the shared context unless shareContext() is called again.

Sources: src/LogManager.php418-429

Usage Patterns

Per-Logger Context


Shared Context Across Channels


Context in Middleware


Accumulating Context


Best Practices

  1. Use Structured Context: Structure your context data to make it easily searchable and filterable in log management systems.

  2. Include Correlation IDs: Add request IDs or correlation IDs to your shared context to easily trace requests across services.

  3. Don't Overuse Context: While context is useful, too much context can make logs harder to read and increase log storage requirements.

  4. Clear Context When Appropriate: Use withoutContext() to clear logger context when it's no longer needed, especially in long-running processes.

  5. Be Mindful of Sensitive Data: Avoid including sensitive information (passwords, tokens, etc.) in log context without proper redaction.

  6. Use the Right Context Level: Choose between local and shared context based on how widely the information should be available:

    • Use shared context for request-level information needed across your application
    • Use local context for information specific to a particular component or process

By leveraging Hypervel Log's contextual logging features, you can create more informative, traceable, and useful log entries throughout your application.