Skip to content

Commit 1729051

Browse files
authored
chore: Single log line for each request (#705)
1 parent 921449d commit 1729051

File tree

4 files changed

+69
-93
lines changed

4 files changed

+69
-93
lines changed

src/server/middleware/adminRoutes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { createBullBoard } from "@bull-board/api";
22
import { BullMQAdapter } from "@bull-board/api/bullMQAdapter";
33
import { FastifyAdapter } from "@bull-board/fastify";
44
import fastifyBasicAuth from "@fastify/basic-auth";
5-
import { Queue } from "bullmq";
5+
import type { Queue } from "bullmq";
66
import { timingSafeEqual } from "crypto";
7-
import { FastifyInstance } from "fastify";
7+
import type { FastifyInstance } from "fastify";
88
import { StatusCodes } from "http-status-codes";
99
import { env } from "../../utils/env";
1010
import { CancelRecycledNoncesQueue } from "../../worker/queues/cancelRecycledNoncesQueue";

src/server/middleware/error.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { stringify } from "thirdweb/utils";
44
import { ZodError } from "zod";
55
import { env } from "../../utils/env";
66
import { parseEthersError } from "../../utils/ethers";
7-
import { logger } from "../../utils/logger";
87

98
export type CustomError = {
109
message: string;
@@ -63,13 +62,6 @@ const isZodError = (err: unknown): boolean => {
6362
export const withErrorHandler = async (server: FastifyInstance) => {
6463
server.setErrorHandler(
6564
(error: Error | CustomError | ZodError, request, reply) => {
66-
logger({
67-
service: "server",
68-
level: "error",
69-
message: `Encountered server error`,
70-
error,
71-
});
72-
7365
// Ethers Error Codes
7466
if (parseEthersError(error)) {
7567
return reply.status(StatusCodes.BAD_REQUEST).send({

src/server/middleware/logs.ts

Lines changed: 57 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,70 @@
1-
import { FastifyInstance } from "fastify";
1+
import type { FastifyInstance } from "fastify";
2+
import { stringify } from "thirdweb/utils";
23
import { logger } from "../../utils/logger";
4+
import { ADMIN_QUEUES_BASEPATH } from "./adminRoutes";
5+
6+
const SKIP_LOG_PATHS = new Set([
7+
"",
8+
"/",
9+
"/favicon.ico",
10+
"/system/health",
11+
"/json",
12+
"/static",
13+
// Skip these routes case of importing sensitive details.
14+
"/backend-wallet/import",
15+
"/configuration/wallets",
16+
]);
317

418
export const withRequestLogs = async (server: FastifyInstance) => {
5-
server.addHook("onRequest", async (request, reply) => {
19+
server.addHook("onSend", (request, reply, payload, done) => {
620
if (
7-
!request.routerPath?.includes("static") &&
8-
!request.routerPath?.includes("json") &&
9-
request.method !== "OPTIONS" &&
10-
request.routerPath !== "/"
21+
request.method === "OPTIONS" ||
22+
!request.routeOptions.url ||
23+
SKIP_LOG_PATHS.has(request.routeOptions.url) ||
24+
request.routeOptions.url.startsWith(ADMIN_QUEUES_BASEPATH)
1125
) {
12-
logger({
13-
service: "server",
14-
level: "info",
15-
message: `Request received - ${request.method} - ${request.routerPath}`,
16-
});
26+
done();
27+
return;
1728
}
1829

19-
if (process.env.NODE_ENV === "production") {
20-
if (
21-
request.routerPath?.includes("static") &&
22-
// Bullboard requires access to static bundle files
23-
!request.routerPath?.startsWith("/admin/queues")
24-
) {
25-
return reply.status(404).send({
26-
statusCode: 404,
27-
error: "Not Found",
28-
message: "Not Found",
29-
});
30-
}
31-
}
32-
});
30+
const { method, routeOptions, headers, params, query, body } = request;
31+
const { statusCode, elapsedTime } = reply;
32+
const isError = statusCode >= 400;
3333

34-
server.addHook("preHandler", async (request, reply) => {
35-
if (
36-
!request.routerPath?.includes("static") &&
37-
!request.routerPath?.includes("json") &&
38-
!request.routerPath?.includes("/backend-wallet/import") &&
39-
request.method !== "OPTIONS"
40-
) {
41-
if (request.body && Object.keys(request.body).length > 0) {
42-
logger({
43-
service: "server",
44-
level: "info",
45-
message: `Request body - ${request.method} - ${request.routerPath}`,
46-
data: request.body,
47-
});
48-
}
34+
const extractedHeaders = {
35+
"x-backend-wallet-address": headers["x-backend-wallet-address"],
36+
"x-idempotency-key": headers["x-idempotency-key"],
37+
"x-account-address": headers["x-account-address"],
38+
"x-account-factory-address": headers["x-account-factory-address"],
39+
};
4940

50-
if (request.params && Object.keys(request.params).length > 0) {
51-
logger({
52-
service: "server",
53-
level: "info",
54-
message: `Request params - ${request.method}`,
55-
data: request.params,
56-
});
57-
}
41+
const paramsStr =
42+
params && Object.keys(params).length
43+
? `params=${stringify(params)}`
44+
: undefined;
45+
const queryStr =
46+
query && Object.keys(query).length
47+
? `querystring=${stringify(query)}`
48+
: undefined;
49+
const bodyStr =
50+
body && Object.keys(body).length ? `body=${stringify(body)}` : undefined;
51+
const payloadStr = isError ? `payload=${payload}` : undefined;
5852

59-
if (request.query && Object.keys(request.query).length > 0) {
60-
logger({
61-
service: "server",
62-
level: "info",
63-
message: `Request querystring - ${request.method} - ${request.routerPath}`,
64-
data: request.query,
65-
});
66-
}
67-
}
68-
});
69-
70-
server.addHook("onResponse", (request, reply, done) => {
71-
if (
72-
!request.routerPath?.includes("static") &&
73-
!request.routerPath?.includes("json") &&
74-
request.method !== "OPTIONS" &&
75-
request.routerPath !== "/"
76-
) {
77-
logger({
78-
service: "server",
79-
level: "info",
80-
message: `Request completed - ${request.method} - ${
81-
reply.request.routerPath
82-
} - status code: ${reply.statusCode} - Response time: ${reply
83-
.getResponseTime()
84-
.toFixed(2)}ms`,
85-
});
86-
}
53+
logger({
54+
service: "server",
55+
level: isError ? "error" : "info",
56+
message: [
57+
`[Request complete - ${statusCode}]`,
58+
`method=${method}`,
59+
`path=${routeOptions.url}`,
60+
`headers=${stringify(extractedHeaders)}`,
61+
paramsStr,
62+
queryStr,
63+
bodyStr,
64+
`duration=${elapsedTime.toFixed(1)}ms`,
65+
payloadStr,
66+
].join(" "),
67+
});
8768

8869
done();
8970
});

src/utils/usage.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Static } from "@sinclair/typebox";
22
import { UsageEvent } from "@thirdweb-dev/service-utils/cf-worker";
33
import { FastifyInstance } from "fastify";
44
import { Address, Hex } from "thirdweb";
5+
import { ADMIN_QUEUES_BASEPATH } from "../server/middleware/adminRoutes";
56
import { contractParamSchema } from "../server/schemas/sharedApiSchemas";
67
import { walletWithAddressParamSchema } from "../server/schemas/wallet";
78
import { getChainIdFromChain } from "../server/utils/chain";
@@ -44,29 +45,31 @@ const ANALYTICS_DEFAULT_HEADERS = {
4445
} as HeadersInit;
4546

4647
const SKIP_USAGE_PATHS = new Set([
48+
"",
4749
"/",
4850
"/favicon.ico",
4951
"/system/health",
5052
"/json",
5153
"/static",
52-
"",
5354
]);
5455

5556
export const withServerUsageReporting = (server: FastifyInstance) => {
56-
// Skip reporting if CLIENT_ANALYTICS_URL is not set.
57+
// Skip reporting if CLIENT_ANALYTICS_URL is unset.
5758
if (env.CLIENT_ANALYTICS_URL === "") {
5859
return;
5960
}
6061

6162
server.addHook("onResponse", async (request, reply) => {
6263
if (
63-
SKIP_USAGE_PATHS.has(reply.request.routerPath) ||
64-
reply.request.method === "OPTIONS"
64+
request.method === "OPTIONS" ||
65+
!request.routeOptions.url ||
66+
SKIP_USAGE_PATHS.has(request.routeOptions.url) ||
67+
request.routeOptions.url.startsWith(ADMIN_QUEUES_BASEPATH)
6568
) {
6669
return;
6770
}
6871

69-
const requestParams = request?.params as
72+
const requestParams = request.params as
7073
| (Static<typeof contractParamSchema> &
7174
Static<typeof walletWithAddressParamSchema>)
7275
| undefined;
@@ -79,7 +82,7 @@ export const withServerUsageReporting = (server: FastifyInstance) => {
7982
source: "engine",
8083
action: "api_request",
8184
clientId: thirdwebClientId,
82-
pathname: reply.request.routerPath,
85+
pathname: reply.request.routeOptions.url,
8386
chainId,
8487
walletAddress: requestParams?.walletAddress,
8588
contractAddress: requestParams?.contractAddress,
@@ -97,7 +100,7 @@ export const withServerUsageReporting = (server: FastifyInstance) => {
97100
};
98101

99102
export const reportUsage = (usageEvents: ReportUsageParams[]) => {
100-
// Skip reporting if CLIENT_ANALYTICS_URL is not set.
103+
// Skip reporting if CLIENT_ANALYTICS_URL is unset.
101104
if (env.CLIENT_ANALYTICS_URL === "") {
102105
return;
103106
}

0 commit comments

Comments
 (0)