fix(tracker-web): telemetry ingest auth (X-Install-Token) + show cost as approx
- telemetry proxy attaches an X-Install-Token (derived from the payload, with a fallback) so the backend ingest auth gate stops returning 401 on browser beacons. - job-detail Cost shows ~$x.xx approx when the figure is estimated (token-based).
This commit is contained in:
parent
696ee4189e
commit
37d049eb69
@ -11,11 +11,23 @@ export async function POST(req: NextRequest) {
|
|||||||
try {
|
try {
|
||||||
const body = await req.text();
|
const body = await req.text();
|
||||||
|
|
||||||
|
// The backend telemetry ingest requires a JWT or an X-Install-Token. Browser
|
||||||
|
// beacons can't set an Authorization header, so derive an install token from
|
||||||
|
// the payload (installId) with a stable fallback to satisfy the auth gate.
|
||||||
|
let installToken = 'web-telemetry';
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(body);
|
||||||
|
installToken = parsed.installId || parsed.events?.[0]?.installId || installToken;
|
||||||
|
} catch {
|
||||||
|
/* keep fallback */
|
||||||
|
}
|
||||||
|
|
||||||
const res = await fetch(`${PLATFORM_SERVICE_URL}/api/telemetry/events`, {
|
const res = await fetch(`${PLATFORM_SERVICE_URL}/api/telemetry/events`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-Product-Id': PRODUCT_ID,
|
'X-Product-Id': PRODUCT_ID,
|
||||||
|
'X-Install-Token': installToken,
|
||||||
},
|
},
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -325,7 +325,14 @@ export default function FleetJobDetailPage() {
|
|||||||
const t = runTotals(runs);
|
const t = runTotals(runs);
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap gap-2" aria-label="Job totals">
|
<div className="flex flex-wrap gap-2" aria-label="Job totals">
|
||||||
<Stat label="Total cost" value={t.costUsd > 0 ? fmtUsd(t.costUsd) : '—'} />
|
<Stat
|
||||||
|
label="Total cost"
|
||||||
|
value={
|
||||||
|
t.costUsd > 0
|
||||||
|
? `${t.estimated ? '~' : ''}${fmtUsd(t.costUsd)}${t.estimated ? ' approx' : ''}`
|
||||||
|
: '—'
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Stat label="Tokens in" value={t.tokensIn > 0 ? fmtNum(t.tokensIn) : '—'} />
|
<Stat label="Tokens in" value={t.tokensIn > 0 ? fmtNum(t.tokensIn) : '—'} />
|
||||||
<Stat label="Tokens out" value={t.tokensOut > 0 ? fmtNum(t.tokensOut) : '—'} />
|
<Stat label="Tokens out" value={t.tokensOut > 0 ? fmtNum(t.tokensOut) : '—'} />
|
||||||
<Stat
|
<Stat
|
||||||
@ -393,9 +400,10 @@ export default function FleetJobDetailPage() {
|
|||||||
<td className="py-2 text-right font-mono text-xs">
|
<td className="py-2 text-right font-mono text-xs">
|
||||||
{ins.costUsd != null ? (
|
{ins.costUsd != null ? (
|
||||||
<>
|
<>
|
||||||
|
{ins.estimated ? '~' : ''}
|
||||||
{fmtUsd(ins.costUsd)}
|
{fmtUsd(ins.costUsd)}
|
||||||
{ins.estimated ? (
|
{ins.estimated ? (
|
||||||
<span className="text-muted-foreground"> est.</span>
|
<span className="text-muted-foreground"> approx</span>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@ -501,9 +509,11 @@ function runTotals(runs: FleetRun[]) {
|
|||||||
let tokensIn = 0;
|
let tokensIn = 0;
|
||||||
let tokensOut = 0;
|
let tokensOut = 0;
|
||||||
let durationMs = 0;
|
let durationMs = 0;
|
||||||
|
let estimated = false;
|
||||||
for (const r of runs) {
|
for (const r of runs) {
|
||||||
const ins = r.insights ?? {};
|
const ins = r.insights ?? {};
|
||||||
costUsd += ins.costUsd ?? 0;
|
costUsd += ins.costUsd ?? 0;
|
||||||
|
if (ins.estimated) estimated = true;
|
||||||
tokensIn += ins.tokensIn ?? 0;
|
tokensIn += ins.tokensIn ?? 0;
|
||||||
tokensOut += ins.tokensOut ?? 0;
|
tokensOut += ins.tokensOut ?? 0;
|
||||||
if (r.endedAt) {
|
if (r.endedAt) {
|
||||||
@ -511,7 +521,7 @@ function runTotals(runs: FleetRun[]) {
|
|||||||
if (Number.isFinite(d) && d > 0) durationMs += d;
|
if (Number.isFinite(d) && d > 0) durationMs += d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { costUsd, tokensIn, tokensOut, durationMs };
|
return { costUsd, tokensIn, tokensOut, durationMs, estimated };
|
||||||
}
|
}
|
||||||
|
|
||||||
function fmtUsd(n: number): string {
|
function fmtUsd(n: number): string {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user