solitus0 / httplug-logger-plugin
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/solitus0/httplug-logger-plugin
Requires
- php: >=8.1
- monolog/monolog: >=3.7
- php-http/client-common: ^2.7
- php-http/guzzle7-adapter: ^1.0
- symfony/config: >=6.4
- symfony/dependency-injection: >=6.4
- symfony/http-kernel: >=6.4
Requires (Dev)
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1
- phpstan/phpstan-strict-rules: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: >10
- rector/rector: ^2.0
- spaze/phpstan-disallowed-calls: ^4.7
- symplify/easy-coding-standard: ^12.3
README
Symfony bundle that logs HTTPlug requests/responses through Monolog, with optional Guzzle transfer stats and Google Cloud log formatting.
Features
- HTTPlug plugin that logs request + response context for each client.
- Structured context (
httpRequest,jsonPayload,transfer_stats) suitable for JSON logging. - Log level selection based on response status (2xx info, 4xx warning, 500 error, >500 critical).
- Optional Guzzle transfer stats (latency + timing breakdown).
- Optional request/trace decorators for Google Cloud logging.
Requirements
- PHP 8.1+
- Symfony 6.4+
- Monolog 3.7+
- HTTPlug (php-http/client-common)
- Guzzle 7 adapter (for transfer stats factory)
Installation
composer require solitus0/httplug-logger-plugin
If you are not using Symfony Flex, register the bundle:
return [ Solitus0\HttplugLoggerBundle\LoggerBundle::class => ['all' => true], ];
Basic Configuration
Define one or more logging plugins:
# config/packages/httplug_logger.yaml httplug_logger: plugins: api_client: parser_collection: httplug_logger.parser_collection.default level_picker: httplug_logger.level_picker.default logger: monolog.logger.http_client
Attach the plugin to an HTTPlug client:
# config/packages/httplug.yaml httplug: clients: api_client: plugins: - httplug_logger.plugin.api_client
Transfer Stats (Guzzle 7)
To log transfer timing metrics, use the provided factory (it injects Guzzle on_stats to collect timing data):
# config/packages/httplug.yaml httplug: clients: api_client: factory: httplug_logger.guzzle7_factory.transfer_stats_aware plugins: - httplug_logger.plugin.api_client
When enabled, the log context includes:
transfer_stats:namelookup_time,connect_time,appconnect_time,pretransfer_time,starttransfer_time,total_time(seconds)httpRequest.latency: formatted string like0.123456s
Monolog Formatter (Google Cloud Logging)
The bundle provides a JSON formatter that reshapes records to Google Cloud Logging format:
# config/packages/monolog.yaml monolog: handlers: http_client: type: stream path: "php://stdout" formatter: monolog.formatter.gcp level: info
Optional Log Decorators
Configure decorators that add extra metadata to logs:
# config/packages/httplug_logger.yaml httplug_logger: features: request_decorator: true gcp_trace_decorator: false
request_decoratoraddsreferer,route,remoteIp,host,userAgentto the log recordextra.gcp_trace_decoratorreads thex-cloud-trace-contextheader and adds alogging.googleapis.com/tracevalue. It requiresGOOGLE_CLOUD_PROJECT_IDin your environment.
Response Payload Truncation
Response payload logging is enabled by default and truncated if it exceeds a size limit:
# config/packages/httplug_logger.yaml httplug_logger: parser: response_payload_truncate: true response_payload_max_kilobyte_size: 7
Notes:
- If a response has a
content-dispositionheader (e.g., file download), the payload is replaced with a placeholder message. - JSON responses are decoded and logged as structured data when possible.
GraphQL Request Payloads
A GraphQL request payload parser exists but is not part of the default parser collection. To enable it, define a custom parser collection service:
# config/services.yaml services: httplug_logger.parser_collection.graphql: class: Solitus0\HttplugLoggerBundle\Parser\PsrHttpMessageParserCollection autowire: true autoconfigure: true arguments: $parsers: - '@httplug_logger.parser.psr_request' - '@httplug_logger.parser.psr_request_graphql_payload' - '@httplug_logger.parser.psr_response' - '@httplug_logger.parser.psr_response_payload' - '@httplug_logger.parser.exception' - '@httplug_logger.parser.transfer_stats'
Then reference it in your plugin config:
# config/packages/httplug_logger.yaml httplug_logger: plugins: api_client: parser_collection: httplug_logger.parser_collection.graphql level_picker: httplug_logger.level_picker.default logger: monolog.logger.http_client
Customization
- Log level picker: implement
Solitus0\HttplugLoggerBundle\LevelPicker\LogLevelPickerInterfaceand pointlevel_pickerto your service. - Parsers: implement
RequestParserInterface,ResponseParserInterface, orExceptionParserInterfaceand add to a customPsrHttpMessageParserCollection.
Logged Context Shape (Default)
The log record includes a message plus structured context. Shape example (values are illustrative placeholders):
{
"message": "Sending request",
"context": {
"httpRequest": {
"requestMethod": "GET",
"requestUrl": "https://example.com/resource",
"requestSize": "123",
"status": 200,
"responseSize": "456",
"latency": "0.123456s"
},
"jsonPayload": {
"requestHeaders": {
"Accept": "application/json",
"Authorization": "REDACTED",
"User-Agent": "YourApp/1.0"
},
"requestPayload": {"query": "..."},
"responsePayload": {"data": {"id": 1}}
},
"transfer_stats": {
"namelookup_time": 0.001,
"connect_time": 0.012,
"appconnect_time": 0.020,
"pretransfer_time": 0.030,
"starttransfer_time": 0.040,
"total_time": 0.123
},
"client_name": "api_client"
},
"level": 200,
"level_name": "INFO",
"channel": "http_client",
"datetime": "2025-01-01T12:00:00.000000+00:00",
"extra": {
"route": "/internal/endpoint",
"remoteIp": "127.0.0.1",
"host": "localhost",
"userAgent": "Symfony BrowserKit"
}
}
Notes:
extrafields are added only whenfeatures.request_decoratororfeatures.gcp_trace_decoratorare enabled.transfer_statsandhttpRequest.latencyappear only when using the transfer-stats-aware Guzzle factory.- Payloads are omitted or truncated based on parser settings and response headers.
Testing and QA
make phpstanmake ecsmake rectormake all