Skip to content

feat(analytics): live request log, per-model cost, and visualization …#230

Open
jahin-abrar-official wants to merge 6 commits into
tashfeenahmed:mainfrom
jahin-abrar-official:feat/live-request-log
Open

feat(analytics): live request log, per-model cost, and visualization …#230
jahin-abrar-official wants to merge 6 commits into
tashfeenahmed:mainfrom
jahin-abrar-official:feat/live-request-log

Conversation

@jahin-abrar-official

@jahin-abrar-official jahin-abrar-official commented Jun 5, 2026

Copy link
Copy Markdown

added some feature for better annalysis . hope you guys will love it . if this is approvable please approve it . and add me as contributor . this will be my 1st contribution

  • Live Request Log backend Added. GET /api/analytics/live-requests endpoint that returns the last 100 requests with provider, model display name, status, latency, error, and timestamp. Supports an errorsOnly=true query filter.

  • Live Request Log UI Added a new full-width "Live Request Log" panel under Per-Model Breakdown with an All / Errors Only toggle. Rows are clickable and open a side drawer showing full request details + error payload.

  • Per-Model timeline endpoint� Added GET /api/analytics/by-model-timeline that returns per-model daily/hourly aggregates with requests, tokens, and cost for time-series visualization.

  • Per-Model Breakdown UI enhancements Added two toggle sets:

  • Total / Over Time switches between aggregated totals and time-series trends.

  • Table / Chart / Pie switches visualization type. Pie is disabled in Over Time mode.

  • Added a new Cost column in the table view with clickable column sorting.

  • Over Time chart tooltip Added a custom styled tooltip with background that shows timestamp, provider, model, requests, and cost.

  • Tests Added test coverage for the live-requests endpoint and errorsOnly filter in the analytics route tests.

  • Build verification Both client and server builds pass; all existing analytics tests pass.

Analytics Charts & UI

  • Fixed Over Time chart — added dual Y-axis (requests left, cost right)

  • Added 1h filter — minute-level buckets (HH:MM) alongside 24h/7d/30d

  • Human-readable time labels — formatAxisLabel() formats 1h→06:42, 24h→6 AM, 7d/30d→Jun 5

  • Wrapped X-axis labels — wrapLabel() splits long model names into multi-line SVG text so they don't overlap

  • Smart latency formatting — ≥1000ms renders as 1.5s instead of 1500ms across charts and Live Request Log

  • Pie chart label toggle — added "Labels" button to show/hide pie slice percentages

Live Request Log

  • Upgraded from "Recent errors" to full request log with All / Errors Only filter

  • Color-coded status badges (200 OK, 429 Rate Limit, 502 Bad Gateway, etc.)

  • Click any row to open drawer with full request details

Pricing Page (new)

  • Table view — Model, Provider, Input (/1M),Output(/1M), Last Updated
  • Inline editing — click any price cell → type value → Enter to save; only that field updates
  • Unconfigured models at top — sorted so models missing either price appear first with "NEW" badge and red highlight
  • Both prices required — model only considered configured when input AND output are both set
  • Screen-sized JSON editor — 95vw×92vh modal with Copy, Paste, Edit, and "Update by AI" toolbar
  • AI update flow — sends JSON to /v1/chat/completions with prompt to research current live pricing; strips markdown fences; shows loading state
  • AI warning popup — advises using ChatGPT for browsing accuracy; "Proceed anyway" (green) or "I will do by ChatGPT" (red)

Backend

  • DB migration — added input_cost_per_1m, output_cost_per_1m, cost_updated_at to models table
  • Cost API — GET /api/cost lists all models with pricing; PUT /api/cost bulk updates only provided fields (fixes bug where saving input wiped output)
  • Analytics cost calculation — uses per-model DB prices with fallback to $3/$15 per 1M tokens; combines input + output into single estimatedCost

