Skip to content

Conversation

@hungthai1401
Copy link
Contributor

@hungthai1401 hungthai1401 commented Aug 11, 2025

Sorry for my late.
This PR implement log method to satisfy PSR-3.

Summary by CodeRabbit

  • New Features

    • Adds PSR-3 compliant logging with proper level routing (debug/info/warning/error, etc.) and context forwarding to the runtime logger.
  • Bug Fixes

    • Replaces a no-op logger so messages are recorded reliably.
    • Invalid or unsupported log levels now raise clear errors instead of failing silently.
  • Tests

    • Expanded unit test suite covering level mappings, message types, contexts, error cases, and a test spy for RPC interactions.

@coderabbitai
Copy link

coderabbitai bot commented Aug 11, 2025

Walkthrough

Injects a RoadRunner AppLogger into RpcLogger and implements PSR-3 level normalization and dispatch in log(); adds a comprehensive unit test suite and a test RPC spy to validate level-to-RPC mappings, message/context handling, and invalid-level behavior.

Changes

Cohort / File(s) Summary of Changes
Logger integration and PSR-3 mapping
src/RpcLogger.php
Added AppLogger dependency and __construct(AppLogger $logger); implemented log to normalize PSR-3 levels and dispatch to error/warning/info/debug; forward context; cast info messages to string; throw PsrInvalidArgumentException for invalid levels; updated imports and removed placeholder TODOs.
Unit tests for RpcLogger
tests/Unit/RpcLoggerTest.php
Expanded test file into a full suite: introduced setup wiring RpcSpy → AppLogger → RpcLogger; added data providers and many tests covering level mapping (emergency/alert/critical/error → ErrorWithContext; warning → WarningWithContext; notice/info → InfoWithContext; debug → DebugWithContext), stringable messages, empty/complex contexts, case-insensitive and invalid levels, and PSR-3 trait method behaviours.
Test RPC spy
tests/Unit/RpcSpy.php
Added RpcSpy test double implementing Spiral\Goridge\RPC\RPCInterface; records calls in public calls array with accessors getLastCall(), getCallCount(), and reset(); call() appends entries and returns null; withCodec() and withServicePrefix() are fluent no-ops.

Sequence Diagram(s)

sequenceDiagram
  actor Caller
  participant RpcLogger
  participant AppLogger as RoadRunner AppLogger

  Caller->>RpcLogger: log(level, message, context)
  RpcLogger->>RpcLogger: normalize level (string/lowecase)
  alt level in {emergency, alert, critical, error}
    RpcLogger->>AppLogger: error(message, context)
  else level == warning
    RpcLogger->>AppLogger: warning(message, context)
  else level in {notice, info}
    RpcLogger->>AppLogger: info((string) message, context)
  else level == debug
    RpcLogger->>AppLogger: debug(message, context)
  else invalid level
    RpcLogger-->>Caller: throw PsrInvalidArgumentException
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I hop through logs both near and far,
Nudging levels — info, warn, error, star.
I pass your context, string or date,
Route each chirp to its RPC gate.
A rabbit’s nibble, tidy and quick. 🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2e7bebc and 28a1bb3.

