apiforgejs 1.0.1 → 1.0.2
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/package.json +1 -1
- package/src/database.js +24 -7
- package/src/ui.html +13 -5
package/package.json
CHANGED
package/src/database.js
CHANGED
|
@@ -229,6 +229,19 @@ class ApiForgeDatabase {
|
|
|
229
229
|
this._begin.run();
|
|
230
230
|
try {
|
|
231
231
|
for (const r of routes) stmt.run(r.route, r.method);
|
|
232
|
+
// Remove routes no longer in the router that never had traffic
|
|
233
|
+
if (routes.length > 0) {
|
|
234
|
+
const keys = routes.map(r => `${r.route}|${r.method}`);
|
|
235
|
+
const ph = keys.map(() => '?').join(', ');
|
|
236
|
+
this.db.prepare(`
|
|
237
|
+
DELETE FROM known_routes
|
|
238
|
+
WHERE route || '|' || method NOT IN (${ph})
|
|
239
|
+
AND NOT EXISTS (
|
|
240
|
+
SELECT 1 FROM api_metrics m
|
|
241
|
+
WHERE m.route = known_routes.route AND m.method = known_routes.method
|
|
242
|
+
)
|
|
243
|
+
`).run(...keys);
|
|
244
|
+
}
|
|
232
245
|
this._commit.run();
|
|
233
246
|
} catch (err) {
|
|
234
247
|
this._rollback.run();
|
|
@@ -258,13 +271,17 @@ class ApiForgeDatabase {
|
|
|
258
271
|
|
|
259
272
|
getReleases() {
|
|
260
273
|
return this.db.prepare(`
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
274
|
+
WITH release_times AS (
|
|
275
|
+
SELECT release_tag, MIN(bucket_ts) AS release_ts
|
|
276
|
+
FROM api_metrics
|
|
277
|
+
WHERE release_tag IS NOT NULL AND release_tag != ''
|
|
278
|
+
GROUP BY release_tag
|
|
279
|
+
)
|
|
280
|
+
SELECT rt.release_tag,
|
|
281
|
+
rt.release_ts,
|
|
282
|
+
(SELECT COUNT(*) FROM known_routes WHERE first_seen <= rt.release_ts + 60) AS routes_affected
|
|
283
|
+
FROM release_times rt
|
|
284
|
+
ORDER BY rt.release_ts DESC
|
|
268
285
|
LIMIT 20
|
|
269
286
|
`).all();
|
|
270
287
|
}
|
package/src/ui.html
CHANGED
|
@@ -421,6 +421,7 @@ function mapInsights(insights) {
|
|
|
421
421
|
function mapReleases(releases) {
|
|
422
422
|
return (releases || []).map(r => ({
|
|
423
423
|
tag: r.release_tag,
|
|
424
|
+
ts: r.release_ts,
|
|
424
425
|
summary: `${r.routes_affected || 0} route${r.routes_affected !== 1 ? 's' : ''} recorded`,
|
|
425
426
|
age: formatAge(r.release_ts),
|
|
426
427
|
by: 'local',
|
|
@@ -739,11 +740,18 @@ function Overview({ timeRange, setRoute, setParams, lastUpdated }) {
|
|
|
739
740
|
const globalCalls = chartData?.calls || Array(fallbackPts).fill(0);
|
|
740
741
|
const xLabelsFinal = xLabels.length > 0 ? xLabels : Array.from({length:globalP90.length}, (_,i) => `${i}`);
|
|
741
742
|
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
743
|
+
const MARKER_COLORS = ['#b91c1c','#15803d','#2563eb','#b45309','#7c3aed'];
|
|
744
|
+
const nowTs = Date.now() / 1000;
|
|
745
|
+
const releaseMarkers = globalTs && globalTs.length > 0
|
|
746
|
+
? [...(RELEASES || [])]
|
|
747
|
+
.filter(r => r.ts != null && r.ts >= nowTs - hours * 3600)
|
|
748
|
+
.reverse()
|
|
749
|
+
.map((r, i) => {
|
|
750
|
+
const idx = globalTs.reduce((best, b, j) =>
|
|
751
|
+
Math.abs(b.bucket_ts - r.ts) < Math.abs(globalTs[best].bucket_ts - r.ts) ? j : best, 0);
|
|
752
|
+
return { idx, label: r.tag, color: MARKER_COLORS[i % MARKER_COLORS.length] };
|
|
753
|
+
})
|
|
754
|
+
: [];
|
|
747
755
|
|
|
748
756
|
const topSlow = [...ENDPOINTS].filter(e => !e.untracked && e.base_p90 > 0).sort((a,b) => b.base_p90-a.base_p90).slice(0,5);
|
|
749
757
|
const topCalled = [...ENDPOINTS].sort((a,b) => b.calls24h-a.calls24h).slice(0,5);
|