diff --git a/frontend/.gitignore b/frontend/.gitignore index 7c0736e..b0c20fc 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -5,3 +5,4 @@ node_modules /functions/\[\[path\]\].js.map /public/build .dev.vars +/functions/metafile* \ No newline at end of file diff --git a/frontend/app/components/StatsContext.tsx b/frontend/app/components/StatsContext.tsx index 75606f2..171cec5 100644 --- a/frontend/app/components/StatsContext.tsx +++ b/frontend/app/components/StatsContext.tsx @@ -1,4 +1,5 @@ import { createContext, useContext } from "react"; +import type { SQLRequestEvent } from "../../../worker/lib/tools"; export const StatsContext = createContext(null); @@ -16,13 +17,7 @@ export const initialStats = { update: 0, delete: 0, insert: 0, - log: [] as { - type: string; - query: string; - ts: string; - served_by: string; - duration: string; - }[], + log: [] as SQLRequestEvent[], }; export function useStats() { diff --git a/frontend/app/root.tsx b/frontend/app/root.tsx index e8af6a7..0c8b441 100644 --- a/frontend/app/root.tsx +++ b/frontend/app/root.tsx @@ -45,7 +45,7 @@ const statsReducer = (state: any, action: any) => { if (action.update) state.update += action.update; if (action.delete) state.delete += action.delete; if (action.insert) state.insert += action.insert; - if (action.log) state.log.push(...action.log); + if (action.log) state.log.push({ ...action.log }); return state; }; @@ -74,10 +74,7 @@ export default function App() { property="og:description" content="This is a demo of the Northwind dataset, running on Cloudflare Workers, and D1 - Cloudflare's newest SQL database, running on SQLite." /> - + - + {
Customer avatar
diff --git a/frontend/app/routes/dash.tsx b/frontend/app/routes/dash.tsx index b5bf7a2..0f53e57 100644 --- a/frontend/app/routes/dash.tsx +++ b/frontend/app/routes/dash.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from "react"; import { useStats } from "~/components/StatsContext"; +import { SQLRequestEvent } from "worker/lib/tools"; interface Status { cf: @@ -71,25 +72,53 @@ export default function Dash() {

Explore the app and see metrics here

- {stats?.log?.map((log, index: number) => { - console.log(log); - if (log.type == "sql") { - return ( -
-

- {log.ts}, {log.served_by}, {log.duration}ms -

- {log.query.split("\n").map((l: string, index: number) => { - return ( -

- {l} -

- ); - })} -
- ); - } else return null; - })} +
+ {stats?.log?.map((log: SQLRequestEvent, index: number) => { + if (log.type === "sql") { + return ( +
+

+ Request at {log.timestamp} + + Request duration: {log.overallTimeMs}ms + +

+
    + {log.queries.map((query, queryIndex) => ( +
  • +

    + Served by: {query.served_by} + + Query duration: {query.duration}ms + +

    +
    + {query.query + .split("\n") + .map((line: string, lineIndex: number) => ( +

    + {line} +

    + ))} +
    +
  • + ))} +
+
+ ); + } + return null; + })} +
); diff --git a/frontend/app/routes/employees.tsx b/frontend/app/routes/employees.tsx index 4007cee..11e6dc2 100644 --- a/frontend/app/routes/employees.tsx +++ b/frontend/app/routes/employees.tsx @@ -83,7 +83,7 @@ const Employees = () => {
employee avatar
diff --git a/frontend/app/routes/suppliers.tsx b/frontend/app/routes/suppliers.tsx index e1e7d5c..b050673 100644 --- a/frontend/app/routes/suppliers.tsx +++ b/frontend/app/routes/suppliers.tsx @@ -82,11 +82,9 @@ const Suppliers = () => {
supplier
diff --git a/worker/lib/api/customers.ts b/worker/lib/api/customers.ts index 6231bf2..0f99d7f 100644 --- a/worker/lib/api/customers.ts +++ b/worker/lib/api/customers.ts @@ -18,13 +18,12 @@ const apiCustomers = () => { [[itemsPerPage, (page - 1) * itemsPerPage]] ); try { - console.log(stmts); + const startTime = Date.now(); const response: D1Result[] = await env.DB.batch( stmts as D1PreparedStatement[] ); - console.log(response); - console.log("response[0]:", response[0]); - console.log("response[1]:", response[1]); + const overallTimeMs = Date.now() - startTime; + const first = response[0]; const total = count && first.results ? (first.results[0] as any).total : 0; @@ -40,7 +39,7 @@ const apiCustomers = () => { queries: stmts.length, results: customers.length + (count ? 1 : 0), select: stmts.length, - log: createSQLLog(sql, response), + log: createSQLLog(sql, response, overallTimeMs), }, customers: customers, }; @@ -67,13 +66,17 @@ const apiCustomer = () => { [[id]] ); try { + const startTime = Date.now(); const customer: any = await (stmts[0] as D1PreparedStatement).all(); + const overallTimeMs = Date.now() - startTime; + return { stats: { queries: 1, results: 1, select: 1, - log: createSQLLog(sql, [customer]), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, [customer], overallTimeMs), }, customer: customer.results[0], }; diff --git a/worker/lib/api/employees.ts b/worker/lib/api/employees.ts index 82c90d4..eda55c4 100644 --- a/worker/lib/api/employees.ts +++ b/worker/lib/api/employees.ts @@ -18,9 +18,12 @@ const apiEmployees = () => { [[itemsPerPage, (page - 1) * itemsPerPage]] ); try { + const startTime = Date.now(); const response: D1Result[] = await env.DB.batch( stmts as D1PreparedStatement[] ); + const overallTimeMs = Date.now() - startTime; + const first = response[0]; const total = count && first.results ? (first.results[0] as any).total : 0; @@ -36,7 +39,8 @@ const apiEmployees = () => { queries: stmts.length, results: employees.length + (count ? 1 : 0), select: stmts.length, - log: createSQLLog(sql, response), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, response, overallTimeMs), }, employees: employees, }; @@ -63,13 +67,17 @@ const apiEmployee = () => { [[id]] ); try { + const startTime = Date.now(); const employee: any = await (stmts[0] as D1PreparedStatement).all(); + const overallTimeMs = Date.now() - startTime; + return { stats: { queries: 1, results: 1, select_leftjoin: 1, - log: createSQLLog(sql, [employee]), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, [employee], overallTimeMs), }, employee: employee.results[0], }; diff --git a/worker/lib/api/orders.ts b/worker/lib/api/orders.ts index 32d9cca..3d0f8d2 100644 --- a/worker/lib/api/orders.ts +++ b/worker/lib/api/orders.ts @@ -18,9 +18,12 @@ const apiOrders = () => { [[itemsPerPage, (page - 1) * itemsPerPage]] ); try { + const startTime = Date.now(); const response: D1Result[] = await env.DB.batch( stmts as D1PreparedStatement[] ); + const overallTimeMs = Date.now() - startTime; + const first = response[0]; const total = count && first.results ? (first.results[0] as any).total : 0; @@ -36,7 +39,8 @@ const apiOrders = () => { queries: stmts.length, results: orders.length + (count ? 1 : 0), select: stmts.length, - log: createSQLLog(sql, response), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, response, overallTimeMs), }, orders: orders, }; @@ -65,7 +69,10 @@ const apiOrder = () => { ); try { + const startTime = Date.now(); const response = await env.DB.batch(stmts as D1PreparedStatement[]); + const overallTimeMs = Date.now() - startTime; + const orders: any = response[0].results; const products: any = response[1].results; return { @@ -74,7 +81,8 @@ const apiOrder = () => { results: products.length + 1, select: stmts.length, select_where: stmts.length, - log: createSQLLog(sql, response), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, response, overallTimeMs), }, order: orders ? orders[0] : {}, products: products, diff --git a/worker/lib/api/products.ts b/worker/lib/api/products.ts index 0071e44..3b86f3d 100644 --- a/worker/lib/api/products.ts +++ b/worker/lib/api/products.ts @@ -18,9 +18,12 @@ const apiProducts = () => { [[itemsPerPage, (page - 1) * itemsPerPage]] ); try { + const startTime = Date.now(); const response: D1Result[] = await env.DB.batch( stmts as D1PreparedStatement[] ); + const overallTimeMs = Date.now() - startTime; + const first = response[0]; const total = count && first.results ? (first.results[0] as any).total : 0; @@ -36,7 +39,8 @@ const apiProducts = () => { queries: stmts.length, results: products.length + (count ? 1 : 0), select: stmts.length, - log: createSQLLog(sql, response), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, response, overallTimeMs), }, products: products, }; @@ -63,15 +67,19 @@ const apiProduct = () => { ], [[id]] ); + const startTime = Date.now(); const product: D1Result = await ( stmts[0] as D1PreparedStatement ).all(); + const overallTimeMs = Date.now() - startTime; + return { stats: { queries: 1, results: 1, select: 1, - log: createSQLLog(sql, [product]), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, [product], overallTimeMs), }, product: product.results ? product.results[0] : {}, }; diff --git a/worker/lib/api/search.ts b/worker/lib/api/search.ts index ac0869e..b1d08ab 100644 --- a/worker/lib/api/search.ts +++ b/worker/lib/api/search.ts @@ -21,7 +21,10 @@ const apiSearch = () => { ); try { + const startTime = Date.now(); const search = await (stmts[0] as D1PreparedStatement).all(); + const overallTimeMs = Date.now() - startTime; + return { items: itemsPerPage, stats: { @@ -29,7 +32,8 @@ const apiSearch = () => { results: search.results ? search.results.length : 0, select_fts: 0, select_where: 1, - log: createSQLLog(sql, [search]), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, [search], overallTimeMs), }, results: search.results, }; diff --git a/worker/lib/api/suppliers.ts b/worker/lib/api/suppliers.ts index abd05eb..cbab13e 100644 --- a/worker/lib/api/suppliers.ts +++ b/worker/lib/api/suppliers.ts @@ -18,9 +18,11 @@ const apiSuppliers = () => { [[itemsPerPage, (page - 1) * itemsPerPage]] ); try { + const startTime = Date.now(); const response: D1Result[] = await env.DB.batch( stmts as D1PreparedStatement[] ); + const overallTimeMs = Date.now() - startTime; const first = response[0]; const total = count && first.results ? (first.results[0] as any).total : 0; @@ -36,7 +38,8 @@ const apiSuppliers = () => { queries: stmts.length, results: suppliers.length + (count ? 1 : 0), select: stmts.length, - log: createSQLLog(sql, response), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, response, overallTimeMs), }, suppliers: suppliers, }; @@ -63,15 +66,18 @@ const apiSupplier = () => { ], [[id]] ); + const startTime = Date.now(); const supplier: D1Result = await ( stmts[0] as D1PreparedStatement ).all(); + const overallTimeMs = Date.now() - startTime; return { stats: { queries: 1, results: 1, select: 1, - log: createSQLLog(sql, [supplier]), + overallTimeMs: overallTimeMs, + log: createSQLLog(sql, [supplier], overallTimeMs), }, supplier: supplier.results ? supplier.results[0] : {}, }; diff --git a/worker/lib/tools.ts b/worker/lib/tools.ts index c907109..a57f243 100644 --- a/worker/lib/tools.ts +++ b/worker/lib/tools.ts @@ -17,19 +17,36 @@ const mime_types = [ }, ]; -const createSQLLog = (statements: any, response: any) => { - let logs = []; - for (let l in response) { - logs.push({ - type: "sql", - served_by: response[l].meta.served_by, - query: statements[l], - duration: response[l].meta.duration, - ts: new Date().toISOString(), - }); - } +interface SQLQueryLog { + query: string; + served_by: string; + duration: number; +} + +export interface SQLRequestEvent { + type: "sql"; + timestamp: string; + queries: SQLQueryLog[]; + overallTimeMs: number; +} + +const createSQLLog = ( + statements: string[], + response: any[], + overallTimeMs: number +): SQLRequestEvent => { + const queries = response.map((res, index) => ({ + query: statements[index], + served_by: res.meta.served_by, + duration: res.meta.duration, + })); - return logs; + return { + type: "sql", + timestamp: new Date().toISOString(), + queries, + overallTimeMs, + }; }; const getMime = (file: string) => { @@ -53,7 +70,7 @@ const prepareStatements = ( countTable: string | false, query: Array, values: Array -) => { +): [D1PreparedStatement[], string[]] => { var stmts: D1PreparedStatement[] = []; var sql = []; if (countTable) {