Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve logging messages #25

Merged
merged 2 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { config } from "./src/config.js";
import { logger } from "./src/logger.js";
import GET from "./src/fetch/GET.js";
import * as prometheus from "./src/prometheus.js";

if (config.verbose) logger.enable();
import { APIError } from "./src/fetch/utils.js";

const app = Bun.serve({
hostname: config.hostname,
port: config.port,
fetch(req: Request) {
let pathname = new URL(req.url).pathname;
if (req.method === "GET") return GET(req);
prometheus.request_error.inc({ pathname: new URL(req.url).pathname, status: 400 });
return new Response("Invalid request", { status: 400 });
return APIError(pathname, 405, "invalid_request_method", "Invalid request method, only GET allowed");
}
});

Expand Down
4 changes: 1 addition & 3 deletions src/clickhouse/makeQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ export async function makeQuery<T = unknown>(query: string) {
prometheus.bytes_read.inc(data.statistics.bytes_read);
prometheus.rows_read.inc(data.statistics.rows_read);
prometheus.elapsed.inc(data.statistics.elapsed);
logger.info({ query, statistics: data.statistics, rows: data.rows });
logger.trace("<makeQuery>\n", { query, statistics: data.statistics, rows: data.rows });

return data;
} catch (e: any) {
logger.error(e.message);

throw new Error(e.message);
}
}
2 changes: 2 additions & 0 deletions src/clickhouse/ping.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { PingResult } from "@clickhouse/client-web";
import client from "./createClient.js";
import { logger } from "../logger.js";

