Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ If it saves you or your team time, please consider [sponsoring its development](

## [Unreleased]

### Changed

* `Factory::withHttpLogger()` and `Factory::withHttpDebugLogger()` have been deprecated. If you're using these methods,
you can use `HttpClientOptions` instead.
([Documentation](https://firebase-php.readthedocs.io/en/latest/setup.html#logging))

### Deprecated methods

* `Kreait\Firebase\Factory::withHttpLogger()`
* `Kreait\Firebase\Factory::withHttpDebugLogger()`
* `Kreait\Firebase\Http\Middleware::log()`

## [7.24.0] - 2025-11-27

### Changed
Expand Down
38 changes: 15 additions & 23 deletions docs/setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -222,44 +222,36 @@ You can also add middlewares to the Guzzle HTTP Client:
You can find more information about Guzzle Middlewares at
`Guzzle: Handlers and Middleware <https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html>`_

*******
Logging
*******
=======

In order to log API requests to the Firebase APIs, you can provide the factory with loggers
implementing ``Psr\Log\LoggerInterface``.

The following examples use the `Monolog <https://github.com/Seldaek/monolog>`_ logger, but
The following example uses the `Monolog <https://github.com/Seldaek/monolog>`_ logger, but
work with any `PSR-3 log implementation <https://packagist.org/providers/psr/log-implementation>`_.

.. code-block:: php

use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware as GuzzleMiddleware;
use Kreait\Firebase\Factory;
use Monolog\Logger;
use Kreait\Firebase\Http\HttpClientOptions;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Log\LogLevel;

$httpLogger = new Logger('firebase_http_logs');
$httpLogger->pushHandler(new StreamHandler('path/to/firebase_api.log', Logger::INFO));
$httpLogger->pushHandler(new StreamHandler('path/to/firebase_api.log'));

// Without further arguments, requests and responses will be logged with basic
// request and response information. Successful responses will be logged with
// the 'info' log level, failures (Status code >= 400) with 'notice'
$factory = $factory->withHttpLogger($httpLogger);

// You can configure the message format and log levels individually
$messageFormatter = new MessageFormatter(MessageFormatter::SHORT);
$factory = $factory->withHttpLogger(
$httpLogger, $messageFormatter, $successes = 'debug', $errors = 'warning'
);

// You can provide a separate logger for detailed HTTP message logs
$httpDebugLogger = new Logger('firebase_http_debug_logs');
$httpDebugLogger->pushHandler(
new StreamHandler('path/to/firebase_api_debug.log',
Logger::DEBUG)
$logMiddleware = GuzzleMiddleware::log(
logger: $httpLogger,
formatter: new MessageFormatter(),
logLevel: LogLevel::INFO,
);

// Logs will include the full request and response headers and bodies
$factory = $factory->withHttpDebugLogger($httpDebugLogger)
$options = $options->withGuzzleMiddleware($logMiddleware, 'http_debug_logs');

$factory = (new Factory())
->withHttpClientOptions($clientOptions)
;
56 changes: 30 additions & 26 deletions src/Firebase/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,6 @@ final class Factory

private ClockInterface $clock;

/**
* @var callable|null
*/
private $httpLogMiddleware;

/**
* @var callable|null
*/
private $httpDebugLogMiddleware;

/**
* @var callable|null
*/
Expand Down Expand Up @@ -317,33 +307,55 @@ public function withHttpClientOptions(HttpClientOptions $options): self
}

/**
* @deprecated 7.25.0 Create the log middleware outside the factory and use `HttpClientOptions::withGuzzleMiddleware()` and `withClientOptions()` instead
*
* @see withHttpClientOptions()
* @see HttpClientOptions::withGuzzleMiddleware()
*
* @param non-empty-string|null $logLevel
* @param non-empty-string|null $errorLogLevel
*/
public function withHttpLogger(LoggerInterface $logger, ?MessageFormatter $formatter = null, ?string $logLevel = null, ?string $errorLogLevel = null): self
{
$formatter ??= new MessageFormatter();
$logLevel ??= LogLevel::INFO;
$errorLogLevel ??= LogLevel::NOTICE;
$clientOptions = $this->httpClientOptions->withGuzzleMiddleware(
middleware: Middleware::log(
$logger,
$formatter ?? new MessageFormatter(),
$logLevel ?? LogLevel::INFO,
$errorLogLevel ?? LogLevel::NOTICE,
),
name: 'http_logs'
);

$factory = clone $this;
$factory->httpLogMiddleware = Middleware::log($logger, $formatter, $logLevel, $errorLogLevel);
$factory->httpClientOptions = $clientOptions;

return $factory;
}

/**
* @deprecated 7.25.0 Create the log middleware outside the factory and use `HttpClientOptions::withGuzzleMiddleware()` and `withClientOptions()` instead
*
* @see withHttpClientOptions()
* @see HttpClientOptions::withGuzzleMiddleware()
*
* @param non-empty-string|null $logLevel
* @param non-empty-string|null $errorLogLevel
*/
public function withHttpDebugLogger(LoggerInterface $logger, ?MessageFormatter $formatter = null, ?string $logLevel = null, ?string $errorLogLevel = null): self
{
$formatter ??= new MessageFormatter(MessageFormatter::DEBUG);
$logLevel ??= LogLevel::INFO;
$errorLogLevel ??= LogLevel::NOTICE;
$clientOptions = $this->httpClientOptions->withGuzzleMiddleware(
middleware: Middleware::log(
$logger,
$formatter ?? new MessageFormatter(MessageFormatter::DEBUG),
$logLevel ?? LogLevel::INFO,
$errorLogLevel ?? LogLevel::NOTICE,
),
name: 'http_debug_logs'
);

$factory = clone $this;
$factory->httpDebugLogMiddleware = Middleware::log($logger, $formatter, $logLevel, $errorLogLevel);
$factory->httpClientOptions = $clientOptions;

return $factory;
}
Expand Down Expand Up @@ -587,14 +599,6 @@ public function createApiClient(?array $config = null, ?array $middlewares = nul

$handler = HandlerStack::create($config['handler'] ?? null);

if ($this->httpLogMiddleware !== null) {
$handler->push($this->httpLogMiddleware, 'http_logs');
}

if ($this->httpDebugLogMiddleware !== null) {
$handler->push($this->httpDebugLogMiddleware, 'http_debug_logs');
}

foreach ($this->httpClientOptions->guzzleMiddlewares() as $middleware) {
$handler->push($middleware['middleware'], $middleware['name']);
}
Expand Down
4 changes: 3 additions & 1 deletion src/Firebase/Http/Middleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ public static function addDatabaseAuthVariableOverride(?array $override): callab
}

/**
* @deprecated 7.25.0 Use the Log Middleware provided by the GuzzleHTTP library instead
*
* @return callable(callable): Closure
*/
public static function log(LoggerInterface $logger, MessageFormatter $formatter, string $logLevel, string $errorLogLevel): callable
{
return static fn(callable $handler): Closure => static fn($request, array $options) => $handler($request, $options)->then(
return static fn(callable $handler): Closure => static fn(RequestInterface $request, array $options) => $handler($request, $options)->then(
static function (ResponseInterface $response) use ($logger, $request, $formatter, $logLevel, $errorLogLevel): ResponseInterface {
$message = $formatter->format($request, $response);
$messageLogLevel = $response->getStatusCode() >= StatusCode::STATUS_BAD_REQUEST ? $errorLogLevel : $logLevel;
Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/Http/HttpClientOptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @internal
*/
class HttpClientOptionsTest extends IntegrationTestCase
final class HttpClientOptionsTest extends IntegrationTestCase
{
#[Test]
public function itWorksWithAFunctionMiddleware(): void
Expand Down
18 changes: 16 additions & 2 deletions tests/Integration/HttpLoggingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

namespace Kreait\Firebase\Tests\Integration;

use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;
use Kreait\Firebase\Contract\Auth;
use Kreait\Firebase\Exception\Auth\UserNotFound;
use Kreait\Firebase\Http\HttpClientOptions;
use Kreait\Firebase\Tests\IntegrationTestCase;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Throwable;

/**
Expand All @@ -34,9 +38,19 @@ protected function setUp(): void
$this->logger = $this->createMock(LoggerInterface::class);
$this->debugLogger = $this->createMock(LoggerInterface::class);

$logMiddleware = Middleware::log($this->logger, new MessageFormatter(), LogLevel::INFO);
$debugLogMiddleware = Middleware::log($this->debugLogger, new MessageFormatter(MessageFormatter::DEBUG), LogLevel::DEBUG);

$clientOptions = HttpClientOptions::default();

$this->auth = self::$factory->createAuth();
$this->authWithLogger = self::$factory->withHttpLogger($this->logger)->createAuth();
$this->authWithDebugLogger = self::$factory->withHttpDebugLogger($this->debugLogger)->createAuth();
$this->authWithLogger = self::$factory
->withHttpClientOptions($clientOptions->withGuzzleMiddleware($logMiddleware))
->createAuth();

$this->authWithDebugLogger = self::$factory
->withHttpClientOptions($clientOptions->withGuzzleMiddleware($debugLogMiddleware))
->createAuth();
}

#[Test]
Expand Down
Loading