Allow full, anonymized, or disabled IP recording per server through the UI
and API, and pass the selected mode to Sentinel. Adapt traffic breakdowns
to the effective IP mode, including views that aggregate multiple servers.
Every released Sentinel with traffic analytics (1.0.0 and later) has
the dashboard and series routes and the requests, bytes_in and app
fields, so the fallbacks for builds without them are not needed.
- Keep "no data" handling for Sentinel without traffic routes (0.0.x)
- Keep the resource-scope fallback, which Sentinel 1.0.1 needs
Allow validated host file and directory mounts outside resource directories
while protecting external paths from deletion.
Clean up cancelled deployment containers and clear tracked process IDs.
Preserve legacy KeyDB and Dragonfly password parsing, accept server backup
paths without extension restrictions, and allow Compose variable proxy ports.
- Align the traffic window to the minute so the 60 s cache is used.
- Skip only an unsafe key instead of hiding the whole server.
- Look up unknown container owners in one query per push.
A resource with several traffic keys (Compose services, previews) was
queried key by key, and unique visitors were summed, so one visitor
on two keys counted twice. When Sentinel has the new
/api/resource/{uuid}/traffic routes, Coolify now asks once per
resource and gets merged unique visitors and latency percentiles; the
"approximate" badges go away for a resource on one server. Older
Sentinel versions answer 404: Coolify remembers this for 5 minutes and
uses the per-key merge as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Traffic analytics now covers every resource on both proxies:
- Caddy: Compose applications and services get access-log labels. The
log_append key is {uuid}-{service}, the same key Sentinel reads from
Traefik router names.
- A resource owns the Sentinel key {uuid} and every key that starts
with {uuid}-. Application pages and the traffic card now merge all
keys, so Compose applications and previews show data on Traefik too.
- Global analytics: the leaderboard groups the keys of one resource
into one row, lists services, and never names keys of other teams.
- New service analytics page (project.service.analytics) with the same
view and authorization as the application page.
- Switching the proxy type restarts Sentinel when analytics is on, so
it reads the new log path. Sentinel gets no traffic mount when the
proxy has no analytics support.
- Caddy servers show a note that resources log only after a redeploy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a per-server Analytics page scoped to that host, move traffic
settings out of Sentinel, and put metrics settings on Charts.
Surface 4xx/5xx on path rows and restyle deployment logs.
Pass series bucket timestamps to sparkline payloads so charts align with the selected range. Show loading overlays on analytics filters and range tabs, restyle the analytics header, and replace Sentinel custom-image autosave with an Apply and restart button so the unsaved bar no longer flashes.
- Dispatch the chart refresh event even when loadData() finds no
overviews, so a wire:ignore'd chart flips to its no-data state
instead of keeping stale data.
- Cache dashboard-route absence for 60s in SentinelTrafficClient so
older Sentinel installs that 404 the dashboard endpoint aren't
re-probed over SSH on every refresh within the same window.
- Make Pest's loadLazy() throw when no __lazyLoad trigger is found
instead of silently testing the un-mounted placeholder.
- Mark Analytics, Dashboard\TrafficAnalytics and Project\Application\Analytics
Livewire components #[Lazy] with skeleton placeholder() views so pages render
instantly while Sentinel data loads in a deferred request
- Add SentinelTrafficClient::prefetchServerWide() to warm all server-wide
endpoints in a single batched docker exec instead of ~14-15 serial SSH
round-trips, and refactor overview/paths/breakdown URL building into shared
helpers
- Cap per-app leaderboard overviews fetched via MAX_LEADERBOARD_APPS to bound
requests on servers with many apps
- Add hasRequestSeries() to detect empty request charts and render a no-data
state instead of a blank chart
- Gate ServerSetting's automatic Sentinel restart on is_sentinel_enabled so
tuning geoip/traffic settings no longer silently enables Sentinel
- Add reusable skeleton UI components (skeleton, skeleton/table, skeleton/tiles)
for the new placeholder views
Replace the stacked status-over-time chart with a single requests
area series and a separate status-codes breakdown. Add p95 latency
sparklines to KPI cards, wire requests/latency into chart payloads,
and hide live refresh outside the 24h range.
Extend TrafficSeriesBucketData with requests, bytesIn, bytesOut,
uniqueVisitors, and p95 fields, and aggregate them per bucket in the
global, dashboard, and application analytics Livewire components.
Add bandwidthSpark() and uniquesSpark() to BuildsTrafficChartPayload
and wire them into the chart payloads and blade views.
Also add a compactNumber() helper for dense metric columns, a
--chart-spark-bandwidth CSS variable, and improve the traffic globe
with focus/resume controls, shortest-path angle interpolation, and
brighter base/marker theme colors.
Swap the static world-map partial for a cobe-based 3D globe
(traffic-globe.js) driven by per-country marker data. Extract shared
sparkline/device/geo derivations into BuildsTrafficChartPayload and
reuse it across global, dashboard, and per-application analytics
components. Add device-donut, hosts-list, and sparkline partials, and
extend breakdown dimensions with protocol/cache/status. Default live
refresh to off until manually armed.
Replace the server-scoped Analytics Livewire component with an
app-wide one that filters by server/application and supports live
refresh. Add a per-bucket status-class time series endpoint/data
class for a stacked-area chart, falling back to the donut when the
Sentinel build doesn't support it. Decorate top-path rows with their
owning domain, expand breakdown dimensions to agent/ip/useragent, and
raise path/breakdown result limits. Capture X-Forwarded-For,
User-Agent, and Referer headers in traefik access logs (now enabled
in dev too) so IP, browser, and referrer breakdowns work. Add
flag-image and referer-host helpers for geo/referrer rendering.