@mushinjs/plugin-stats 0.2.0-next.20261112165327 → 0.2.0-next.20261113103537
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Setobox
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Setobox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { readdir, stat } from 'node:fs/promises'\r\nimport { createRequire } from 'node:module'\r\nimport { join } from 'node:path'\r\nimport { monitorEventLoopDelay } from 'node:perf_hooks'\r\nimport { Context, Service, z } from '@mushinjs/core'\r\nimport { isSandbox } from '@mushinjs/plugin-bots'\r\nimport type {} from '@mushinjs/plugin-flows'\r\nimport type {} from '@mushinjs/plugin-providers'\r\nimport type {} from '@mushinjs/plugin-storage'\r\nimport {\r\n bump, compact, type Counters, type DayDoc, dayHour, dayStart, type Dimension, emptyCounters, merge, type Metric, metricValues, sum, top,\r\n} from './counters'\r\n\r\nexport * from './counters'\r\n\r\ndeclare module '@mushinjs/core' {\r\n interface Context {\r\n stats: StatsService\r\n }\r\n\r\n interface Events {\r\n 'stats/sample'(sample: PerfSample): void\r\n }\r\n}\r\n\r\n/** Process load at one moment: CPU in percent of one core, memory in bytes, event loop delay in ms. */\r\nexport interface PerfSample {\r\n t: number\r\n cpu: number\r\n rss: number\r\n heapUsed: number\r\n heapTotal: number\r\n loopMean: number\r\n loopMax: number\r\n}\r\n\r\nconst HOUR = 3_600_000\r\nconst DAY = 24 * HOUR\r\n/** One sample every 5 seconds, an hour of them kept. */\r\nconst SAMPLE_EVERY = 5_000\r\nconst SAMPLE_LIMIT = 720\r\nconst FLUSH_EVERY = 30_000\r\n/** Hourly buckets are kept this many days, then folded into one bucket per day. */\r\nconst HOURLY_DAYS = 30\r\n/** Daily totals are kept this many days. */\r\nconst DAILY_DAYS = 365\r\nconst DATA_SIZE_TTL = 60_000\r\n/** The event loop histogram measures timer ticks of this many ms; the delay is what goes beyond it. */\r\nconst LOOP_RESOLUTION = 10\r\nconst lag = (ns: number) => Math.max(0, Math.round((ns / 1e6 - LOOP_RESOLUTION) * 100) / 100)\r\n\r\nconst require = createRequire(import.meta.url)\r\nconst versionOf = (name: string) => {\r\n try {\r\n return (require(`${name}/package.json`) as { version: string }).version\r\n } catch {}\r\n}\r\n\r\nconst METRICS = ['messages', 'received', 'sent', 'commands', 'flows', 'llmCalls', 'llmTokens'] as const satisfies Metric[]\r\nconst DIMENSIONS = ['channels', 'users', 'commands', 'flows', 'llm'] as const satisfies Dimension[]\r\n\r\nasync function directorySize(dir: string): Promise<number> {\r\n let total = 0\r\n for (const entry of await readdir(dir, { withFileTypes: true }).catch(() => [])) {\r\n const path = join(dir, entry.name)\r\n if (entry.isDirectory()) total += await directorySize(path)\r\n else if (entry.isFile()) total += (await stat(path).catch(() => undefined))?.size ?? 0\r\n }\r\n return total\r\n}\r\n\r\n/**\r\n * Counts messages, commands, flow runs and model requests per hour, stored as one document per\r\n * day under `stats/`, and samples the process's CPU, memory and event loop for the overview page.\r\n */\r\nexport class StatsService extends Service {\r\n static inject = ['storage', 'actions']\r\n\r\n private home: Context\r\n private days = new Map<string, DayDoc>()\r\n private dirty = new Set<string>()\r\n private samples: PerfSample[] = []\r\n private dataSize?: { at: number; bytes: number }\r\n private startedAt = Date.now()\r\n\r\n constructor(ctx: Context) {\r\n super(ctx, 'stats')\r\n this.home = ctx\r\n }\r\n\r\n async *[Service.init]() {\r\n const [today] = dayHour(Date.now())\r\n await this.prune(today)\r\n yield this.home.on('bots/message', (record) => !isSandbox(record.channel) && this.count(record.timestamp, (counters, doc) => {\r\n if (record.direction === 'out') return bump(counters.out, record.botId)\r\n bump(counters.in, record.botId)\r\n const channel = `${record.botId}|${record.channel.type}:${record.channel.id}`\r\n const user = `${record.botId}|${record.user.id}`\r\n bump(counters.channels, channel)\r\n bump(counters.users, user)\r\n if (record.channel.name) doc.names[channel] = record.channel.name\r\n if (record.user.name) doc.names[user] = record.user.name\r\n }))\r\n yield this.home.on('bots/command', (call) => this.count(call.at, (counters) => bump(counters.commands, `${call.botId}|${call.name}`)))\r\n yield this.home.on('flows/run', (trace) => {\r\n if (trace.test) return\r\n this.count(trace.at, (counters, doc) => {\r\n bump(counters.flows, trace.flowId)\r\n if (trace.error) bump(counters.flowErrors, trace.flowId)\r\n const name = this.home.get('flows')?.list().find((flow) => flow.id === trace.flowId)?.name\r\n if (name) doc.names[`flow:${trace.flowId}`] = name\r\n })\r\n })\r\n yield this.home.on('llm/called', (call) => this.count(Date.now(), (counters) => {\r\n const usage = counters.llm[`${call.providerName}|${call.model}`] ??= { calls: 0, errors: 0, tokens: 0 }\r\n usage.calls++\r\n if (!call.ok) usage.errors++\r\n usage.tokens += (call.inputTokens ?? 0) + (call.outputTokens ?? 0)\r\n }))\r\n yield this.home.effect(() => {\r\n const timer = setInterval(() => {\r\n const [day] = dayHour(Date.now())\r\n this.flush().then(() => this.prune(day)).catch((error) => this.home.logger('stats').warn('saving statistics failed: %s', error))\r\n }, FLUSH_EVERY)\r\n return () => {\r\n clearInterval(timer)\r\n return this.flush()\r\n }\r\n }, 'stats flush')\r\n yield this.home.effect(() => this.sampler(), 'stats sampler')\r\n yield* this.defineActions()\r\n }\r\n\r\n // ---- counting ----\r\n\r\n private async load(day: string) {\r\n let doc = this.days.get(day)\r\n if (!doc) {\r\n const stored = await this.home.storage.get<DayDoc>(`stats/${day}`)\r\n // Counting may have started on this day while it was being read.\r\n doc = this.days.get(day) ?? { day, hours: stored?.hours ?? {}, names: stored?.names ?? {} }\r\n this.days.set(day, doc)\r\n }\r\n return doc\r\n }\r\n\r\n /** Adds to the bucket of the hour `time` falls in. */\r\n private count(time: number, update: (counters: Counters, doc: DayDoc) => void) {\r\n const [day, hour] = dayHour(time)\r\n const apply = (doc: DayDoc) => {\r\n update(doc.hours[hour] ??= emptyCounters(), doc)\r\n this.dirty.add(day)\r\n }\r\n const cached = this.days.get(day)\r\n if (cached) apply(cached)\r\n else this.load(day).then(apply).catch(() => {})\r\n }\r\n\r\n /** Writes changed days; days other than today leave memory once written. */\r\n async flush() {\r\n const [today] = dayHour(Date.now())\r\n for (const day of [...this.dirty]) {\r\n this.dirty.delete(day)\r\n const doc = this.days.get(day)\r\n if (doc) await this.home.storage.set(`stats/${day}`, doc)\r\n }\r\n for (const day of this.days.keys()) if (day !== today && !this.dirty.has(day)) this.days.delete(day)\r\n }\r\n\r\n /** Folds days past the hourly retention into daily totals and deletes days past the daily one. */\r\n private async prune(today: string) {\r\n const now = dayStart(today)\r\n for (const key of await this.home.storage.list('stats')) {\r\n const day = key.slice('stats/'.length)\r\n const age = (now - dayStart(day)) / DAY\r\n if (!Number.isFinite(age) || age < HOURLY_DAYS) continue\r\n if (age >= DAILY_DAYS) {\r\n await this.home.storage.delete(key)\r\n continue\r\n }\r\n const doc = await this.home.storage.get<DayDoc>(key)\r\n if (doc && !doc.hours['*']) await this.home.storage.set(key, compact(doc))\r\n }\r\n }\r\n\r\n /** Days covering the last `hours` hours, oldest first. */\r\n private async daysFor(from: number, to: number) {\r\n const docs: DayDoc[] = []\r\n for (let time = dayStart(dayHour(from)[0]); time <= to; time += DAY) {\r\n // Daylight saving can make a day 23 or 25 hours long; take the day the time falls in.\r\n docs.push(await this.load(dayHour(time + 2 * HOUR)[0]))\r\n }\r\n return docs\r\n }\r\n\r\n /** Counters for whole hours in [from, to], one bucket each, plus the doc they came from. */\r\n private async buckets(from: number, to: number) {\r\n const result: { time: number; counters: Counters; doc: DayDoc }[] = []\r\n for (const doc of await this.daysFor(from, to)) {\r\n const start = dayStart(doc.day)\r\n for (const [hour, counters] of Object.entries(doc.hours)) {\r\n const time = hour === '*' ? start : start + Number(hour) * HOUR\r\n if (time + (hour === '*' ? DAY : HOUR) <= from || time > to) continue\r\n result.push({ time, counters, doc })\r\n }\r\n }\r\n return result\r\n }\r\n\r\n // ---- queries ----\r\n\r\n /** Totals since local midnight. */\r\n async today() {\r\n const now = Date.now()\r\n const total = emptyCounters()\r\n for (const { counters } of await this.buckets(dayStart(dayHour(now)[0]), now)) merge(total, counters)\r\n const llm = Object.values(total.llm)\r\n return {\r\n received: sum(total.in),\r\n sent: sum(total.out),\r\n commands: sum(total.commands),\r\n flowRuns: sum(total.flows),\r\n flowErrors: sum(total.flowErrors),\r\n llmCalls: llm.reduce((count, usage) => count + usage.calls, 0),\r\n llmTokens: llm.reduce((count, usage) => count + usage.tokens, 0),\r\n }\r\n }\r\n\r\n /**\r\n * A metric over the last `hours` hours, one point per hour or per day, split into series (by bot\r\n * for messages, by provider and model for model usage).\r\n */\r\n async series(input: { metric: Metric; hours: number; granularity?: 'hour' | 'day' }) {\r\n const granularity = input.granularity ?? (input.hours > 72 ? 'day' : 'hour')\r\n const now = Date.now()\r\n const step = granularity === 'day' ? DAY : HOUR\r\n const first = granularity === 'day'\r\n ? dayStart(dayHour(now - (Math.ceil(input.hours / 24) - 1) * DAY)[0])\r\n : Math.floor(now / HOUR) * HOUR - (input.hours - 1) * HOUR\r\n const slotOf = (time: number) => (granularity === 'day' ? dayStart(dayHour(time)[0]) : Math.floor(time / HOUR) * HOUR)\r\n const points = new Map<number, Record<string, number>>()\r\n for (let time = first; time <= now; time += step) points.set(slotOf(time + (granularity === 'day' ? 2 * HOUR : 0)), {})\r\n const keys = new Set<string>()\r\n for (const { time, counters } of await this.buckets(first, now)) {\r\n const values = points.get(slotOf(time))\r\n if (!values) continue\r\n for (const [key, value] of Object.entries(metricValues(counters, input.metric))) {\r\n keys.add(key)\r\n bump(values, key, value)\r\n }\r\n }\r\n const bots = this.home.get('bots')\r\n const nameOf = (key: string) => {\r\n if (input.metric === 'messages' || input.metric === 'received' || input.metric === 'sent') {\r\n return bots?.list().find((bot) => bot.id === key)?.name ?? key\r\n }\r\n return key === 'total' ? key : key.replace('|', ' · ')\r\n }\r\n return {\r\n granularity,\r\n series: [...keys].sort().map((key) => ({ key, name: nameOf(key) })),\r\n points: [...points].map(([t, values]) => ({ t, values })),\r\n }\r\n }\r\n\r\n /** The most active chats, people, commands, flows or models over the last `days` days. */\r\n async top(input: { dimension: Dimension; days: number; limit?: number }) {\r\n const now = Date.now()\r\n const from = dayStart(dayHour(now - (input.days - 1) * DAY)[0])\r\n const total = emptyCounters()\r\n const names: Record<string, string> = {}\r\n for (const { counters, doc } of await this.buckets(from, now)) {\r\n merge(total, counters)\r\n Object.assign(names, doc.names)\r\n }\r\n const bots = this.home.get('bots')\r\n const flows = this.home.get('flows')\r\n const botName = (id: string) => bots?.list().find((bot) => bot.id === id)?.name\r\n return top(total, input.dimension, input.limit ?? 10).map(([key, count]) => {\r\n if (input.dimension === 'flows') {\r\n return { key, name: flows?.list().find((flow) => flow.id === key)?.name ?? names[`flow:${key}`] ?? key, count, errors: total.flowErrors[key] ?? 0 }\r\n }\r\n if (input.dimension === 'llm') {\r\n const [provider, model] = key.split('|')\r\n return { key, name: `${provider} · ${model}`, count, tokens: total.llm[key].tokens, errors: total.llm[key].errors }\r\n }\r\n const [botId, rest] = [key.slice(0, key.indexOf('|')), key.slice(key.indexOf('|') + 1)]\r\n const name = input.dimension === 'commands' ? `/${rest}` : names[key] ?? rest.replace(/^(group|private):/, '')\r\n return { key, name, id: rest, botId, bot: botName(botId), count }\r\n })\r\n }\r\n\r\n /** The last hour of process samples, oldest first. */\r\n performance() {\r\n return this.samples\r\n }\r\n\r\n private sampler() {\r\n const histogram = monitorEventLoopDelay({ resolution: LOOP_RESOLUTION })\r\n histogram.enable()\r\n let cpu = process.cpuUsage()\r\n let at = performance.now()\r\n const timer = setInterval(() => {\r\n const nextCpu = process.cpuUsage()\r\n const nextAt = performance.now()\r\n const used = (nextCpu.user - cpu.user + nextCpu.system - cpu.system) / 1000\r\n const memory = process.memoryUsage()\r\n const sample: PerfSample = {\r\n t: Date.now(),\r\n cpu: Math.round((used / Math.max(1, nextAt - at)) * 1000) / 10,\r\n rss: memory.rss,\r\n heapUsed: memory.heapUsed,\r\n heapTotal: memory.heapTotal,\r\n loopMean: Number.isFinite(histogram.mean) ? lag(histogram.mean) : 0,\r\n loopMax: lag(histogram.max),\r\n }\r\n cpu = nextCpu\r\n at = nextAt\r\n histogram.reset()\r\n this.samples.push(sample)\r\n if (this.samples.length > SAMPLE_LIMIT) this.samples.splice(0, this.samples.length - SAMPLE_LIMIT)\r\n this.home.emit('stats/sample', sample)\r\n }, SAMPLE_EVERY)\r\n timer.unref?.()\r\n return () => {\r\n clearInterval(timer)\r\n histogram.disable()\r\n }\r\n }\r\n\r\n private async dataDirSize() {\r\n if (!this.dataSize || Date.now() - this.dataSize.at > DATA_SIZE_TTL) {\r\n this.dataSize = { at: Date.now(), bytes: await directorySize(this.home.storage.dir) }\r\n }\r\n return this.dataSize.bytes\r\n }\r\n\r\n /** Everything the overview's number cards and version panel show. */\r\n async overview() {\r\n const bots = this.home.get('bots')\r\n const flows = this.home.get('flows')\r\n const llm = this.home.get('llm')\r\n const manager = this.home.manager\r\n const botList = bots?.list() ?? []\r\n const flowList = flows?.list() ?? []\r\n const providers = llm?.list() ?? []\r\n const commands = new Set((bots?.commandList().commands ?? []).map((entry) => `${entry.botId}|${entry.name.toLowerCase()}`))\r\n const catalog = await manager.catalog().catch(() => [])\r\n const versions = new Map(catalog.map((entry) => [entry.package, entry.version]))\r\n return {\r\n bots: { online: botList.filter((bot) => bot.status === 'online').length, total: botList.length },\r\n appPlugins: { enabled: manager.entries.filter((entry) => entry.enabled !== false).length, total: manager.entries.length },\r\n botPlugins: { enabled: botList.reduce((count, bot) => count + bot.plugins.filter((plugin) => plugin.enabled).length, 0) },\r\n flows: { total: flowList.length, enabled: flowList.filter((flow) => flow.enabled).length, withErrors: flowList.filter((flow) => flow.errors > 0).length },\r\n commands: commands.size,\r\n providers: { total: providers.length, passed: providers.filter((provider) => provider.lastTest?.ok).length },\r\n today: await this.today(),\r\n versions: {\r\n mushin: versionOf('@mushinjs/core'),\r\n node: process.version,\r\n cordis: versionOf('cordis'),\r\n plugins: manager.entries.map((entry) => ({ package: entry.package, enabled: entry.enabled !== false, version: versions.get(entry.package) })),\r\n },\r\n platform: `${process.platform} ${process.arch}`,\r\n startedAt: this.startedAt,\r\n uptime: Math.round(process.uptime()),\r\n dataBytes: await this.dataDirSize(),\r\n sample: this.samples.at(-1),\r\n }\r\n }\r\n\r\n // ---- actions ----\r\n\r\n private *defineActions() {\r\n const actions = this.home.actions\r\n\r\n yield actions.define({\r\n name: 'stats.overview',\r\n description: 'Instance at a glance: bots online, plugins, flows (and how many have errors), commands, providers, today\\'s messages, commands, flow runs and model tokens, versions, uptime and data directory size.',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.overview(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'stats.series',\r\n description: 'A metric over time, one point per hour or day: messages (split by bot), received, sent, commands, flows (runs), llmCalls or llmTokens (split by provider and model).',\r\n risk: 'read',\r\n input: z.object({\r\n metric: z.enum(METRICS),\r\n hours: z.number().int().min(1).max(24 * 366).default(24).describe('How far back, e.g. 24 or 168 (7 days)'),\r\n granularity: z.enum(['hour', 'day']).optional().describe('Defaults to hour up to 3 days, day beyond'),\r\n }),\r\n handler: (input) => this.series(input),\r\n })\r\n\r\n yield actions.define({\r\n name: 'stats.top',\r\n description: 'The busiest chats, users, commands, flows or models (llm) over the last days, highest first.',\r\n risk: 'read',\r\n input: z.object({\r\n dimension: z.enum(DIMENSIONS),\r\n days: z.number().int().min(1).max(366).default(7),\r\n limit: z.number().int().min(1).max(50).optional(),\r\n }),\r\n handler: (input) => this.top(input),\r\n })\r\n\r\n yield actions.define({\r\n name: 'stats.performance',\r\n description: 'Process CPU (percent of one core), memory (bytes) and event loop delay (ms), one sample every 5 seconds for the last hour.',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.performance(),\r\n })\r\n }\r\n}\r\n\r\nexport default StatsService\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { readdir, stat } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { join } from 'node:path'\nimport { monitorEventLoopDelay } from 'node:perf_hooks'\nimport { Context, Service, z } from '@mushinjs/core'\nimport { isSandbox } from '@mushinjs/plugin-bots'\nimport type {} from '@mushinjs/plugin-flows'\nimport type {} from '@mushinjs/plugin-providers'\nimport type {} from '@mushinjs/plugin-storage'\nimport {\n bump, compact, type Counters, type DayDoc, dayHour, dayStart, type Dimension, emptyCounters, merge, type Metric, metricValues, sum, top,\n} from './counters'\n\nexport * from './counters'\n\ndeclare module '@mushinjs/core' {\n interface Context {\n stats: StatsService\n }\n\n interface Events {\n 'stats/sample'(sample: PerfSample): void\n }\n}\n\n/** Process load at one moment: CPU in percent of one core, memory in bytes, event loop delay in ms. */\nexport interface PerfSample {\n t: number\n cpu: number\n rss: number\n heapUsed: number\n heapTotal: number\n loopMean: number\n loopMax: number\n}\n\nconst HOUR = 3_600_000\nconst DAY = 24 * HOUR\n/** One sample every 5 seconds, an hour of them kept. */\nconst SAMPLE_EVERY = 5_000\nconst SAMPLE_LIMIT = 720\nconst FLUSH_EVERY = 30_000\n/** Hourly buckets are kept this many days, then folded into one bucket per day. */\nconst HOURLY_DAYS = 30\n/** Daily totals are kept this many days. */\nconst DAILY_DAYS = 365\nconst DATA_SIZE_TTL = 60_000\n/** The event loop histogram measures timer ticks of this many ms; the delay is what goes beyond it. */\nconst LOOP_RESOLUTION = 10\nconst lag = (ns: number) => Math.max(0, Math.round((ns / 1e6 - LOOP_RESOLUTION) * 100) / 100)\n\nconst require = createRequire(import.meta.url)\nconst versionOf = (name: string) => {\n try {\n return (require(`${name}/package.json`) as { version: string }).version\n } catch {}\n}\n\nconst METRICS = ['messages', 'received', 'sent', 'commands', 'flows', 'llmCalls', 'llmTokens'] as const satisfies Metric[]\nconst DIMENSIONS = ['channels', 'users', 'commands', 'flows', 'llm'] as const satisfies Dimension[]\n\nasync function directorySize(dir: string): Promise<number> {\n let total = 0\n for (const entry of await readdir(dir, { withFileTypes: true }).catch(() => [])) {\n const path = join(dir, entry.name)\n if (entry.isDirectory()) total += await directorySize(path)\n else if (entry.isFile()) total += (await stat(path).catch(() => undefined))?.size ?? 0\n }\n return total\n}\n\n/**\n * Counts messages, commands, flow runs and model requests per hour, stored as one document per\n * day under `stats/`, and samples the process's CPU, memory and event loop for the overview page.\n */\nexport class StatsService extends Service {\n static inject = ['storage', 'actions']\n\n private home: Context\n private days = new Map<string, DayDoc>()\n private dirty = new Set<string>()\n private samples: PerfSample[] = []\n private dataSize?: { at: number; bytes: number }\n private startedAt = Date.now()\n\n constructor(ctx: Context) {\n super(ctx, 'stats')\n this.home = ctx\n }\n\n async *[Service.init]() {\n const [today] = dayHour(Date.now())\n await this.prune(today)\n yield this.home.on('bots/message', (record) => !isSandbox(record.channel) && this.count(record.timestamp, (counters, doc) => {\n if (record.direction === 'out') return bump(counters.out, record.botId)\n bump(counters.in, record.botId)\n const channel = `${record.botId}|${record.channel.type}:${record.channel.id}`\n const user = `${record.botId}|${record.user.id}`\n bump(counters.channels, channel)\n bump(counters.users, user)\n if (record.channel.name) doc.names[channel] = record.channel.name\n if (record.user.name) doc.names[user] = record.user.name\n }))\n yield this.home.on('bots/command', (call) => this.count(call.at, (counters) => bump(counters.commands, `${call.botId}|${call.name}`)))\n yield this.home.on('flows/run', (trace) => {\n if (trace.test) return\n this.count(trace.at, (counters, doc) => {\n bump(counters.flows, trace.flowId)\n if (trace.error) bump(counters.flowErrors, trace.flowId)\n const name = this.home.get('flows')?.list().find((flow) => flow.id === trace.flowId)?.name\n if (name) doc.names[`flow:${trace.flowId}`] = name\n })\n })\n yield this.home.on('llm/called', (call) => this.count(Date.now(), (counters) => {\n const usage = counters.llm[`${call.providerName}|${call.model}`] ??= { calls: 0, errors: 0, tokens: 0 }\n usage.calls++\n if (!call.ok) usage.errors++\n usage.tokens += (call.inputTokens ?? 0) + (call.outputTokens ?? 0)\n }))\n yield this.home.effect(() => {\n const timer = setInterval(() => {\n const [day] = dayHour(Date.now())\n this.flush().then(() => this.prune(day)).catch((error) => this.home.logger('stats').warn('saving statistics failed: %s', error))\n }, FLUSH_EVERY)\n return () => {\n clearInterval(timer)\n return this.flush()\n }\n }, 'stats flush')\n yield this.home.effect(() => this.sampler(), 'stats sampler')\n yield* this.defineActions()\n }\n\n // ---- counting ----\n\n private async load(day: string) {\n let doc = this.days.get(day)\n if (!doc) {\n const stored = await this.home.storage.get<DayDoc>(`stats/${day}`)\n // Counting may have started on this day while it was being read.\n doc = this.days.get(day) ?? { day, hours: stored?.hours ?? {}, names: stored?.names ?? {} }\n this.days.set(day, doc)\n }\n return doc\n }\n\n /** Adds to the bucket of the hour `time` falls in. */\n private count(time: number, update: (counters: Counters, doc: DayDoc) => void) {\n const [day, hour] = dayHour(time)\n const apply = (doc: DayDoc) => {\n update(doc.hours[hour] ??= emptyCounters(), doc)\n this.dirty.add(day)\n }\n const cached = this.days.get(day)\n if (cached) apply(cached)\n else this.load(day).then(apply).catch(() => {})\n }\n\n /** Writes changed days; days other than today leave memory once written. */\n async flush() {\n const [today] = dayHour(Date.now())\n for (const day of [...this.dirty]) {\n this.dirty.delete(day)\n const doc = this.days.get(day)\n if (doc) await this.home.storage.set(`stats/${day}`, doc)\n }\n for (const day of this.days.keys()) if (day !== today && !this.dirty.has(day)) this.days.delete(day)\n }\n\n /** Folds days past the hourly retention into daily totals and deletes days past the daily one. */\n private async prune(today: string) {\n const now = dayStart(today)\n for (const key of await this.home.storage.list('stats')) {\n const day = key.slice('stats/'.length)\n const age = (now - dayStart(day)) / DAY\n if (!Number.isFinite(age) || age < HOURLY_DAYS) continue\n if (age >= DAILY_DAYS) {\n await this.home.storage.delete(key)\n continue\n }\n const doc = await this.home.storage.get<DayDoc>(key)\n if (doc && !doc.hours['*']) await this.home.storage.set(key, compact(doc))\n }\n }\n\n /** Days covering the last `hours` hours, oldest first. */\n private async daysFor(from: number, to: number) {\n const docs: DayDoc[] = []\n for (let time = dayStart(dayHour(from)[0]); time <= to; time += DAY) {\n // Daylight saving can make a day 23 or 25 hours long; take the day the time falls in.\n docs.push(await this.load(dayHour(time + 2 * HOUR)[0]))\n }\n return docs\n }\n\n /** Counters for whole hours in [from, to], one bucket each, plus the doc they came from. */\n private async buckets(from: number, to: number) {\n const result: { time: number; counters: Counters; doc: DayDoc }[] = []\n for (const doc of await this.daysFor(from, to)) {\n const start = dayStart(doc.day)\n for (const [hour, counters] of Object.entries(doc.hours)) {\n const time = hour === '*' ? start : start + Number(hour) * HOUR\n if (time + (hour === '*' ? DAY : HOUR) <= from || time > to) continue\n result.push({ time, counters, doc })\n }\n }\n return result\n }\n\n // ---- queries ----\n\n /** Totals since local midnight. */\n async today() {\n const now = Date.now()\n const total = emptyCounters()\n for (const { counters } of await this.buckets(dayStart(dayHour(now)[0]), now)) merge(total, counters)\n const llm = Object.values(total.llm)\n return {\n received: sum(total.in),\n sent: sum(total.out),\n commands: sum(total.commands),\n flowRuns: sum(total.flows),\n flowErrors: sum(total.flowErrors),\n llmCalls: llm.reduce((count, usage) => count + usage.calls, 0),\n llmTokens: llm.reduce((count, usage) => count + usage.tokens, 0),\n }\n }\n\n /**\n * A metric over the last `hours` hours, one point per hour or per day, split into series (by bot\n * for messages, by provider and model for model usage).\n */\n async series(input: { metric: Metric; hours: number; granularity?: 'hour' | 'day' }) {\n const granularity = input.granularity ?? (input.hours > 72 ? 'day' : 'hour')\n const now = Date.now()\n const step = granularity === 'day' ? DAY : HOUR\n const first = granularity === 'day'\n ? dayStart(dayHour(now - (Math.ceil(input.hours / 24) - 1) * DAY)[0])\n : Math.floor(now / HOUR) * HOUR - (input.hours - 1) * HOUR\n const slotOf = (time: number) => (granularity === 'day' ? dayStart(dayHour(time)[0]) : Math.floor(time / HOUR) * HOUR)\n const points = new Map<number, Record<string, number>>()\n for (let time = first; time <= now; time += step) points.set(slotOf(time + (granularity === 'day' ? 2 * HOUR : 0)), {})\n const keys = new Set<string>()\n for (const { time, counters } of await this.buckets(first, now)) {\n const values = points.get(slotOf(time))\n if (!values) continue\n for (const [key, value] of Object.entries(metricValues(counters, input.metric))) {\n keys.add(key)\n bump(values, key, value)\n }\n }\n const bots = this.home.get('bots')\n const nameOf = (key: string) => {\n if (input.metric === 'messages' || input.metric === 'received' || input.metric === 'sent') {\n return bots?.list().find((bot) => bot.id === key)?.name ?? key\n }\n return key === 'total' ? key : key.replace('|', ' · ')\n }\n return {\n granularity,\n series: [...keys].sort().map((key) => ({ key, name: nameOf(key) })),\n points: [...points].map(([t, values]) => ({ t, values })),\n }\n }\n\n /** The most active chats, people, commands, flows or models over the last `days` days. */\n async top(input: { dimension: Dimension; days: number; limit?: number }) {\n const now = Date.now()\n const from = dayStart(dayHour(now - (input.days - 1) * DAY)[0])\n const total = emptyCounters()\n const names: Record<string, string> = {}\n for (const { counters, doc } of await this.buckets(from, now)) {\n merge(total, counters)\n Object.assign(names, doc.names)\n }\n const bots = this.home.get('bots')\n const flows = this.home.get('flows')\n const botName = (id: string) => bots?.list().find((bot) => bot.id === id)?.name\n return top(total, input.dimension, input.limit ?? 10).map(([key, count]) => {\n if (input.dimension === 'flows') {\n return { key, name: flows?.list().find((flow) => flow.id === key)?.name ?? names[`flow:${key}`] ?? key, count, errors: total.flowErrors[key] ?? 0 }\n }\n if (input.dimension === 'llm') {\n const [provider, model] = key.split('|')\n return { key, name: `${provider} · ${model}`, count, tokens: total.llm[key].tokens, errors: total.llm[key].errors }\n }\n const [botId, rest] = [key.slice(0, key.indexOf('|')), key.slice(key.indexOf('|') + 1)]\n const name = input.dimension === 'commands' ? `/${rest}` : names[key] ?? rest.replace(/^(group|private):/, '')\n return { key, name, id: rest, botId, bot: botName(botId), count }\n })\n }\n\n /** The last hour of process samples, oldest first. */\n performance() {\n return this.samples\n }\n\n private sampler() {\n const histogram = monitorEventLoopDelay({ resolution: LOOP_RESOLUTION })\n histogram.enable()\n let cpu = process.cpuUsage()\n let at = performance.now()\n const timer = setInterval(() => {\n const nextCpu = process.cpuUsage()\n const nextAt = performance.now()\n const used = (nextCpu.user - cpu.user + nextCpu.system - cpu.system) / 1000\n const memory = process.memoryUsage()\n const sample: PerfSample = {\n t: Date.now(),\n cpu: Math.round((used / Math.max(1, nextAt - at)) * 1000) / 10,\n rss: memory.rss,\n heapUsed: memory.heapUsed,\n heapTotal: memory.heapTotal,\n loopMean: Number.isFinite(histogram.mean) ? lag(histogram.mean) : 0,\n loopMax: lag(histogram.max),\n }\n cpu = nextCpu\n at = nextAt\n histogram.reset()\n this.samples.push(sample)\n if (this.samples.length > SAMPLE_LIMIT) this.samples.splice(0, this.samples.length - SAMPLE_LIMIT)\n this.home.emit('stats/sample', sample)\n }, SAMPLE_EVERY)\n timer.unref?.()\n return () => {\n clearInterval(timer)\n histogram.disable()\n }\n }\n\n private async dataDirSize() {\n if (!this.dataSize || Date.now() - this.dataSize.at > DATA_SIZE_TTL) {\n this.dataSize = { at: Date.now(), bytes: await directorySize(this.home.storage.dir) }\n }\n return this.dataSize.bytes\n }\n\n /** Everything the overview's number cards and version panel show. */\n async overview() {\n const bots = this.home.get('bots')\n const flows = this.home.get('flows')\n const llm = this.home.get('llm')\n const manager = this.home.manager\n const botList = bots?.list() ?? []\n const flowList = flows?.list() ?? []\n const providers = llm?.list() ?? []\n const commands = new Set((bots?.commandList().commands ?? []).map((entry) => `${entry.botId}|${entry.name.toLowerCase()}`))\n const catalog = await manager.catalog().catch(() => [])\n const versions = new Map(catalog.map((entry) => [entry.package, entry.version]))\n return {\n bots: { online: botList.filter((bot) => bot.status === 'online').length, total: botList.length },\n appPlugins: { enabled: manager.entries.filter((entry) => entry.enabled !== false).length, total: manager.entries.length },\n botPlugins: { enabled: botList.reduce((count, bot) => count + bot.plugins.filter((plugin) => plugin.enabled).length, 0) },\n flows: { total: flowList.length, enabled: flowList.filter((flow) => flow.enabled).length, withErrors: flowList.filter((flow) => flow.errors > 0).length },\n commands: commands.size,\n providers: { total: providers.length, passed: providers.filter((provider) => provider.lastTest?.ok).length },\n today: await this.today(),\n versions: {\n mushin: versionOf('@mushinjs/core'),\n node: process.version,\n cordis: versionOf('cordis'),\n plugins: manager.entries.map((entry) => ({ package: entry.package, enabled: entry.enabled !== false, version: versions.get(entry.package) })),\n },\n platform: `${process.platform} ${process.arch}`,\n startedAt: this.startedAt,\n uptime: Math.round(process.uptime()),\n dataBytes: await this.dataDirSize(),\n sample: this.samples.at(-1),\n }\n }\n\n // ---- actions ----\n\n private *defineActions() {\n const actions = this.home.actions\n\n yield actions.define({\n name: 'stats.overview',\n description: 'Instance at a glance: bots online, plugins, flows (and how many have errors), commands, providers, today\\'s messages, commands, flow runs and model tokens, versions, uptime and data directory size.',\n risk: 'read',\n input: z.object({}),\n handler: () => this.overview(),\n })\n\n yield actions.define({\n name: 'stats.series',\n description: 'A metric over time, one point per hour or day: messages (split by bot), received, sent, commands, flows (runs), llmCalls or llmTokens (split by provider and model).',\n risk: 'read',\n input: z.object({\n metric: z.enum(METRICS),\n hours: z.number().int().min(1).max(24 * 366).default(24).describe('How far back, e.g. 24 or 168 (7 days)'),\n granularity: z.enum(['hour', 'day']).optional().describe('Defaults to hour up to 3 days, day beyond'),\n }),\n handler: (input) => this.series(input),\n })\n\n yield actions.define({\n name: 'stats.top',\n description: 'The busiest chats, users, commands, flows or models (llm) over the last days, highest first.',\n risk: 'read',\n input: z.object({\n dimension: z.enum(DIMENSIONS),\n days: z.number().int().min(1).max(366).default(7),\n limit: z.number().int().min(1).max(50).optional(),\n }),\n handler: (input) => this.top(input),\n })\n\n yield actions.define({\n name: 'stats.performance',\n description: 'Process CPU (percent of one core), memory (bytes) and event loop delay (ms), one sample every 5 seconds for the last hour.',\n risk: 'read',\n input: z.object({}),\n handler: () => this.performance(),\n })\n }\n}\n\nexport default StatsService\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mushinjs/plugin-stats",
|
|
3
|
-
"version": "0.2.0-next.
|
|
3
|
+
"version": "0.2.0-next.20261113103537",
|
|
4
4
|
"description": "Usage statistics and runtime performance for the overview page",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@mushinjs/core": "0.2.0-next.
|
|
56
|
-
"@mushinjs/plugin-bots": "0.2.0-next.
|
|
57
|
-
"@mushinjs/plugin-flows": "0.2.0-next.
|
|
58
|
-
"@mushinjs/plugin-providers": "0.2.0-next.
|
|
59
|
-
"@mushinjs/plugin-storage": "0.2.0-next.
|
|
55
|
+
"@mushinjs/core": "0.2.0-next.20261113103537",
|
|
56
|
+
"@mushinjs/plugin-bots": "0.2.0-next.20261113103537",
|
|
57
|
+
"@mushinjs/plugin-flows": "0.2.0-next.20261113103537",
|
|
58
|
+
"@mushinjs/plugin-providers": "0.2.0-next.20261113103537",
|
|
59
|
+
"@mushinjs/plugin-storage": "0.2.0-next.20261113103537",
|
|
60
60
|
"cordis": "4.0.0-rc.11"
|
|
61
61
|
}
|
|
62
62
|
}
|