PHPackages                             saloonphp/barstool - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. saloonphp/barstool

ActiveLibrary[HTTP &amp; Networking](/categories/http)

saloonphp/barstool
==================

A Laravel package for logging Saloon Requests &amp; Response.

v1.2.0(3w ago)1852.1k↑15112.5%3[2 issues](https://github.com/saloonphp/barstool/issues)[2 PRs](https://github.com/saloonphp/barstool/pulls)1MITPHPPHP ^8.3|^8.4|^8.5CI passing

Since Mar 26Pushed 1mo agoCompare

[ Source](https://github.com/saloonphp/barstool)[ Packagist](https://packagist.org/packages/saloonphp/barstool)[ Docs](https://github.com/saloonphp/barstool)[ RSS](/packages/saloonphp-barstool/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (5)Dependencies (42)Versions (12)Used By (1)

Barstool
========

[](#barstool)

[![Latest Version on Packagist](https://camo.githubusercontent.com/ffb0e6c4cf24425ccb1adda416e751b76ae47a2413ae8e1983c3d5bea8b95361/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73616c6f6f6e7068702f62617273746f6f6c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/saloonphp/barstool)[![GitHub Tests Action Status](https://camo.githubusercontent.com/0824755a4abce3ed3d4456632799bfcb985a8ee5d66502adfcbd82f84fbe1d1d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f73616c6f6f6e7068702f62617273746f6f6c2f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/saloonphp/barstool/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/3b461a425e2f020f1bf57d47596b8fa844961e79ab26b9e2ce301725dbbb9e75/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f73616c6f6f6e7068702f62617273746f6f6c2f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/saloonphp/barstool/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/51fdb02fae4cd9e717d70726d80b0d97058bd9d6402011e86f73fb54e3a6ec32/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73616c6f6f6e7068702f62617273746f6f6c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/saloonphp/barstool)

Barstool is a dedicated Laravel package to help you keep track of your [Saloon](https://github.com/saloonphp/saloon) requests &amp; responses.

Barstool will allow you to easily view, search, and filter your logs directly in your database tool of choice.

The package is designed to be as simple as possible to get up and running, with minimal configuration required.

So pull up a barstool, grab a drink, and let's get logging in the Saloon! Yeehaw!

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 12+
- Saloon v4

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require saloonphp/barstool
```

You can publish and run the migrations with:

```
php artisan vendor:publish --tag="barstool-migrations"
php artisan migrate
```

You can publish the config file with:

```
php artisan vendor:publish --tag="barstool-config"
```

Finally, set up [pruning](#pruning-old-recordings) in your scheduler so your logs don't grow forever.

Usage
-----

[](#usage)

That's all folks! Once installed, Barstool starts logging your [Saloon](https://github.com/saloonphp/saloon) requests automatically. Check the config out for more control.

Here are some of the things you can see with Barstool:

- Request Method
- Connector Used
- Request Used
- Request URL
- Request Headers
- Request Body
- Response Status Code
- Response Headers
- Response Body
- Response Duration

Barstool will even log fatal errors caused by your Saloon requests, so you can see what went wrong.

[![Screenshot of the fatal error logged in the database](/art/fatal_error.png)](/art/fatal_error.png)

Tip

We will be adding more features soon, so keep an eye out for updates!

Configuration
-------------

[](#configuration)

Everything below lives in `config/barstool.php` once published.

### Enabling &amp; disabling

[](#enabling--disabling)

Barstool is enabled out of the box. To switch it off entirely — no requests recorded — set the env variable:

```
BARSTOOL_ENABLED=false
```

Handy for local development or test environments where you don't want the noise.

### Choosing what gets recorded

[](#choosing-what-gets-recorded)

By default, Barstool records every Saloon request. You can narrow that down in two directions:

- **`only`** — an allowlist. If any connectors or requests are listed, only those are recorded and everything else is skipped automatically. Handy when you have lots of connectors but only care about a few.
- **`ignore`** — a denylist. Listed connectors or requests are never recorded.

```
// config/barstool.php
'only' => [
    'connectors' => [
        StripeConnector::class, // record everything sent through this connector...
    ],
    'requests' => [],
],

'ignore' => [
    'connectors' => [],
    'requests' => [
        StripeHealthCheckRequest::class, // ...except this noisy request
    ],
],
```

A request is recorded if it matches either `only` list (or both lists are empty), and the `ignore` list always takes precedence — so you can allow a whole connector and still ignore individual requests on it.

### Keeping only failed responses

[](#keeping-only-failed-responses)

If you mainly use Barstool to investigate failures, you can skip storing successful response data:

```
'keep_successful_responses' => false,
```

The request, response status, duration, and outcome are still recorded for successful calls — only the response body and headers are omitted, so your "show me failures" queries stay accurate. Failed responses and fatal errors are always kept in full.

### Redacting sensitive request headers

[](#redacting-sensitive-request-headers)

Headers listed in `excluded_request_headers` are stored with their value replaced by `REDACTED`. The `Authorization` header is redacted by default.

```
'excluded_request_headers' => [
    'Authorization',
    'X-Api-Key',            // redact this header on every request
    SensitiveRequest::class, // redact ALL headers for this request
    SensitiveConnector::class, // redact ALL headers for this connector
    // '*',                 // redact ALL headers on every request
],
```

When `'*'` or a connector/request class matches, every header is dropped from the recording except Barstool's own `X-Barstool-UUID` correlation header.

Header names are matched case-insensitively, so `authorization` is caught by an `Authorization` exclusion.

### Redacting sensitive response headers

[](#redacting-sensitive-response-headers)

Response headers work the same way via `excluded_response_headers` — matching values are stored as `REDACTED`. The `Set-Cookie` header is redacted by default so session cookies never land in your logs:

```
'excluded_response_headers' => [
    'Set-Cookie',
    // '*',                    // redact every response header
    // SensitiveConnector::class, // redact all response headers for a connector
    // SensitiveRequest::class,   // or a single request
],
```

### Excluding response bodies

[](#excluding-response-bodies)

Response bodies for sensitive endpoints can be kept out of the database entirely — they are stored as `REDACTED`:

```
'excluded_response_body' => [
    SensitiveConnector::class, // exclude bodies for a whole connector
    SensitiveRequest::class,   // or a single request
    // '*',                    // or every response
],
```

### Response body limits

[](#response-body-limits)

To keep the table lean, Barstool only stores response bodies that are:

- **A supported content type** — JSON, XML, SOAP, HTML, or plain text. Anything else (files, images, binary data) is stored as ``.
- **Within the size limit** — `max_response_size` (in kilobytes, default `100`). Oversized bodies are stored as `` too.

```
'max_response_size' => 100,
```

You may also spot a couple of other placeholder values in the `barstools` table: streamed request/response bodies are stored as `` (reading them would consume the stream before your application gets it), and multipart request bodies as ``.

### Database connection

[](#database-connection)

Recordings are stored on your default database connection. To keep them elsewhere — a separate database, or just a different connection — set:

```
BARSTOOL_DB_CONNECTION=barstool
```

The migration and the `Barstool` model both respect this connection.

### Pruning old recordings

[](#pruning-old-recordings)

Recordings are kept for 30 days by default, controlled by:

```
'keep_for_days' => 30,
```

Pruning uses [Laravel's model pruning](https://laravel.com/docs/eloquent#pruning-models), so you need to schedule it. Please check the Laravel Documentation for your version to know where to put the code below.

```
use Saloon\Barstool\Models\Barstool;

Schedule::command('model:prune', [
    '--model' => [Barstool::class],
])->daily();
```

### Queue support

[](#queue-support)

By default, Barstool writes recordings to the database synchronously. If you'd like to offload this to a queue, you can enable it in the config:

```
'queue' => [
    'enabled' => env('BARSTOOL_QUEUE_ENABLED', false),
    'connection' => env('BARSTOOL_QUEUE_CONNECTION'),  // null uses default connection
    'queue' => env('BARSTOOL_QUEUE_NAME'),             // null uses default queue
],
```

Or simply set `BARSTOOL_QUEUE_ENABLED=true` in your `.env` file.

When queue support is enabled, recordings are dispatched as jobs instead of being written inline. Each job is **unique** (preventing duplicates) and uses **idempotent writes** (`updateOrCreate`), so recordings are safe even if a job is retried. Failed jobs will automatically retry up to 3 times with a backoff of 5 and 30 seconds.

Adding context to recordings
----------------------------

[](#adding-context-to-recordings)

Sometimes the request and response alone don't tell the whole story. You can attach your own context to recordings — the current user, tenant, job name, anything you like — and it will be stored in the `context` column of the `barstools` table as JSON:

```
use Saloon\Barstool\Barstool;

Barstool::context([
    'user_id' => auth()->id(),
    'tenant_id' => $tenant->id,
]);

// Or add a single key:
Barstool::addContext('job', 'user-sync');
```

Once set, the context is stored against every request Barstool records until the end of the current request or job. Calling `context()` again merges the new keys in (overwriting any that already exist), and you can clear everything with `Barstool::flushContext()`.

Under the hood this uses [Laravel Context](https://laravel.com/docs/context) hidden data, which means:

- Context added in a controller is carried into queued jobs automatically, so requests sent from inside a job still record it.
- It is reset between requests and jobs by the framework, so nothing leaks across tenants or users.
- It stays out of your application's log context.

Important

If you are upgrading from an earlier version of Barstool, publish and run the migrations again to add the new `context` column:

```
php artisan vendor:publish --tag="barstool-migrations"
php artisan migrate
```

Barstool only touches the `context` column when you actually set context, so upgrading the package without running the migration is safe until you start using this feature.

Correlating Barstool records with your own models
-------------------------------------------------

[](#correlating-barstool-records-with-your-own-models)

If you want a row in one of your own tables to point at a Barstool recording (rather than storing extra data on the recording itself), you can read the recording's UUID straight off the sent request. Barstool adds an `X-Barstool-UUID` header to every request it records:

```
$response = $connector->send($request);

$barstoolUuid = $response->getPendingRequest()->headers()->get('X-Barstool-UUID');

if ($response->failed()) {
    UserSyncLog::create([
        'user_id' => auth()->id(),
        'barstool_uuid' => $barstoolUuid,
    ]);
}
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](./.github/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Craig Potter](https://github.com/craigpotter)
- [Sam Carre](https://github.com/Sammyjo20)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

55

—

FairBetter than 97% of packages

Maintenance90

Actively maintained with recent releases

Popularity41

Moderate usage in the ecosystem

Community15

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 66.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~28 days

Total

5

Last Release

22d ago

PHP version history (2 changes)v1.0.0PHP ^8.3|^8.4

v1.2.0PHP ^8.3|^8.4|^8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/de41c8bfde9d0edb25da9fdc159283fe9442e3dc9b651ee9aa7ded8384e5629d?d=identicon)[SamCarre](/maintainers/SamCarre)

---

Top Contributors

[![craigpotter](https://avatars.githubusercontent.com/u/1442635?v=4)](https://github.com/craigpotter "craigpotter (6 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![lloricode](https://avatars.githubusercontent.com/u/8251344?v=4)](https://github.com/lloricode "lloricode (1 commits)")[![niladam](https://avatars.githubusercontent.com/u/4151765?v=4)](https://github.com/niladam "niladam (1 commits)")

---

Tags

httplaravelloggingsaloonsaloonphpbarstool

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/saloonphp-barstool/health.svg)

```
[![Health](https://phpackages.com/badges/saloonphp-barstool/health.svg)](https://phpackages.com/packages/saloonphp-barstool)
```

###  Alternatives

[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3915.5k](/packages/rawilk-profile-filament-plugin)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

46273.9k](/packages/harris21-laravel-fuse)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

25060.1k](/packages/vormkracht10-laravel-mails)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
