Agora
Integrations

Telescope

mediaTelescopeExtension — a first-class @adonis-agora/telescope extension that adds a "Media" overview dashboard (uploads, storage operations, image conversions) built from the agora:media:* diagnostics events. Telescope stays an optional, never-imported peer.

@adonis-agora/media already publishes agora:media:* lifecycle events onto the diagnostics bus (see Configuration → Diagnostics). When Telescope is installed, its generic diagnostics watcher records those events automatically — so you get media entries with zero wiring. mediaTelescopeExtension goes one step further: it contributes a dedicated "Media" overview dashboard built from those recorded events.

Telescope is an optional, never-imported peer (>=0.4.0 <1.0.0 — every 0.x from 0.4 on). The extension object structurally (not nominally) satisfies Telescope's TelescopeExtension contract, so @adonis-agora/media never depends on @adonis-agora/telescope — installed or not, the media library behaves identically.


Wire it up

Import the extension from the ./telescope subpath and add it to config/telescope.ts:

config/telescope.ts
import { defineConfig } from '@adonis-agora/telescope'
import { mediaTelescopeExtension } from '@adonis-agora/media/telescope'

export default defineConfig({
  extensions: [mediaTelescopeExtension()],
})

That's it — no changes to config/media.ts. As long as emitDiagnostics is on (the default), media operations flow onto the bus, Telescope's generic watcher records them as type: 'diagnostic', tag: 'lib:media', and the dashboard's panels read those recorded entries.


What the dashboard shows

mediaTelescopeExtension() registers a "Media" dashboard and the data providers its panels bind to, sourced from the media diagnostics events (attach, delete, conversion, attachment.*, and the upload.* lifecycle):

  • Active resumable uploads
  • Upload success rate and throughput
  • Uploads over time
  • Recent uploads
  • Storage operations over time
  • Attachment activity
  • Conversions over time
  • Recent conversions

The extension contributes no watcher and no dedicated media entry type. Media events are recorded under the generic diagnostic entry type (tag: 'lib:media'), so the "Media" dashboard is the entry point rather than a separate navigable entry list. (Same design as @adonis-agora/durable/telescope.)

mediaTelescopeExtension(opts) accepts the dashboard options (MediaDashboardOptions) if you need to tune it; the default (mediaTelescopeExtension()) is the common case.


MediaWatcher — richer entries, wired by hand

A watcher does exist, exported as MediaWatcher from the same subpath. It is not part of the extension above, because the AdonisJS Telescope SDK's TelescopeExtension contract doesn't accept watchers — its watchers are core and emitter-based. So it is offered for standalone wiring by a host that wants more than the generic bridge gives it.

import { MediaWatcher } from '@adonis-agora/media/telescope'

const watcher = new MediaWatcher()
watcher.register({ store: telescopeStore }) // your Telescope store
// …later
watcher.dispose()

What it buys you over the generic diagnostics watcher: a per-operation entry of type: 'media', with the event's payload flattened into structured content rather than stored as a raw envelope — so an upload entry carries its disk, key, mode and size as fields you can read, not as a nested blob.

Three details make it safe to run alongside everything else:

  • No double-recording. register() claims each channel it records through the reference-counted Symbol.for('@agora/diagnostics:claims') registry, and the generic DiagnosticsWatcher skips claimed channels by default. dispose() releases the claim and detaches every subscription. That skip is honoured from @adonis-agora/telescope 0.6.0 onward; on 0.4.x/0.5.x the generic watcher predates the claim registry, so running both records each event twice. The overview dashboard is unaffected either way — it reads the generic entries, and this watcher is opt-in.
  • upload.progress is deliberately excluded — neither recorded nor claimed. A per-chunk event would flood the timeline; it stays available on its channel for programmatic subscribers.
  • Still zero coupling. It subscribes to the same node:diagnostics_channel channels media publishes on. Neither @adonis-agora/telescope nor @adonis-agora/diagnostics is imported.

Next steps

On this page