PHPackages                             vulpecula-io/laravel-datum - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. vulpecula-io/laravel-datum

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

vulpecula-io/laravel-datum
==========================

Datum records different data and aggregations for use on Dashboards

v0.4.0(1y ago)0809[5 PRs](https://github.com/vulpecula-io/laravel-datum/pulls)MITPHPPHP ^8.1CI passing

Since Oct 30Pushed 1w ago1 watchersCompare

[ Source](https://github.com/vulpecula-io/laravel-datum)[ Packagist](https://packagist.org/packages/vulpecula-io/laravel-datum)[ Docs](https://github.com/vulpecula-io/laravel-datum)[ GitHub Sponsors](https://github.com/vulpecula-io)[ RSS](/packages/vulpecula-io-laravel-datum/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (9)Dependencies (22)Versions (18)Used By (0)

Datum recording data and aggregations for dashboards
====================================================

[](#datum-recording-data-and-aggregations-for-dashboards)

[![Latest Version on Packagist](https://camo.githubusercontent.com/1b4b49629d95947c4ccb81fd454129f15ec0d2726ae494976178d242cb5a582f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f76756c706563756c612d696f2f6c61726176656c2d646174756d2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vulpecula-io/laravel-datum)[![GitHub Tests Action Status](https://camo.githubusercontent.com/ce84b04b39b93536b2a5c24d91e304e13321e6431d9e9f7fab96bf0f06540284/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f76756c706563756c612d696f2f6c61726176656c2d646174756d2f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/vulpecula-io/laravel-datum/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/1a90cf995664313cc29e8a6f3eff0bb6f3110a30dea88cdc45d0f96eea3e2e85/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f76756c706563756c612d696f2f6c61726176656c2d646174756d2f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/vulpecula-io/laravel-datum/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/b761d381180416549d390f1f807710ba74b43c26c47816ad8c77705d31668a95/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f76756c706563756c612d696f2f6c61726176656c2d646174756d2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vulpecula-io/laravel-datum)

This leans heavily on the [Laravel Pulse](https://pulse.laravel.com) package for the general idea of how to obtain and process the data, but it's reworked to provide alternative and longer periods and be frontend agnostic. There is no interface built in - that's for you to do and put together, but the base functionality of aggregating data and pulling the data is there for you to use.

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

[](#installation)

You can install the package via composer:

```
composer require vulpecula-io/laravel-datum
```

You can publish and run the migrations with:

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

You can publish the config file with:

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

This is the contents of the published config file:

```
return [

    /*
    |--------------------------------------------------------------------------
    | Datum Master Switch
    |--------------------------------------------------------------------------
    |
    | This configuration option may be used to completely disable all Datum
    | data recorders regardless of their individual configurations. This
    | provides a single option to quickly disable all Datum recording.
    |
    */

    'enabled' => env('DATUM_ENABLED', true),

    /*
    |--------------------------------------------------------------------------
    | Datum Storage Driver
    |--------------------------------------------------------------------------
    |
    | This configuration option determines which storage driver will be used
    | while storing entries from Datum's recorders. In addition, you also
    | may provide any options to configure the selected storage driver.
    |
    */

    'storage' => [
        'driver' => env('DATUM_STORAGE_DRIVER', 'database'),

        'database' => [
            'connection' => env('DATUM_DB_CONNECTION', 'tenant'),
            'chunk' => 1000,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Datum Ingest Driver
    |--------------------------------------------------------------------------
    |
    | This configuration options determines the ingest driver that will be used
    | to capture entries from Datum's recorders. Ingest drivers are great to
    | free up your request workers quickly by offloading the data storage.
    |
    */

    'ingest' => [
        'driver' => env('DATUM_INGEST_DRIVER', 'storage'),

        'buffer' => env('DATUM_INGEST_BUFFER', 5000),

        'trim' => [
            'lottery' => [1, 1_000],
            'keep' => '365 days',
        ],

        'redis' => [
            'connection' => env('DATUM_REDIS_CONNECTION'),
            'chunk' => 1000,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Datum Cache Driver
    |--------------------------------------------------------------------------
    |
    | This configuration option determines the cache driver that will be used
    | for various tasks, including caching dashboard results, establishing
    | locks for events that should only occur on one server and signals.
    |
    */

    'cache' => env('DATUM_CACHE_DRIVER'),

    /*
    |--------------------------------------------------------------------------
    | Datum Recorders
    |--------------------------------------------------------------------------
    |
    | The following array lists the "recorders" that will be registered with
    | Datum, along with their configuration. Recorders gather application
    | event data from requests and tasks to pass to your ingest driver.
    |
    */

    'recorders' => [
        //        Recorders\ExampleRecord::class => [
        //            'enabled' => env('YOUR_RECORDER_ENABLED', true),
        //            'sample_rate' => env('DATUM_USER_REQUESTS_SAMPLE_RATE', 1),
        //            'ignore' => [
        //                '#^/datum$#', // Datum dashboard...
        //                '#^/telescope#', // Telescope dashboard...
        //            ],
        //        ],
    ],
];
```

Recorders
---------

[](#recorders)

Just as in Laravel Pulse, you need to create your own custom recorders to handle the data 'acquisition'. You can review the code of Pulse to see some examples of how to write a custom recorder [here](https://github.com/laravel/pulse/tree/1.x/src/Recorders).

Note

It's important to remember that the recorder should only 'fired' when the data is not going to change or if it makes no difference that it appears multiple times in the data aggregators.

Tip

Example: if you're recording turnover based on an `Invoice` model you need to ensure that you fire the associated recorder only when the invoice is no longer going to be edited/changed, otherwise the turnover will be recorded multiple times and provide an incorrect value for any graphs/aggregators obtained later.

### Registering the recorder

[](#registering-the-recorder)

Once you have a custom recorder you need to add it to the `recorders` array in the config file. The key is the class name of the recorder and the value is an array of configuration options. The only required option is `enabled` which is a boolean value to determine if the recorder should be used or not. The other options are optional and are passed to the recorder's constructor.

Like the standard recorders of Laravel Pulse you can pass a `sample_rate` or an array of items to `ignore`. The `sample_rate` is a number between 0 and 1 that determines the percentage of requests that should be recorded. The `ignore` option is an array of regular expressions that will be matched. If the item matches any of the regular expressions the recorder will not be used.

`Period` enum
-------------

[](#period-enum)

The `Period` enum is used to determine the intervals to use for the data. The enum is as follows:

- `Period::HOUR` - single hour interval split in 60 minute intervals
- `Period::SIXHOUR` - six hour interval split in 12 half hour intervals
- `Period::HALFDAY` - twelve hour interval split in 24 half hour intervals
- `Period::DAY` - single day interval split in 24 hour intervals
- `Period::WEEK` - standard weekly interval split in 7 day intervals
- `Period::MONTH` - standard monthly interval split in daily intervals (depending on the numnber of days in the month: `CarbonImmutable::now()->daysInMonth` is used)
- `Period::QUARTER` - standard quarterly interval split in `(int) CarbonImmutable::now()->daysInYear / 4` (~91 days) intervals
- `Period::HALFYEAR` - six-month interval split in 6-month intervals
- `Period::YEAR` - standard yearly interval split in 12-month intervals

If you want to use the `Period` enum in your own code you can import it with `use Vulpecula\Datum\Enums\Period;`. There is a `label()` function which will return the label for the enum value. For example `Period::HOUR->label()` will return `Hour`. There is a language file available that can be published using:

```
php artisan vendor:publish --tag="datum-lang"
```

Furthermore, you can get an array of all the `Period` enum values and their corresponding labels using the following:

```
array_map(
    fn(Period $period) => $period->label(),
    Period::cases()
);
```

This is useful if you want to provide a dropdown of the available periods for the user to select.

Getting the data out
--------------------

[](#getting-the-data-out)

Once the data is in the database you'll want to display it on the dashboard (or anywhere else you want to use it).

There are two primary functions available: `graph()` and `aggregate()`.

### `graph()`

[](#graph)

The `graph()` function will return a `Collection` of data that can be used to graph the data. The function takes 3 parameters:

- `array $types` - An array of the types of data you want to graph. The types are the `type` column of the datum tables and are set in the recorders.
- `string $aggregate` - The aggregate function to use. This can be any of the standard SQL aggregate functions: `count`, `sum`, `avg`, `min`, `max`.
- `Period $interval` - The interval to use for the data (see [above](#period-enum) for the available intervals).

```
$graphs = \Vulpecula\Datum\Facades\Datum::graph(['user_created', 'user_deleted'], 'count', Period::DAY);
```

This will return a `Collection` of objects one for `user_created` and one for `user_deleted`. Each object will be its own collection of objects with the `key` for each object the distinct `key`s in the database that have been recorded against the `types`. The value of the collection will be (in this example) an array of 24 elements with each having the timestamp of the start of the hour and the `count` of the number of records for that hour.

### `aggregate()`

[](#aggregate)

The `aggregate()` function will return a `Collection` of data that can be used to display the data in a table. The function requires 3 parameters:

- `string $type` - The type of data you want to aggregate. The type is the `type` column of the datum tables and is set in the recorders.
- `array|string $aggregates` - The aggregate function(s) to use. This can be any of the standard SQL aggregate functions: `count`, `sum`, `avg`, `min`, `max`. If you want to use multiple aggregate functions you can pass an array of the functions.
- `Period $interval` - The interval to use for the data (see [above](#period-enum) for the available intervals).

Optional parameters are:

- `?string $orderBy` - The column to order the results by. The default is `key`.
- `string $direction` - The direction to order the results by. The default is `desc`.
- `int $limit` - The number of results to return. The default is `101` which will return all results.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

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

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

[](#contributing)

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

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

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Richard Browne](https://github.com/rabrowne85)
- [All Contributors](../../contributors)

License
-------

[](#license)

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

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance74

Regular maintenance activity

Popularity13

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 77.6% 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 ~18 days

Recently: every ~36 days

Total

9

Last Release

458d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/70c5b43f72ae4a8827a8a7fe719e133b89cddadc48f95345ccd5902e127387de?d=identicon)[rabrowne85](/maintainers/rabrowne85)

---

Top Contributors

[![rabrowne85](https://avatars.githubusercontent.com/u/8293543?v=4)](https://github.com/rabrowne85 "rabrowne85 (59 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (9 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (8 commits)")

---

Tags

laravelvulpecula-ioVulpecula Limitedlaravel-datum

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/vulpecula-io-laravel-datum/health.svg)

```
[![Health](https://phpackages.com/badges/vulpecula-io-laravel-datum/health.svg)](https://phpackages.com/packages/vulpecula-io-laravel-datum)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k14.1M122](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9742.3M121](/packages/roots-acorn)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[spatie/laravel-responsecache

Speed up a Laravel application by caching the entire response

2.8k8.7M64](/packages/spatie-laravel-responsecache)[flarum/core

Delightfully simple forum software.

201.4M2.2k](/packages/flarum-core)

PHPackages © 2026

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