// Does not work with Bun's implementation of Node streams.
export async function ping(): Promise<PingResult> {
try {
await client.exec({ query: "SELECT 1" });
logger.info("Successfully pinged database");
return { success: true };
} catch (err) {
const message = typeof err === "string" ? err : JSON.stringify(err);
Expand Down
2 changes: 2 additions & 0 deletions src/fetch/GET.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import swaggerFavicon from "../../swagger/favicon.png"
import transfers from "./transfers.js";
import { APIError, toJSON } from "./utils.js";
import { APP_VERSION } from "../config.js";
import { logger } from "../logger.js";

export default async function (req: Request) {
const { pathname } = new URL(req.url);
logger.trace(`Incoming request: [${pathname}]`)
prometheus.request.inc({ pathname });

// Landing page
Expand Down
36 changes: 16 additions & 20 deletions src/fetch/balance.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { makeQuery } from "../clickhouse/makeQuery.js";
import { logger } from "../logger.js";
import { getBalanceChanges } from "../queries.js";
import * as prometheus from "../prometheus.js";
import { APIError, addMetadata, toJSON } from "./utils.js";
import { parseLimit, parsePage } from "../utils.js";

Expand All @@ -13,25 +12,25 @@ function verifyParams(searchParams: URLSearchParams) {
}

export default async function (req: Request) {
try {
const { pathname, searchParams } = new URL(req.url);
logger.info({ searchParams: Object.fromEntries(Array.from(searchParams)) });
const { pathname, searchParams } = new URL(req.url);
logger.trace("<balance>\n", { searchParams: Object.fromEntries(Array.from(searchParams)) });

try {
verifyParams(searchParams);
} catch (e: any) {
return APIError(pathname, 400, "bad_query_input", e.message);
}
try {
verifyParams(searchParams);
} catch (e: any) {
return APIError(pathname, 400, "bad_query_input", e.message);
}

const query = getBalanceChanges(searchParams);
let response;
const query = getBalanceChanges(searchParams);
let response;

try {
response = await makeQuery(query);
} catch (e: any) {
return APIError(pathname, 500, "failed_database_query", e.message);
}
try {
response = await makeQuery(query);
} catch (e: any) {
return APIError(pathname, 500, "failed_database_query", e.message);
}

try {
return toJSON(
addMetadata(
response,
Expand All @@ -40,9 +39,6 @@ export default async function (req: Request) {
)
);
} catch (e: any) {
logger.error(e);
prometheus.request_error.inc({ pathname: "/balance", status: 400 });

return new Response(e.message, { status: 400 });
return APIError(pathname, 500, "failed_response", e.message);
}
}
9 changes: 7 additions & 2 deletions src/fetch/head.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import { makeQuery } from "../clickhouse/makeQuery.js";

export default async function (req: Request) {
let query = "SELECT block_num FROM cursors ORDER BY block_num DESC LIMIT 1";
let pathname = new URL(req.url).pathname;
let response;

try {
response = await makeQuery(query);
} catch (e: any) {
return APIError(new URL(req.url).pathname, 500, "failed_database_query", e.message);
return APIError(pathname, 500, "failed_database_query", e.message);
}

return toJSON(addMetadata(response));
try {
return toJSON(addMetadata(response));
} catch (e: any) {
return APIError(pathname, 500, "failed_response", e.message);
}
}
23 changes: 8 additions & 15 deletions src/fetch/health.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import client from "../clickhouse/createClient.js";
import { logger } from "../logger.js";
import * as prometheus from "../prometheus.js";
import { APIError } from "./utils.js";

// TODO: Add log entry
export default async function (_req: Request) {
try {
const response = await client.ping();

if (response.success === false) throw new Error(response.error.message);
if (response.success === true) return new Response("OK");

return new Response("Unknown response from ClickHouse");
} catch (e: any) {
logger.error(e);
prometheus.request_error.inc({ pathname: "/health", status: 503 });

return new Response(e.message, { status: 503 });
export default async function (req: Request) {
const response = await client.ping();

if (!response.success) {
return APIError(new URL(req.url).pathname, 503, "failed_ping_database", response.error.message);
}

return new Response("OK");
}
2 changes: 2 additions & 0 deletions src/fetch/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { registry } from "../prometheus.js";
import { makeQuery } from "../clickhouse/makeQuery.js";
import { getBalanceChanges, getTotalSupply, getTransfers } from "../queries.js";
import { APIError, addMetadata } from "./utils.js";
import { logger } from "../logger.js";
const TAGS = {
MONITORING: "Monitoring",
HEALTH: "Health",
Expand All @@ -29,6 +30,7 @@ const head_example = addMetadata({
}
});

logger.debug("Querying examples for OpenAPI...");
const supply_example = await makeQuery(
getTotalSupply(new URLSearchParams({ limit: "1" }), true)
).then(
Expand Down
36 changes: 16 additions & 20 deletions src/fetch/supply.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { makeQuery } from "../clickhouse/makeQuery.js";
import { logger } from "../logger.js";
import { getTotalSupply } from "../queries.js";
import * as prometheus from "../prometheus.js";
import { APIError, addMetadata, toJSON } from "./utils.js";
import { parseLimit, parsePage } from "../utils.js";

Expand All @@ -13,25 +12,25 @@ function verifyParams(searchParams: URLSearchParams) {
}

export default async function (req: Request) {
try {
const { pathname, searchParams } = new URL(req.url);
logger.info({ searchParams: Object.fromEntries(Array.from(searchParams)) });
const { pathname, searchParams } = new URL(req.url);
logger.trace("<supply>\n", { searchParams: Object.fromEntries(Array.from(searchParams)) });

try {
verifyParams(searchParams);
} catch (e: any) {
return APIError(pathname, 400, "bad_query_input", e.message);
}
try {
verifyParams(searchParams);
} catch (e: any) {
return APIError(pathname, 400, "bad_query_input", e.message);
}

const query = getTotalSupply(searchParams);
let response;
const query = getTotalSupply(searchParams);
let response;

try {
response = await makeQuery(query);
} catch (e: any) {
return APIError(pathname, 500, "failed_database_query", e.message);
}
try {
response = await makeQuery(query);
} catch (e: any) {
return APIError(pathname, 500, "failed_database_query", e.message);
}

try {
return toJSON(
addMetadata(
response,
Expand All @@ -40,9 +39,6 @@ export default async function (req: Request) {
)
);
} catch (e: any) {
logger.error(e);
prometheus.request_error.inc({ pathname: "/supply", status: 400 });

return new Response(e.message, { status: 400 });
return APIError(pathname, 500, "failed_response", e.message);
}
}
28 changes: 12 additions & 16 deletions src/fetch/transfers.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { makeQuery } from "../clickhouse/makeQuery.js";
import { logger } from "../logger.js";
import { getTransfers } from "../queries.js";
import * as prometheus from "../prometheus.js";
import { APIError, addMetadata, toJSON } from "./utils.js";
import { parseLimit, parsePage } from "../utils.js";

export default async function (req: Request) {
const { pathname, searchParams } = new URL(req.url);
logger.trace("<transfers>\n", { searchParams: Object.fromEntries(Array.from(searchParams)) });

const query = getTransfers(searchParams);
let response;

try {
const { pathname, searchParams } = new URL(req.url);
logger.info({ searchParams: Object.fromEntries(Array.from(searchParams)) });

const query = getTransfers(searchParams);
let response;
response = await makeQuery(query);
} catch (e: any) {
return APIError(pathname, 500, "failed_database_query", e.message);
}

try {
response = await makeQuery(query);
} catch (e: any) {
return APIError(pathname, 500, "failed_database_query", e.message);
}

try {
return toJSON(
addMetadata(
response,
Expand All @@ -27,9 +26,6 @@ export default async function (req: Request) {
)
);
} catch (e: any) {
logger.error(e);
prometheus.request_error.inc({ pathname: "/transfers", status: 400 });

return new Response(e.message, { status: 400 });
return APIError(pathname, 500, "failed_response", e.message);
}
}
2 changes: 1 addition & 1 deletion src/fetch/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function APIError(pathname: string, status: number, code?: string, detail
detail: detail ? detail : ""
}

logger.error(api_error);
logger.error("<APIError>\n", api_error);
prometheus.request_error.inc({ pathname, status });
return toJSON(api_error, status);
}
Expand Down
7 changes: 5 additions & 2 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Logger, type ILogObj } from "tslog";
import { APP_NAME, APP_VERSION } from "./config.js";
import { APP_NAME, APP_VERSION, config } from "./config.js";

class TsLogger extends Logger<ILogObj> {
constructor() {
Expand All @@ -11,11 +11,14 @@ class TsLogger extends Logger<ILogObj> {
public enable(type: "pretty" | "json" = "pretty") {
this.settings.type = type;
this.settings.minLevel = 0;
this.info("Enabled logger");
}

public disable() {
this.settings.type = "hidden";
this.info("Disabled logger");
}
}

export const logger = new TsLogger();
export const logger = new TsLogger();
if (config.verbose) logger.enable();
6 changes: 4 additions & 2 deletions src/prometheus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ export const registry = new client.Registry();
export function registerCounter(name: string, help = "help", labelNames: string[] = [], config?: CounterConfiguration<string>) {
try {
registry.registerMetric(new Counter({ name, help, labelNames, ...config }));
logger.debug(`Registered new counter metric: ${name}`);
return registry.getSingleMetric(name) as Counter;
} catch (e) {
logger.error({ name, e });
logger.error("Error registering counter:", { name, e });
throw new Error(`${e}`);
}
}

export function registerGauge(name: string, help = "help", labelNames: string[] = [], config?: GaugeConfiguration<string>) {
try {
registry.registerMetric(new Gauge({ name, help, labelNames, ...config }));
logger.debug(`Registered new gauge metric: ${name}`);
return registry.getSingleMetric(name) as Gauge;
} catch (e) {
logger.error({ name, e });
logger.error("Error registering gauge:", { name, e });
throw new Error(`${e}`);
}
}
Expand Down
Loading