Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Statamic Telemetry Laravel Package

cboxdk/statamic-telemetry

A Statamic addon that brings lightweight telemetry to your site, capturing usage and performance data you can review from the control panel. Laravel-native, configurable, and quick to install via Composer for insight into how your site and content are used.

View on GitHub
Deep Wiki
Context7

Getting Started

The 3.0 unit change is still the foundation of this assessment, but 3.1.0 gives you the first genuinely new capability since the upgrade: a content audit log. Treat them as two separate pieces of work with two separate verification steps.

composer require cboxdk/laravel-telemetry:^3.0
composer require <vendor>/<statamic-telemetry-package>:^3.1
composer require cboxdk/laravel-telemetry-ui:^3.1   # only if you want the Content screen

The dependency guard rail from 3.0 is unchanged: running the addon against a 2.x laravel-telemetry fails resolution, and that failure is intentional. Read the constraint error before reaching for --with-all-dependencies.

Where to look first, in order:

  1. The audit config and its off switch. Confirm STATAMIC_TELEMETRY_CONTENT_AUDIT is not false and decide deliberately whether audit.actor_name is on. These two values define what your compliance story can answer later.
  2. The statamic.stache.warm_duration bucket definition. 3.1 replaces the inherited telemetry.default_buckets with its own 0.05 s – 300 s bounds. If you published config before 3.0, you still carry millisecond buckets (1 … 10000), which is exactly the bug this release fixes — but only if you are not overriding it locally.
  3. The recorder binding in the service provider, still, to confirm you are on the 3.x implementation and therefore emitting seconds.
  4. The statamic.content.change span, whose statamic.content.action attribute now carries the semantic action (created, updated, …) rather than the counter's label. Anyone parsing that attribute needs to know before they see the new values.

First use case: make one content change and follow it end to end.

# In the CP: edit an entry title, save, then publish it.
# Then look for exactly one statamic.content.change event per save in your logs backend.

You should see the item identity (id, title, handle, collection, site, URL, CP edit link), action: updated, the changed field handles (never their values), user.id and user.name, and source: cp. Then warm the Stache and confirm the warm duration lands somewhere sensible inside the new buckets rather than pinned to the first one.

Implementation Patterns

Treat the audit log as an event stream, not a table. It lives in the logs backend, one statamic.content.change record per save. That shapes everything: retention is your logging retention, queries are log queries, and joins back to current content are on id + collection/handle rather than foreign keys. Snapshot semantics are the point — the title recorded is the title at the time of the save — so build "what did this look like then" views from the record, not from the live entry.

Use source to separate humans from automation. cp, api, web, console plus the command name is the single most useful dimension in the record. Filter source: cp for editorial activity reporting, filter source: console out of anything that should reflect people, and alert on unexpected api volume. Without this filter, a nightly import makes your "editors are busy" dashboard meaningless.

Keep the counter, change the span consumer. statamic.content.changes is unchanged — dashboards and alerts on it keep working, and you should not touch them as part of this upgrade. The span attribute statamic.content.action did change semantics. Grep your tracing config, your span-to-metric rules, and any saved trace queries for statamic.content.action and update the value mapping in the same deploy.

Do not build a rollback or value-diff feature on this. The audit log deliberately records field handles and never values. If a stakeholder reads "audit log" and asks for "show me the old value", the answer is that revisions already do that job; this is a who/what/when trail, and the separation is a feature.

Sites are a special case with two shapes. A sites save from the CP is snapshotted at form submission and produces one row per site that actually changed, naming the keys (name, url, locale, …). A sites save from code produces a single saved row with no key-level detail. Any dashboard counting rows by action will show fan-out on CP sites saves and should be read accordingly. Do not build key-level alerting that assumes it works from code paths.

Beware of net-zero volume changes. Two effects land in the same deploy: *Created events are now listened to (so creations finally appear as created rows, adding volume), and entries saved only as a side effect of another (localisations) no longer produce a row (removing volume). On a multi-site install these can roughly cancel out. Compare per-collection and per-source counts, not the global total, or you will conclude nothing changed.

Dashboards before deploy, still. The 3.1 rollout has one additional graph hazard: the first window after deploying reads pre-existing bucket counts against the new bounds. Order it as: deploy → verify a known warm reads correctly in the new buckets → annotate the deploy → ignore or discard the transitional histogram window before quoting percentiles. Anyone who screenshots histogram_quantile in the first hour will get a number that is neither the old nor the new truth.

Test the fan-out, not just the happy path. If the recorder is swappable, assert: a creation produces exactly one created row; a localisation side-effect save produces none; a CP sites save produces one row per changed site; a code sites save produces one saved row. Those four assertions encode the behaviours most likely to silently regress.

Access control is part of the design. The records surface in laravel-telemetry-ui under Statamic → Content, so anyone with access to that screen sees organisation-wide editing activity. Decide who that is before you enable it, not after someone notices.

Gotchas and Tips

The nav fix may collide with your workaround. The "Telemetry" CP nav item was broken for everyone on laravel-telemetry-ui 2.x+, because it looked for the 1.x route name telemetry-ui.page while 2.x serves telemetry-ui.spa. If you patched around that with a custom nav registration, remove it — otherwise you get two entries pointing at the same place.

statamic.content.action is the quiet breaking change. It used to be the counter's label; it is now what the save did. Nothing throws, nothing logs. Any grouping, filtering, or alert keyed on the old values silently re-partitions into empty or unexpected buckets. This is the same class of failure as the 3.0 unit change: correct data, wrong meaning, no runtime signal.

The bucket fix arrives with a one-window lie. Old millisecond buckets put every warm in the first bucket or two and made percentiles meaningless — you may have ignored that graph for two releases. When the new bounds land, the transition window mixes old counts with new bounds. It settles on its own, as the notes say; do not tune anything against the first window.

Audit rows are bounded by log retention. Anything you promise about "who changed this six months ago" depends on your logs backend, which is usually the shortest-retention store in the stack. Check retention before the first request from legal or support.

Turning the audit off is a per-environment decision with a history gap. STATAMIC_TELEMETRY_CONTENT_AUDIT=false is the right answer for noisy or regulated environments, but the window where it was off is a hole that cannot be backfilled. Same for audit.actor_name: once off, the name is absent from future records, and that is not retroactively fixable.

The email is deliberately absent. Records carry user.id and optionally user.name, never the email. Do not plan an enrichment step that expects to find it downstream; join on user.id at read time instead, and accept that deleted users leave an id with no lookup.

Multi-site makes audit counts look erratic. Row-per-changed-site, no row for localisation side-effect saves, and a single generic row for code-driven site saves all coexist. Per-site counts are meaningful; global row totals are not.

Cold cache after deploy is still not a regression. Now that warm durations render inside 0.05 s – 300 s buckets, the post-restart warm is easier to see and easier to over-react to. Compare like-for-like warm runs.

Nothing about the 3.0 unit invariant has changed. All durations in this package are seconds. Keep that line in the runbook, keep mixed 2.x/3.x emitters out of a shared collector, and keep annotating deploys on the dashboard — the audit-log release adds another step change to the graph for the next reader to puzzle over.

Extension points worth knowing. The configurable recorder and the hook around the warm operation remain the clean places to add your own dimensions (cache store, site, environment). For the audit log, prefer enriching at the logs-backend or UI layer rather than wrapping the recorder — the record schema is the package's contract and is more likely to move than the metric names are.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib