PHPackages                             thekiharani/laravel-cwl - 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. [Logging &amp; Monitoring](/categories/logging)
4. /
5. thekiharani/laravel-cwl

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

thekiharani/laravel-cwl
=======================

AWS CloudWatch log driver for Laravel. Drop-in replacement — just switch LOG\_CHANNEL=cloudwatch.

v0.1.4(3mo ago)1181↓81.8%MITPHPPHP ^8.2CI passing

Since Apr 1Pushed 3mo agoCompare

[ Source](https://github.com/thekiharani/laravel-cwl)[ Packagist](https://packagist.org/packages/thekiharani/laravel-cwl)[ RSS](/packages/thekiharani-laravel-cwl/feed)WikiDiscussions main Synced 4w ago

READMEChangelog (2)Dependencies (6)Versions (8)Used By (0)

Laravel CWL
===========

[](#laravel-cwl)

AWS CloudWatch Logs driver for Laravel. Drop-in replacement — just switch your log channel.

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

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13
- An AWS account with CloudWatch Logs access

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

[](#installation)

```
composer require thekiharani/laravel-cwl
```

The service provider is auto-discovered. Publish the config file:

```
php artisan vendor:publish --provider="NoriaLabs\CloudWatch\CloudWatchServiceProvider"
```

This creates `config/cloudwatch.php`.

Quick Start
-----------

[](#quick-start)

1. Add a `cloudwatch` channel to `config/logging.php`:

```
'channels' => [
    // ...

    'cloudwatch' => [
        'driver' => 'cloudwatch',
        'level'  => env('LOG_LEVEL', 'debug'),
    ],
],
```

2. Set your environment:

```
LOG_CHANNEL=cloudwatch
```

3. Use Laravel's logger as normal:

```
Log::info('Payment processed', ['amount' => 1000, 'currency' => 'KES']);
```

That's it. Logs go to CloudWatch.

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

[](#configuration)

All options are configured via environment variables with sensible defaults.

### AWS Credentials

[](#aws-credentials)

VariableDefaultDescription`AWS_ACCESS_KEY_ID``null`AWS access key`AWS_SECRET_ACCESS_KEY``null`AWS secret key`AWS_DEFAULT_REGION``us-east-1`AWS region for CloudWatchIf both key and secret are `null`, the SDK uses the [default credential provider chain](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html) — IAM roles (EC2/ECS/Lambda), environment variables, `~/.aws/credentials`, etc. This is the recommended approach for production.

### Log Group

[](#log-group)

VariableDefaultDescription`CLOUDWATCH_LOG_GROUP``APP_NAME` (or `laravel`)CloudWatch log group nameThe log group is auto-created on the first log event if it doesn't exist.

### Log Stream

[](#log-stream)

VariableDefaultDescription`CLOUDWATCH_LOG_STREAM``{app}-{env}`Stream name or templateThe stream name supports **dynamic placeholders** that are resolved at flush time (not at boot time):

PlaceholderResolves toExample`{app}``APP_NAME` config value`noria``{env}``APP_ENV` config value`production``{date}`Current date (`Y-m-d`)`2026-04-01``{hostname}`Machine hostname`web-01`**Examples:**

```
# Static stream (default)
CLOUDWATCH_LOG_STREAM="{app}-{env}"
# Result: noria-production

# Daily streams — each day gets its own stream automatically
CLOUDWATCH_LOG_STREAM="{app}-{env}-{date}"
# Result: noria-production-2026-04-01

# Per-host streams — useful for multi-server deploys
CLOUDWATCH_LOG_STREAM="{app}-{hostname}"
# Result: noria-web-01

# Combine all
CLOUDWATCH_LOG_STREAM="{app}-{env}-{hostname}-{date}"
# Result: noria-production-web-01-2026-04-01
```

**Long-running processes:** Placeholders are resolved every time the buffer is flushed, not once at startup. This means queue workers and schedulers will automatically create a new stream at midnight when using `{date}` — no restart required.

Log streams are auto-created on first use.

### Log Retention

[](#log-retention)

VariableDefaultDescription`CLOUDWATCH_LOG_RETENTION``30`Retention in days, or `null` for foreverThe retention policy is applied when the log group is created. Valid values: `1`, `3`, `5`, `7`, `14`, `30`, `60`, `90`, `120`, `150`, `180`, `365`, `400`, `545`, `731`, `1096`, `1827`, `2192`, `2557`, `2922`, `3288`, `3653`.

Set to `null` to retain logs indefinitely:

```
CLOUDWATCH_LOG_RETENTION=
```

### Batch Size

[](#batch-size)

VariableDefaultDescription`CLOUDWATCH_BATCH_SIZE``25`Events buffered before flushing to CloudWatchLogs are buffered in memory and sent in batches to reduce API calls. The buffer is always flushed on application shutdown, so no logs are lost.

- **Higher values** (50-100): fewer API calls, better throughput, slightly delayed delivery
- **Lower values** (1-5): near-real-time delivery, more API calls
- **Set to `1`**: every log is sent immediately (useful for debugging)

### Log Level

[](#log-level)

VariableDefaultDescription`CLOUDWATCH_LOG_LEVEL``debug`Minimum level to send to CloudWatchStandard Monolog/PSR-3 levels: `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`.

You can also override the level per-channel in `config/logging.php`:

```
'cloudwatch' => [
    'driver' => 'cloudwatch',
    'level'  => 'warning', // Only warnings and above
],
```

### Tags

[](#tags)

Tags are key-value pairs applied to the log group when it is created. Useful for cost allocation, filtering, and organization in the AWS console.

Configure in `config/cloudwatch.php`:

```
'tags' => [
    'team'    => 'backend',
    'project' => 'noria',
    'env'     => env('APP_ENV', 'production'),
],
```

Tags are only applied when the log group is first created. To update tags on an existing group, use the AWS console or CLI.

Usage Examples
--------------

[](#usage-examples)

### Basic logging

[](#basic-logging)

```
use Illuminate\Support\Facades\Log;

Log::info('User registered', ['user_id' => 42]);
Log::error('Payment failed', ['order_id' => 'ORD-123', 'reason' => 'insufficient_funds']);
Log::debug('Cache miss', ['key' => 'user:42:profile']);
```

### Stack driver

[](#stack-driver)

Send logs to multiple channels simultaneously:

```
// config/logging.php
'channels' => [
    'stack' => [
        'driver'   => 'stack',
        'channels' => ['single', 'cloudwatch'],
    ],
],
```

### Local development with fallback

[](#local-development-with-fallback)

Use CloudWatch in production, local file in development:

```
# .env (local)
LOG_CHANNEL=single

# .env (production)
LOG_CHANNEL=cloudwatch
```

### Multiple CloudWatch channels

[](#multiple-cloudwatch-channels)

Send different log types to different groups:

```
// config/logging.php
'channels' => [
    'cloudwatch' => [
        'driver' => 'cloudwatch',
        'level'  => 'info',
    ],

    'cloudwatch-errors' => [
        'driver' => 'cloudwatch',
        'level'  => 'error',
    ],
],
```

Override the group/stream per channel by setting different env vars or adjusting `config/cloudwatch.php`.

How It Works
------------

[](#how-it-works)

1. **Driver registration** — The service provider registers a `cloudwatch` driver with Laravel's log manager via Monolog.
2. **Buffering** — Log events are buffered in memory until the batch size is reached or the application shuts down.
3. **Stream resolution** — On each flush, the stream name template is resolved with current values (`{date}` = today). If the resolved name changed since the last flush, a new stream is created automatically.
4. **Auto-creation** — The log group and stream are created on first use. If they already exist, the `ResourceAlreadyExistsException` is silently ignored.
5. **Flushing** — Buffered events are sorted by timestamp and sent to CloudWatch via `putLogEvents`.
6. **Self-healing** — If the stream is deleted externally mid-run, the handler catches the `ResourceNotFoundException`, recreates the group/stream, and retries the flush.
7. **Shutdown** — Any remaining buffered logs are flushed on `close()` and `__destruct()`, so logs are never lost.

All log entries are JSON-formatted via Monolog's `JsonFormatter`.

IAM Permissions
---------------

[](#iam-permissions)

The AWS credentials you provide need the following permissions:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:PutRetentionPolicy"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:YOUR_LOG_GROUP:*"
        }
    ]
}
```

Replace `YOUR_LOG_GROUP` with your actual log group name, or use `*` for all groups.

If you set `retention` to `null`, you can omit `logs:PutRetentionPolicy`.

Full Configuration Reference
----------------------------

[](#full-configuration-reference)

```
# AWS (omit for IAM role)
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1

# CloudWatch
CLOUDWATCH_LOG_GROUP=my-app                    # Default: APP_NAME
CLOUDWATCH_LOG_STREAM={app}-{env}              # Default: {app}-{env}
CLOUDWATCH_LOG_RETENTION=30                    # Default: 30 (days, null = forever)
CLOUDWATCH_BATCH_SIZE=25                       # Default: 25
CLOUDWATCH_LOG_LEVEL=debug                     # Default: debug
```

```
// config/cloudwatch.php — tags (not env-configurable)
'tags' => [
    'team'    => 'backend',
    'project' => 'noria',
],
```

Testing
-------

[](#testing)

```
composer test
# or
./vendor/bin/pest
./vendor/bin/pest --coverage
```

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance82

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~0 days

Total

5

Last Release

91d ago

### Community

Maintainers

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

---

Top Contributors

[![thekiharani](https://avatars.githubusercontent.com/u/44342484?v=4)](https://github.com/thekiharani "thekiharani (10 commits)")

---

Tags

laravelloggingawsmonologcloudwatch

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/thekiharani-laravel-cwl/health.svg)

```
[![Health](https://phpackages.com/badges/thekiharani-laravel-cwl/health.svg)](https://phpackages.com/packages/thekiharani-laravel-cwl)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.0k](/packages/craftcms-cms)[maxbanton/cwh

AWS CloudWatch Handler for Monolog library

42516.0M35](/packages/maxbanton-cwh)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45444.2k1](/packages/pressbooks-pressbooks)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M179](/packages/laravel-ai)[illuminate/log

The Illuminate Log package.

6225.3M610](/packages/illuminate-log)[naoray/laravel-github-monolog

Log driver to store logs as github issues

10822.5k](/packages/naoray-laravel-github-monolog)

PHPackages © 2026

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