Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

bug: Ring and ledger count errors and coverage differently, cost reads slow down over time, and cost comments are stale

オープン
#1,566 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
49/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
go

調査の方向性

Start with core/cost/usage/usage.go and core/cost/ledger/writer.go to compare the error and priceability rules, then inspect the archive read and write paths in core/session/archive and ledger queries in core/cost/ledger. Add or update focused tests for zero-usage successful responses, excluded errors, archive rotation and reads, and past-day caching. Done means the ledger and ring agree, archive reads avoid repeatedly decoding growing segments, and stale comments match the code.

索引モデルが issue の本文から書いたものです。

説明

bug

Problem

The cost and session read paths have three problems. The ring (which serves the duration windows) and the ledger (which serves today/7d/month) count the same traffic by different rules. Two read paths get slower the longer the proxy runs. And several comments in core/cost describe code that has since changed. Line numbers are at ab5f01f26.

1. The ledger hides a coverage gap that the ring reports
  • Ledger (core/cost/ledger/writer.go:519-521): a request counts as priceable only if r.Model != "" && r.Tokens > 0.
  • Ring (core/cost/usage/usage.go:812-840): any successful response with a model counts as priceable, even with zero usage, and it is named in UnpricedBy.

Case: a truncated OpenAI-dialect stream returns 200, the model is set, and there is no usage block. inference-parser publishes no cost record for it. With 9 priced requests plus one of these:

  • window=today shows 9/9, which looks fully priced.
  • window=1h shows 9/10 and names the gap.

The ring's own comment (usage.go:821-825) calls the 9/9 result a bug it fixed. There is no ledger test for a successful response with zero usage.

2. The error rule is written twice, and only one copy was updated
  • countsAsError (usage.go:1279-1285) excludes ErrorKindUpgradeDeclined and ErrorKindDestinationPrivate. The latter was added in ab5f01f26.
  • The ledger (writer.go:514-516) still counts any StatusCode >= 400 || Denied.

So a parsed inference request refused with 403 destination_private counts as an error on today but not on 1h.

Fix for 1 and 2: export usage.CountsAsError and a single "priceable" check, and call both from the ledger writer.

3. Archive segments never rotate, and every read decodes from the start

core/session/archive/archive.go: a segment closes only after 60 minutes idle (:736), at the open-writer cap, or on delete, clear, rename or a write failure. There is no size or event-count limit.

  • planPrune never deletes an open segment (retention.go:54-63). A session busy all day therefore keeps one segment growing without limit, and maxBytes (2 GiB) can stay exceeded.
  • Page and Event decode the segment from its first event up to the cursor, and Earlier calls Page once per 500 events (read.go:44-81, 189-203). inference-router's wentTo calls Earlier on the request path with historyLimit = 2000. With 20k events in the segment, that is 4 page calls, each decompressing and decoding most of the segment, per request.

Fix: rotate in write after N events or M bytes, by calling closeWriter when s.w.info() passes the cap.

4. Every ledger query re-reads every day file in the window

core/cost/ledger/query.go:183-250 / store.go:493-530 open and fully decode each day file on every request, with no cache.

  • agentop polls today every minute and 7d/month every 5 minutes (cmd/agentop/tui/spend.go:211-217). On the 31st, month decodes 31 files per poll, and past days almost never change.
  • The endpoint has no auth.

Fix: cache decoded past days keyed by (path, size, mtime). Only today's file needs re-reading.

5. Comments that contradict the code
  • core/cost/pricing/cost.go:20-25 calls the accumulation wrap "an open defect", but Counts.Add saturates (usage.go:349-405).
  • cost.go:93-99 says MaxPlausibleTokens has "NO IMPORTER ON THIS BRANCH". The ledger writer imports it (writer.go:288-324).
  • cost.go:202-204 says plausibleTokenReport and RefusedTokenRequests don't exist. They do (usage.go:438, :122).
  • ledger/writer.go:929-933 says Dropped() has "No non-test caller today". sessionapi/usage.go:404 calls it.

These read like notes from the middle of a PR stack. A reader trusting them would conclude that sums can still wrap and that the token bounds are not enforced.

Fix: delete or correct them.

Found by a code audit of main at ab5f01f26. Items 3 and 4 were verified by reading the code; the decode cost was not measured.

Assisted-By: Claude (Anthropic AI) [email protected]

主要言語
Go
スター
21
フォーク
43
平均マージ
14時間 25分
マージ済み PR(30日)
245

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

rossoctl/cortex のほかの issue

rossoctl/cortex の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。