jahin-abrar-official and others added 3 commits June 5, 2026 15:31
- Keep per-model paid-equivalent pricing via applyModelPricing
- Keep pinned request tracking (summary + by-model)
- Keep interactive by-model table with sortable columns
- Keep live request log with filter and drawer details
- Remove obsolete costStats query and migrateModelsV23Cost

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MLuqmanBR pushed a commit to MLuqmanBR/api-gateway that referenced this pull request Jun 7, 2026
…shfeenahmed#230)

Redesign custom providers from a per-model {baseUrl, modelId, apiKey} blob into
first-class platform objects that work like the built-in ones. The operator adds
a provider once (slug + display name + base URL), then adds as many models as
they like under it. Multiple API keys for the same custom provider now round-
robin across a single shared base URL.

Server:
  - server/src/db/index.ts — new custom_providers table (id, slug UNIQUE,
    display_name, base_url, created_at) + V23 migration that re-points any
    existing 'custom' rows to a synthetic 'legacy-custom' provider row, so no
    data is lost on upgrade.
  - shared/types.ts — Platform no longer includes 'custom'. New
    CustomProvider/CustomProviderCreate/CustomProviderUpdate/CustomModel* types.
    Model.platform and ApiKey.platform are relaxed to string so they can hold
    any custom slug.
  - server/src/providers/index.ts — add buildProviderFor(platformSlug): returns
    the registered singleton for built-ins, or constructs an OpenAICompatProvider
    bound to the custom_providers row's base_url for custom slugs. The old
    resolveProvider(platform, baseUrl) overload is gone.
  - server/src/routes/custom.ts — new, 8 endpoints:
      GET    /api/custom-providers
      POST   /api/custom-providers
      PATCH  /api/custom-providers/:slug
      DELETE /api/custom-providers/:slug  (cascades to models, api_keys, fallback_config)
      GET    /api/custom-providers/:slug/models
      POST   /api/custom-providers/:slug/models
      PATCH  /api/custom-models/:id
      DELETE /api/custom-models/:id
    Slug regex ^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$ (2-32 chars, no leading/trailing
    dash). Built-in slugs (google/groq/...) are deny-listed. PATCH on
    custom_providers keeps api_keys.base_url in lockstep.
  - server/src/routes/keys.ts — drop POST /api/keys/custom. POST /api/keys now
    validates platform via buildProviderFor and stores base_url on the key row
    for custom slugs. PATCH /api/keys/platform/:platform now accepts custom
    slugs (verified against custom_providers).
  - server/src/services/router.ts — uses buildProviderFor(entry.platform).
    Drop the 'custom && key_id != null' branch; the models.key_id column is
    now a denormalized legacy column that the router doesn't consult.
  - server/src/services/health.ts — uses buildProviderFor(row.platform).
  - server/src/app.ts — mount customRouter behind a path-aware requireAuth
    guard so /api/ping and /api/auth/* stay public. The guard regex-scopes
    requireAuth to /api/custom-providers/* and /api/custom-models/* only.

Tests:
  - server/src/__tests__/routes/custom-providers.test.ts — 16 tests across
    provider CRUD, model CRUD, cascade deletes, slug-collision rejection,
    buildProviderFor integration.
  - server/src/__tests__/routes/proxy-empty-completion.test.ts,
    server/src/__tests__/routes/responses-tool-args-repair.test.ts — add
    buildProviderFor: () => fakeProvider to the vi.mock factory for the new
    provider-lookup function.

Client:
  - client/src/pages/KeysPage.tsx — full rewrite. New components:
    AddPlatformModal, EditPlatformModal, PlatformTile, PlatformsSection,
    CustomModelsSection. Custom provider tiles get Edit/Remove; the
    'Add New Platform' tile is always last in the provider list.

Docs:
  - README.md — update the custom-provider blurb and add a 'Custom platforms
    and models' subsection covering slug rules, modal fields, model form
    essential-vs-advanced toggle, and cascade-on-delete behavior.

Behavior change worth highlighting: the 'model belongs to one specific key'
binding (the models.key_id column) is intentionally dropped. Any enabled key
for the custom provider can now serve any model on it.
MLuqmanBR added a commit to MLuqmanBR/api-gateway that referenced this pull request Jun 7, 2026
…shfeenahmed#230)

Redesign custom providers from a per-model {baseUrl, modelId, apiKey} blob into
first-class platform objects that work like the built-in ones. The operator adds
a provider once (slug + display name + base URL), then adds as many models as
they like under it. Multiple API keys for the same custom provider now round-
robin across a single shared base URL.

Server:
  - server/src/db/index.ts — new custom_providers table (id, slug UNIQUE,
    display_name, base_url, created_at) + V23 migration that re-points any
    existing 'custom' rows to a synthetic 'legacy-custom' provider row, so no
    data is lost on upgrade.
  - shared/types.ts — Platform no longer includes 'custom'. New
    CustomProvider/CustomProviderCreate/CustomProviderUpdate/CustomModel* types.
    Model.platform and ApiKey.platform are relaxed to string so they can hold
    any custom slug.
  - server/src/providers/index.ts — add buildProviderFor(platformSlug): returns
    the registered singleton for built-ins, or constructs an OpenAICompatProvider
    bound to the custom_providers row's base_url for custom slugs. The old
    resolveProvider(platform, baseUrl) overload is gone.
  - server/src/routes/custom.ts — new, 8 endpoints:
      GET    /api/custom-providers
      POST   /api/custom-providers
      PATCH  /api/custom-providers/:slug
      DELETE /api/custom-providers/:slug  (cascades to models, api_keys, fallback_config)
      GET    /api/custom-providers/:slug/models
      POST   /api/custom-providers/:slug/models
      PATCH  /api/custom-models/:id
      DELETE /api/custom-models/:id
    Slug regex ^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$ (2-32 chars, no leading/trailing
    dash). Built-in slugs (google/groq/...) are deny-listed. PATCH on
    custom_providers keeps api_keys.base_url in lockstep.
  - server/src/routes/keys.ts — drop POST /api/keys/custom. POST /api/keys now
    validates platform via buildProviderFor and stores base_url on the key row
    for custom slugs. PATCH /api/keys/platform/:platform now accepts custom
    slugs (verified against custom_providers).
  - server/src/services/router.ts — uses buildProviderFor(entry.platform).
    Drop the 'custom && key_id != null' branch; the models.key_id column is
    now a denormalized legacy column that the router doesn't consult.
  - server/src/services/health.ts — uses buildProviderFor(row.platform).
  - server/src/app.ts — mount customRouter behind a path-aware requireAuth
    guard so /api/ping and /api/auth/* stay public. The guard regex-scopes
    requireAuth to /api/custom-providers/* and /api/custom-models/* only.

Tests:
  - server/src/__tests__/routes/custom-providers.test.ts — 16 tests across
    provider CRUD, model CRUD, cascade deletes, slug-collision rejection,
    buildProviderFor integration.
  - server/src/__tests__/routes/proxy-empty-completion.test.ts,
    server/src/__tests__/routes/responses-tool-args-repair.test.ts — add
    buildProviderFor: () => fakeProvider to the vi.mock factory for the new
    provider-lookup function.

Client:
  - client/src/pages/KeysPage.tsx — full rewrite. New components:
    AddPlatformModal, EditPlatformModal, PlatformTile, PlatformsSection,
    CustomModelsSection. Custom provider tiles get Edit/Remove; the
    'Add New Platform' tile is always last in the provider list.

Docs:
  - README.md — update the custom-provider blurb and add a 'Custom platforms
    and models' subsection covering slug rules, modal fields, model form
    essential-vs-advanced toggle, and cascade-on-delete behavior.

Behavior change worth highlighting: the 'model belongs to one specific key'
binding (the models.key_id column) is intentionally dropped. Any enabled key
for the custom provider can now serve any model on it.
@jahin-abrar-official

Copy link
Copy Markdown
Author

the user can change the cost of per model for better annalysis.
screencapture-127-0-0-1-5173-pricing-2026-06-08-13_42_41
the user can can copy,paste and edit it . also they can update it with the ai too . (using the ai that user setup)
screencapture-127-0-0-1-5173-pricing-2026-06-08-13_42_47
(some more graphs are added for more annalysis)
screencapture-127-0-0-1-5173-analytics-2026-06-08-13_42_18

MLuqmanBR added a commit to MLuqmanBR/api-gateway that referenced this pull request Jun 10, 2026
…shfeenahmed#230)

Redesign custom providers from a per-model {baseUrl, modelId, apiKey} blob into
first-class platform objects that work like the built-in ones. The operator adds
a provider once (slug + display name + base URL), then adds as many models as
they like under it. Multiple API keys for the same custom provider now round-
robin across a single shared base URL.

Server:
  - server/src/db/index.ts — new custom_providers table (id, slug UNIQUE,
    display_name, base_url, created_at) + V23 migration that re-points any
    existing 'custom' rows to a synthetic 'legacy-custom' provider row, so no
    data is lost on upgrade.
  - shared/types.ts — Platform no longer includes 'custom'. New
    CustomProvider/CustomProviderCreate/CustomProviderUpdate/CustomModel* types.
    Model.platform and ApiKey.platform are relaxed to string so they can hold
    any custom slug.
  - server/src/providers/index.ts — add buildProviderFor(platformSlug): returns
    the registered singleton for built-ins, or constructs an OpenAICompatProvider
    bound to the custom_providers row's base_url for custom slugs. The old
    resolveProvider(platform, baseUrl) overload is gone.
  - server/src/routes/custom.ts — new, 8 endpoints:
      GET    /api/custom-providers
      POST   /api/custom-providers
      PATCH  /api/custom-providers/:slug
      DELETE /api/custom-providers/:slug  (cascades to models, api_keys, fallback_config)
      GET    /api/custom-providers/:slug/models
      POST   /api/custom-providers/:slug/models
      PATCH  /api/custom-models/:id
      DELETE /api/custom-models/:id
    Slug regex ^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$ (2-32 chars, no leading/trailing
    dash). Built-in slugs (google/groq/...) are deny-listed. PATCH on
    custom_providers keeps api_keys.base_url in lockstep.
  - server/src/routes/keys.ts — drop POST /api/keys/custom. POST /api/keys now
    validates platform via buildProviderFor and stores base_url on the key row
    for custom slugs. PATCH /api/keys/platform/:platform now accepts custom
    slugs (verified against custom_providers).
  - server/src/services/router.ts — uses buildProviderFor(entry.platform).
    Drop the 'custom && key_id != null' branch; the models.key_id column is
    now a denormalized legacy column that the router doesn't consult.
  - server/src/services/health.ts — uses buildProviderFor(row.platform).
  - server/src/app.ts — mount customRouter behind a path-aware requireAuth
    guard so /api/ping and /api/auth/* stay public. The guard regex-scopes
    requireAuth to /api/custom-providers/* and /api/custom-models/* only.

Tests:
  - server/src/__tests__/routes/custom-providers.test.ts — 16 tests across
    provider CRUD, model CRUD, cascade deletes, slug-collision rejection,
    buildProviderFor integration.
  - server/src/__tests__/routes/proxy-empty-completion.test.ts,
    server/src/__tests__/routes/responses-tool-args-repair.test.ts — add
    buildProviderFor: () => fakeProvider to the vi.mock factory for the new
    provider-lookup function.

Client:
  - client/src/pages/KeysPage.tsx — full rewrite. New components:
    AddPlatformModal, EditPlatformModal, PlatformTile, PlatformsSection,
    CustomModelsSection. Custom provider tiles get Edit/Remove; the
    'Add New Platform' tile is always last in the provider list.

Docs:
  - README.md — update the custom-provider blurb and add a 'Custom platforms
    and models' subsection covering slug rules, modal fields, model form
    essential-vs-advanced toggle, and cascade-on-delete behavior.

Behavior change worth highlighting: the 'model belongs to one specific key'
binding (the models.key_id column) is intentionally dropped. Any enabled key
for the custom provider can now serve any model on it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant