TraceOfPage

tcmts.studio.TraceOfPage · #wnvlg6rp · term · runs on the server

is an async component

One row of the traces page as a page of its own: a definition's spans of a kind (each version of it alike), or a page's, a view's or a statement's, since long ago (1h, 24h, 7d). Its calls, errors, p50 and p95; what runs worse than its version before and the change that did it; each version side by side; where its calls came from in the browser; its slowest and latest traces, each a link to its waterfall.

import { shownMs, sinceMs } from "#codebase/tcmts/cli/main";
import { traceOf } from "#codebase/tcmts/cli/traced";
import { shortHash } from "#codebase/tcmts/core/hash";
import { ago, at, codeHref, shareNow } from "#codebase/tcmts/share";
import { StudioFrame, studioShare, traceOfHref, tracesFrom } from "#codebase/tcmts/studio";

export async function TraceOfPage({
  name,
  kind,
  since,
  from,
}: {
  name: string;
  kind: string;
  since: string;
  from: string;
}) {
  studioShare();
  const s = shareNow();
  if (!s.signedIn) return <StudioFrame tab="traces" title="Sign in">{null}</StudioFrame>;
  const ago_ = ["1h", "24h", "7d"].includes(since) ? since : "24h";
  const t = tracesFrom(s.cb, from)((db) => traceOf(db, s.cb, name, kind, Date.now() - sinceMs(ago_)));
  const q = from === "production" ? "?from=production" : "";
  const kindSaid = kind === "client" ? "from the browser" : kind;
  const row = (x: { trace: string; start: number; dur: number; error: string | null; hash: string | null }) => (
    <a className="lrow tracerow" key={`${x.trace} ${x.start}`} href={at(`/trace/${x.trace}${q}`)}>
      <div>
        <span className="mono">trace {x.trace.slice(0, 8)}</span>{" "}
        <span className="muted">
          {ago(x.start)}
          {t && t.versions.length > 1 && x.hash ? ` · ${shortHash(x.hash)}` : ""}
        </span>
        {x.error && <> <code className="bad">{x.error.split("\n")[0]}</code></>}
      </div>
      <span>{shownMs(x.dur)}</span>
    </a>
  );
  return (
    <StudioFrame tab="traces" title={`${name} · traces`}>
      <div className="crumbs">
        <a href={at(`/traces${ago_ === "24h" ? q : `?since=${ago_}${q.replace("?", "&")}`}`)}>
          {from === "production" ? "Production's traces" : "Traces"}
        </a> <span className="muted">/</span>
      </div>
      <div className="pagehead">
        <h2 className="title mono" style={{ fontSize: 20 }}>{name}</h2>
        <span className="muted">{kindSaid}, in the last {ago_}</span>
        <span className="right actions">
          {t?.definition && <a className="btn small" href={codeHref(name)}>Its code</a>}
          <span className="seg">
            {["1h", "24h", "7d"].map((x) => (
              <a
                key={x}
                className="btn small"
                href={`${traceOfHref(name, kind, from)}${x === "24h" ? "" : `&since=${x}`}`}
                {...(x === ago_ ? { "data-selected": "" } : {})}
              >
                {x}
              </a>
            ))}
          </span>
        </span>
      </div>
      {!t ? (
        <div className="box"><div className="empty">Nothing recorded for it in the last {ago_}.</div></div>
      ) : (
        <>
          {t.change?.verdict?.worse && (
            <div className="notice" style={{ borderColor: "var(--warn)", background: "var(--warnbg)" }}>
              <b className="warn">Worse than its version before: {t.change.verdict.said}.</b>{" "}
              {t.change.changed.length ? <>What changed: {t.change.changed.join(", ")}. </> : null}
              {t.versions[0]?.since && <a href={at(`/history/${t.versions[0].since.causal}`)}>See the change</a>}
            </div>
          )}
          <div className="box">
            <div className="boxbody">
              <div className="stats">
                <div className="stat"><b>{t.n}</b>{kind === "render" ? "renders" : kind === "sql" ? "statements" : "calls"}</div>
                <div className="stat"><b className={t.errors ? "bad" : ""}>{t.errors}</b>errors</div>
                <div className="stat"><b>{shownMs(t.p50)}</b>p50</div>
                <div className="stat"><b>{shownMs(t.p95)}</b>p95</div>
                <div className="stat"><b>{shownMs(t.max)}</b>the longest</div>
              </div>
            </div>
          </div>
          <div className="cols-2" style={{ display: "grid", gap: 24 }}>
            <div>
              <div className="box">
                <div className="boxhead">
                  <b>Latest</b>
                  <span className="muted">each trace, to its waterfall</span>
                </div>
                {t.latest.map(row)}
              </div>
            </div>
            <aside className="side">
              <div className="sect">
                <h4>Slowest</h4>
                {t.slowest.map((x) => (
                  <div key={`${x.trace} ${x.start}`}>
                    <a className="mono" href={at(`/trace/${x.trace}${q}`)}>{x.trace.slice(0, 8)}</a>{" "}
                    <span className="muted">{shownMs(x.dur)} · {ago(x.start)}</span>
                  </div>
                ))}
              </div>
              {t.versions.length > 1 && (
                <div className="sect">
                  <h4>Versions</h4>
                  {t.versions.map((v) => (
                    <div key={v.hash} style={{ marginBottom: 6 }}>
                      <span className="mono">{shortHash(v.hash)}</span>
                      {v.now && <span className="muted"> (now)</span>}{" "}
                      <span className="muted">
                        {v.n} · p95 {shownMs(v.p95)}{v.errors ? ` · ${v.errors} failed` : ""}
                      </span>
                      {v.since && (
                        <a href={at(`/history/${v.since.causal}`)} style={{ display: "block", fontSize: 12.5 }}>
                          {v.since.title}
                        </a>
                      )}
                    </div>
                  ))}
                </div>
              )}
              {t.callers.length > 0 && (
                <div className="sect">
                  <h4>Called from</h4>
                  {t.callers.map((c) => (
                    <div key={c.caller?.hash ?? "page"}>
                      {c.caller && (!c.caller.gone || c.caller.earlier) ? (
                        <a className="mono" href={codeHref(c.caller.label)}>{c.caller.label}</a>
                      ) : (
                        <span className="mono">{c.caller?.label ?? "the page"}</span>
                      )}{" "}
                      <span className="muted">{c.n} · waited p95 {shownMs(c.p95)}</span>
                    </div>
                  ))}
                </div>
              )}
            </aside>
          </div>
        </>
      )}
    </StudioFrame>
  );
}

uses

used by