Stats.jsx
1.9 kB · jsx · 42 lines
1import { Code, Rows, Waiting, ago, bytes, useMirror } from "../components/Mirror.jsx";23function Cloud({ data }) {4 return (5 <>6 <Rows7 list={[8 ["Stats", `${ago(data.at)}, last ${data.hours} h`],9 ["CDN", data.cdn.requests == null ? "no distribution" : `${data.cdn.requests} requests, ${bytes(data.cdn.bytes)}, ${data.cdn.error_4xx}% 4xx, ${data.cdn.error_5xx}% 5xx`],10 ["Bucket", `${data.bucket.site_objects} site files (${bytes(data.bucket.site_bytes)}), ${data.bucket.data_objects} data files (${bytes(data.bucket.data_bytes)})`],11 ["Shop", `${data.bucket.products} live products, ${data.bucket.designs} designs on the CDN, ${data.bucket.posts} posts`],12 ]}13 />14 <Rows list={Object.entries(data.lambdas).map(([name, one]) => [name, `${one.invocations} runs, ${one.errors} errors, ${one.throttles} throttles, ${Math.round(one.duration_ms)} ms avg`])} />15 </>16 );17}1819export function Stats() {20 const seen = useMirror("/stats/stats.json");21 const data = seen?.data ?? null;22 const found = Object.entries(data?.errors ?? {}).flatMap(([name, list]) => list.map((one) => `${one.at ?? "sometime"} ${one.level} ${name} ${one.message}`));2324 return (25 <div className="wrap">26 <article className="doc status narrow">27 <h1>Stats</h1>28 <p className="lead">29 The CDN, the Lambdas and the bucket, read from the bucket every minute. Raw: <a href="/stats/stats.json">stats.json</a>, <a href="/cdn/feed/index.json">feed</a>. The shop's own tick lives on <a href="/automator/">automator</a>.30 </p>31 <section>32 <h2>Cloud</h2>33 {data ? <Cloud data={data} /> : <Waiting seen={seen} />}34 </section>35 <section>36 <h2>Errors</h2>37 {found.length ? <Code lines={found} /> : data ? <p className="fine">None in the window.</p> : <Waiting seen={seen} />}38 </section>39 </article>40 </div>41 );42}