📒 Files selected for processing (2)
  • tests/Unit/RpcLoggerTest.php (1 hunks)
  • tests/Unit/RpcSpy.php (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/Unit/RpcLoggerTest.php (2)
src/RpcLogger.php (2)
  • RpcLogger (13-60)
  • log (30-59)
tests/Unit/RpcSpy.php (3)
  • RpcSpy (17-51)
  • getCallCount (42-45)
  • getLastCall (37-40)
🪛 PHPMD (2.15.0)
tests/Unit/RpcSpy.php

27-27: Avoid unused parameters such as '$codec'. (Unused Code Rules)

(UnusedFormalParameter)


32-32: Avoid unused parameters such as '$service'. (Unused Code Rules)

(UnusedFormalParameter)

🔇 Additional comments (9)
tests/Unit/RpcSpy.php (2)

1-51: Well-designed test double with comprehensive functionality.

The RpcSpy implementation is clean and provides all necessary functionality for testing RPC interactions. The fluent interface methods correctly return $this, and the call recording mechanism is straightforward and effective.


27-35: Unused parameters are acceptable in test doubles.

The static analysis warnings about unused parameters $codec and $service in the fluent interface methods are false positives. These parameters are intentionally unused since this is a test spy that implements the interface contract without requiring actual functionality.

tests/Unit/RpcLoggerTest.php (7)

22-27: LGTM! Clean test setup.

The setUp method properly initializes the test dependencies with clear dependency injection chain: RpcSpy → AppLogger → RpcLogger.


36-48: Excellent use of data providers for comprehensive level testing.

The parameterized test approach ensures all emergency-level log levels (emergency, alert, critical, error) are properly validated to map to the 'ErrorWithContext' RPC method.


145-175: Comprehensive invalid input validation.

Excellent coverage of edge cases for invalid log levels including non-string types, null, and boolean values. The exception message assertions ensure proper error reporting.


177-208: Thorough edge case coverage for message and context handling.

Good testing of boundary conditions including empty strings, numeric strings, and empty context arrays. These tests ensure robust handling of various input scenarios.


211-305: Complete PSR-3 LoggerTrait method coverage.

Excellent systematic testing of all PSR-3 logger methods, validating that each method properly delegates to the correct RPC method through the log() implementation.


307-325: Good complex context validation.

The test with nested arrays and DateTime objects ensures the logger handles complex context data structures properly, which is important for real-world usage.


327-343: Well-organized data providers.

The data providers are properly structured and provide clear test case names that make test failures easy to understand.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/RpcLogger.php (4)

17-22: Constructor injection with a readonly dependency looks good; consider property promotion to reduce boilerplate.

You can remove the explicit property and assignment by promoting it in the constructor.

-    private readonly AppLogger $logger;
-
-    public function __construct(AppLogger $logger)
-    {
-        $this->logger = $logger;
-    }
+    public function __construct(private readonly AppLogger $logger)
+    {
+    }

24-29: Docblock improvements: add @throws and align context key type.

  • PSR-3 reserves the right to throw InvalidArgumentException for invalid levels; document it.
  • Align the context annotation with the assertion below (string keys).
 /**
  * @param mixed $level
- * @param array<array-key, mixed> $context
+ * @param array<string, mixed> $context
+ *
+ * @throws \Psr\Log\InvalidArgumentException
  *
  * @link https://www.php-fig.org/psr/psr-3/#5-psrlogloglevel
  */

36-41: Preserve the original PSR severity when collapsing multiple levels to a single backend level.

Since EMERGENCY/ALERT/CRITICAL/ERROR are all mapped to error(), consider forwarding the original PSR level in context to avoid loss of fidelity.

-                $this->logger->error((string) $message, $context);
+                $this->logger->error((string) $message, $context + ['psr_level' => $normalizedLevel]);

56-58: Improve the exception message for diagnostics.

Including the original type/value helps debugging invalid inputs.

-                throw new PsrInvalidArgumentException('Invalid log level: ' . $normalizedLevel);
+                throw new PsrInvalidArgumentException(
+                    sprintf(
+                        'Invalid log level: %s (normalized: %s)',
+                        \is_scalar($level) ? (string) $level : \get_debug_type($level),
+                        $normalizedLevel
+                    )
+                );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f66b60 and 8fa9dbf.

📒 Files selected for processing (1)
  • src/RpcLogger.php (1 hunks)
🔇 Additional comments (1)
src/RpcLogger.php (1)

9-11: Imports/aliases are appropriate and consistent with PSR-3 usage.

No issues spotted.

Comment on lines +32 to +55
$normalizedLevel = \is_string($level) ? \strtolower($level) : (string) $level;

/** @var array<string, mixed> $context */
switch ($normalizedLevel) {
case PsrLogLevel::EMERGENCY:
case PsrLogLevel::ALERT:
case PsrLogLevel::CRITICAL:
case PsrLogLevel::ERROR:
$this->logger->error($message, $context);
return;

case PsrLogLevel::WARNING:
$this->logger->warning($message, $context);
return;

case PsrLogLevel::NOTICE:
case PsrLogLevel::INFO:
$this->logger->info((string) $message, $context);
return;

case PsrLogLevel::DEBUG:
$this->logger->debug($message, $context);
return;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure message is always a string when calling AppLogger to avoid potential TypeError.

If AppLogger methods are typed as string $message (common), passing a Stringable directly can trigger a TypeError. Cast consistently across all branches (INFO already does).

-                $this->logger->error($message, $context);
+                $this->logger->error((string) $message, $context);
                 return;

             case PsrLogLevel::WARNING:
-                $this->logger->warning($message, $context);
+                $this->logger->warning((string) $message, $context);
                 return;

             case PsrLogLevel::NOTICE:
             case PsrLogLevel::INFO:
                 $this->logger->info((string) $message, $context);
                 return;

             case PsrLogLevel::DEBUG:
-                $this->logger->debug($message, $context);
+                $this->logger->debug((string) $message, $context);
                 return;

To confirm AppLogger’s parameter types, please verify the method signatures:


🌐 Web query:

What are the PHP method signatures (parameter types) of error(), warning(), info(), and debug() on the RoadRunner Logger class (RoadRunner\Logger\Logger or Spiral\RoadRunner\Logger)? Do they accept only string $message or also \Stringable?

💡 Result:

Short answer: the RoadRunner PHP logger methods take string, not \Stringable.

Details / signatures (as published in the package docs):

  • debug(string): void
  • error(string): void
  • info(string): void
  • warning(string): void
    (there is also log(string): void for stderr.)

The RoadRunner app-logger docs and the package README show these methods typed/documented as string, and the RPC API used by the plugin uses plain string parameters. (docs.roadrunner.dev, github.com, packagist.org)

If you want, I can fetch the exact Logger.php source file for the release you care about and paste the function signatures (to show the exact type hints used in code). Which version/branch should I check?

Citations:


Ensure message is cast to string for all AppLogger calls

RoadRunner’s AppLogger methods (debug(), error(), info(), warning()) are strictly typed to accept string only (per docs.roadrunner.dev, app-logger README). Passing a \Stringable directly will trigger a TypeError. You should consistently cast $message to string in every branch:

• File: src/RpcLogger.php (around lines 32–55)
• Update the calls to error(), warning(), and debug() as follows:

--- a/src/RpcLogger.php
+++ b/src/RpcLogger.php
@@ switch ($normalizedLevel) {
     case PsrLogLevel::EMERGENCY:
     case PsrLogLevel::ALERT:
     case PsrLogLevel::CRITICAL:
     case PsrLogLevel::ERROR:
-        $this->logger->error($message, $context);
+        $this->logger->error((string) $message, $context);
         return;

     case PsrLogLevel::WARNING:
-        $this->logger->warning($message, $context);
+        $this->logger->warning((string) $message, $context);
         return;

     case PsrLogLevel::NOTICE:
     case PsrLogLevel::INFO:
         $this->logger->info((string) $message, $context);
         return;

     case PsrLogLevel::DEBUG:
-        $this->logger->debug($message, $context);
+        $this->logger->debug((string) $message, $context);
         return;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$normalizedLevel = \is_string($level) ? \strtolower($level) : (string) $level;
/** @var array<string, mixed> $context */
switch ($normalizedLevel) {
case PsrLogLevel::EMERGENCY:
case PsrLogLevel::ALERT:
case PsrLogLevel::CRITICAL:
case PsrLogLevel::ERROR:
$this->logger->error($message, $context);
return;
case PsrLogLevel::WARNING:
$this->logger->warning($message, $context);
return;
case PsrLogLevel::NOTICE:
case PsrLogLevel::INFO:
$this->logger->info((string) $message, $context);
return;
case PsrLogLevel::DEBUG:
$this->logger->debug($message, $context);
return;
$normalizedLevel = \is_string($level) ? \strtolower($level) : (string) $level;
/** @var array<string, mixed> $context */
switch ($normalizedLevel) {
case PsrLogLevel::EMERGENCY:
case PsrLogLevel::ALERT:
case PsrLogLevel::CRITICAL:
case PsrLogLevel::ERROR:
$this->logger->error((string) $message, $context);
return;
case PsrLogLevel::WARNING:
$this->logger->warning((string) $message, $context);
return;
case PsrLogLevel::NOTICE:
case PsrLogLevel::INFO:
$this->logger->info((string) $message, $context);
return;
case PsrLogLevel::DEBUG:
$this->logger->debug((string) $message, $context);
return;
}
🤖 Prompt for AI Agents
In src/RpcLogger.php around lines 32 to 55, AppLogger methods require a string
and currently some branches pass $message without casting; update the calls to
$this->logger->error, $this->logger->warning and $this->logger->debug to cast
the message to string (e.g. (string) $message) so every logger call receives a
string (info already does this).

@roxblnfk roxblnfk linked an issue Aug 11, 2025 that may be closed by this pull request

/**
* @param mixed $level
* @param array<array-key, mixed> $context
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we have to convert this $context for roadrunner logger format.
For example an Exception, DateTime, or DateInterval object can be here. We need to format it in a good way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roxblnfk Do you have any suggestions for me?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, write tests.
With tests we can merge the PR and then add other features like exceptions formatting

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roxblnfk I have added unit test for this PR, plz confirm them. tysm

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
tests/Unit/RpcLoggerTest.php (5)

31-36: Constructor test is redundant but harmless

Since instantiation is already exercised in setUp() and all subsequent tests, this dedicated constructor test adds minimal extra value. Fine to keep for explicitness; okay to drop to reduce test noise.


147-177: LGTM: Invalid level scenarios; consider a couple more edge cases

The assertions for int, null, and bool(true) are sharp and aligned with normalized string casting. Optional: add tests for bool(false) → 'Invalid log level: ' (empty string) and numeric string '0' to fully cover corner cases.


212-307: Reduce repetition with small assertion helper or a data provider for trait methods

Eight trait-method tests repeat the same pattern. Consider a helper to DRY:

private function assertLastCall(string $expectedMethod): void
{
    $this->assertSame(1, $this->rpc->getCallCount());
    $lastCall = $this->rpc->getLastCall();
    $this->assertSame($expectedMethod, $lastCall['method']);
}

Then each test can shrink to the act + assertLastCall('...'). Alternatively, a data provider mapping method names to expected RPC methods can collapse these into a single parametrized test.


361-369: Silence static analysis warnings for unused parameters in TestRPC

PHPMD flags unused parameters in withCodec/withServicePrefix. Prefix them with an underscore to signal intentional non-use.

-    public function withCodec(CodecInterface $codec): RPCInterface
+    public function withCodec(CodecInterface $_codec): RPCInterface
     {
         return $this;
     }

-    public function withServicePrefix(string $service): RPCInterface
+    public function withServicePrefix(string $_service): RPCInterface
     {
         return $this;
     }

371-375: Avoid mutating internal array pointer in getLastCall()

Using end() mutates the internal pointer. Favor array_key_last for purity.

-    public function getLastCall(): ?array
-    {
-        return end($this->calls) ?: null;
-    }
+    public function getLastCall(): ?array
+    {
+        if ($this->calls === []) {
+            return null;
+        }
+        return $this->calls[array_key_last($this->calls)];
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8fa9dbf and 2e7bebc.

📒 Files selected for processing (1)
  • tests/Unit/RpcLoggerTest.php (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/Unit/RpcLoggerTest.php (1)
src/RpcLogger.php (2)
  • RpcLogger (13-60)
  • log (30-59)
🪛 PHPMD (2.15.0)
tests/Unit/RpcLoggerTest.php

361-361: Avoid unused parameters such as '$codec'. (Unused Code Rules)

(UnusedFormalParameter)


366-366: Avoid unused parameters such as '$service'. (Unused Code Rules)

(UnusedFormalParameter)

🔇 Additional comments (10)
tests/Unit/RpcLoggerTest.php (10)

24-29: LGTM: Clean dependency wiring in setUp()

Good composition: TestRPC → AppLogger → RpcLogger. This isolates the unit under test and gives precise observability of RPC interactions.


38-50: LGTM: Correct mapping for emergency/alert/critical/error to ErrorWithContext

Assertions on method name and DTO payload type are on point.


52-63: LGTM: Warning → WarningWithContext and notice/info → InfoWithContext

Solid coverage and correct assertions for context-bearing calls.

Also applies to: 65-77


79-90: LGTM: Debug → DebugWithContext

Correct mapping and payload type verification.


109-119: LGTM: Correctly asserting no-context path (Info + raw payload)

Both tests validate the “no context → non-with-context RPC method” behavior. This aligns well with AppLogger’s split between WithContext and non-context methods.

Also applies to: 199-210


121-145: LGTM: Case-insensitive level handling

Good coverage for uppercase and mixed-case inputs; matches the normalization strategy.


179-197: LGTM: Message passthrough cases (empty string and numeric string)

Good checks for raw-message passthrough when no context is supplied.


309-327: LGTM: Complex context sanity check

Good to see nested arrays and objects accepted without exploding the serializer path. Method routing remains correct.


329-346: LGTM: Data providers are clear and explicit

Named datasets improve readability of failures.


376-385: LGTM: Utility methods for the spy are straightforward

getCallCount() and reset() are simple and effective for test assertions.

Comment on lines +92 to +107
public function testLogWithStringableMessage(): void
{
$stringableMessage = new class implements \Stringable {
public function __toString(): string
{
return 'Stringable message';
}
};

$this->rpcLogger->log(PsrLogLevel::INFO, $stringableMessage);

$this->assertSame(1, $this->rpc->getCallCount());
$lastCall = $this->rpc->getLastCall();
$this->assertSame('Info', $lastCall['method']);
$this->assertSame('Stringable message', $lastCall['payload']);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Consider asserting stringable handling across all levels; align impl to cast consistently

Great check for stringable messages (INFO with no context). To harden behavior and prevent future regressions:

  • Add analogous tests for stringable messages at ERROR/WARNING/DEBUG (with/without context).
  • Ensure RpcLogger casts to string before delegating at all levels (DEBUG currently passes $message without a cast; INFO/NOTICE cast).

Follow-up: If you want to lock this in at the implementation level, consider this change in RpcLogger::log:

public function log($level, \Stringable|string $message, array $context = []): void
{
    $normalizedLevel = \is_string($level) ? \strtolower($level) : (string) $level;
    $msg = (string) $message;

    switch ($normalizedLevel) {
        case Psr\Log\LogLevel::EMERGENCY:
        case Psr\Log\LogLevel::ALERT:
        case Psr\Log\LogLevel::CRITICAL:
        case Psr\Log\LogLevel::ERROR:
            $this->logger->error($msg, $context);
            return;

        case Psr\Log\LogLevel::WARNING:
            $this->logger->warning($msg, $context);
            return;

        case Psr\Log\LogLevel::NOTICE:
        case Psr\Log\LogLevel::INFO:
            $this->logger->info($msg, $context);
            return;

        case Psr\Log\LogLevel::DEBUG:
            $this->logger->debug($msg, $context);
            return;

        default:
            throw new Psr\Log\InvalidArgumentException('Invalid log level: ' . $normalizedLevel);
    }
}

Run this quick check to confirm current casting patterns in RpcLogger:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate RpcLogger and show how info/debug are invoked
fd -i --full-path 'RpcLogger.php' -t f | while read -r file; do
  echo ">>> $file"
  rg -n -C2 '\$this->logger->info\(' "$file"
  rg -n -C2 '\$this->logger->debug\(' "$file"
done

Length of output: 568


Cast stringable messages for DEBUG too; add tests for other levels

Verified: src/RpcLogger.php casts (string) $message for INFO/NOTICE (around line 49) but passes $message uncast to DEBUG (around line 53). This is inconsistent and can break Stringable handling.

Actionable items:

  • Fix implementation
    • File: src/RpcLogger.php — replace:
      case PsrLogLevel::DEBUG:
          $this->logger->debug($message, $context);
          return;
      
      with:
      case PsrLogLevel::DEBUG:
          $this->logger->debug((string) $message, $context);
          return;
      
  • Add tests
    • File: tests/Unit/RpcLoggerTest.php — add analogous stringable-message tests for DEBUG, WARNING and ERROR (with/without context), mirroring the existing INFO test.
  • Optional improvement
    • Normalize/cast once at the start of RpcLogger::log (accept \Stringable|string $message and do $msg = (string)$message) and use $msg for all logger calls to avoid repetition.
🤖 Prompt for AI Agents
In tests/Unit/RpcLoggerTest.php around lines 92-107, add missing tests and fix
the implementation: update src/RpcLogger.php so the DEBUG branch casts
stringable messages like the others (replace the DEBUG call to pass (string)
$message or better, cast once at the start of RpcLogger::log into $msg and use
$msg for all levels), then add new unit tests in tests/Unit/RpcLoggerTest.php
mirroring the existing INFO test for stringable messages at DEBUG, WARNING and
ERROR (include variants that pass context where applicable) to assert the RPC
call count, method name and that the payload equals the stringified message.

@roxblnfk roxblnfk merged commit d83460e into roadrunner-php:1.x Aug 19, 2025
10 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Aug 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add PSR RpcLogger

2 participants