Skip to content

Commit

Permalink
* Centralize logger creation
Browse files Browse the repository at this point in the history
* Refine "ping" calculations
  • Loading branch information
danthonywalker committed Oct 18, 2023
1 parent 2c97e98 commit 73ba504
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 76 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/.env
/LICENSE
/README.md
/build
/dump.sql
/flyway

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.env
/build
/dump.sql

# JetBrains
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.env
/build
/dump.sql

# Git
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ RUN npm ci
COPY . .

RUN npm run check \
&& npx tsc
&& npm run build

CMD node --no-warnings --enable-source-maps build/index.js
CMD npm run production
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@
"typescript": "5.2.2"
},
"license": "MIT",
"private": true,
"name": "pedestrian",
"private": true,
"scripts": {
"build": "shx rm -rf ./build && tsc",
"check": "tsc --noemit && eslint . && prettier --check .",
"debug": "node --trace-warnings --enable-source-maps ./build/index.js | pino-pretty",
"dump": "docker exec --tty postgres pg_dumpall --clean --username=user > dump.sql",
"migrate": "docker-compose up --detach --build flyway",
"prettier": "prettier --write .",
"production": "node --no-warnings --enable-source-maps ./build/index.js",
"restore": "shx cat dump.sql | docker exec --interactive postgres psql --username=user --dbname=postgres",
"start": "docker-compose up --detach --build pedestrian"
"services": "docker-compose up --detach postgres redis flyway",
"start": "docker-compose up --build pedestrian"
}
}
6 changes: 2 additions & 4 deletions src/commands/carsized/carsized.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ import type { Index } from "lunr";

import lunr from "lunr";
import assert from "node:assert";
import loggerFactory from "pino";

import type { Car, CompareCars } from "./types";

import loggerFactory from "../../logger.factory";
import Environment from "../../shared/environment";
import { isNonNullable } from "../../shared/nullable";
import { usePage } from "../../shared/puppeteer";
import RedisKey, * as redis from "../../shared/redis";
import { Perspective } from "./constants";

const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

const CarsizedBaseUrl = "https://www.carsized.com/en";

Expand Down
6 changes: 2 additions & 4 deletions src/commands/carsized/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import type {
} from "discord.js";

import { AttachmentBuilder } from "discord.js";
import loggerFactory from "pino";

import type { CompareCars } from "./types";

import loggerFactory from "../../logger.factory";
import Session from "../../session";
import * as carsized from "./carsized.manager";
import UI from "./ui";
Expand All @@ -20,9 +20,7 @@ export type Context = CompareCars & {
type Interaction = CommandInteraction | MessageComponentInteraction;
// endregion

const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

const session = new Session<Context>();
export default session;
Expand Down
6 changes: 2 additions & 4 deletions src/commands/surveys/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { BaseInteraction } from "discord.js";

import { messageLink } from "discord.js";
import assert from "node:assert";
import loggerFactory from "pino";

import type {
Answer,
Expand All @@ -16,11 +15,10 @@ import type {
Survey,
} from "./types";

import loggerFactory from "../../logger.factory";
import { QuestionType } from "./constants";

const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

// region Survey
export const surveyLink = ({ channelId, guildId, id }: PartialSurvey) =>
Expand Down
6 changes: 2 additions & 4 deletions src/creators/post/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import {
roleMention,
} from "discord.js";
import assert from "node:assert";
import loggerFactory from "pino";

import type Nullable from "../../shared/nullable";
import type { CreatorType } from "../constants";
import type { CreatorSubscription } from "./database";

import loggerFactory from "../../logger.factory";
import { byDate, isUnique } from "../../shared/array";
import discord from "../../shared/discord";
import { isNullable } from "../../shared/nullable";
Expand All @@ -35,9 +35,7 @@ export type Option = {
type Poster = (creatorDomainId: string) => Promise<Option[]>;
// endregion

const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

const posters = new Map<CreatorType, Poster>();
export const registerPoster = (creatorType: CreatorType, poster: Poster) => {
Expand Down
6 changes: 2 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { glob } from "glob";
import path from "node:path";
import loggerFactory from "pino";
import { collectDefaultMetrics } from "prom-client";

import loggerFactory from "./logger.factory";
import discord from "./shared/discord";
import Environment from "./shared/environment";
import express from "./shared/express";

// region Logger and Metrics
const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

collectDefaultMetrics();
// endregion
Expand Down
17 changes: 17 additions & 0 deletions src/logger.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import path from "node:path";
import pino from "pino";

export default ({ filename }: NodeModule) =>
pino({
errorKey: "error",
formatters: {
bindings: () => ({
name: path.relative(__dirname, filename),
}),
level: (label) => ({
level: label,
}),
},
level: "debug",
messageKey: "message",
});
88 changes: 48 additions & 40 deletions src/shared/discord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,38 @@ import type {
BaseInteraction,
CommandInteraction,
ContextMenuCommandBuilder,
InteractionResponse,
Message,
MessageComponentInteraction,
ModalSubmitInteraction,
SlashCommandBuilder,
} from "discord.js";

import { Client, Events, Routes, User } from "discord.js";
import {
Client,
Events,
InteractionResponse,
Message,
Routes,
User,
} from "discord.js";
import assert from "node:assert";
import loggerFactory from "pino";
import { Histogram } from "prom-client";
import { Gauge, Histogram } from "prom-client";

import loggerFactory from "../logger.factory";

// region Logger and Metrics
const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

const interactionRequestDuration = new Histogram({
help: "Interaction request duration in milliseconds",
labelNames: ["status", "handler"],
name: "interaction_request_duration_milliseconds",
});

const shardPing = new Gauge({
help: "Shard ping in milliseconds",
labelNames: ["shard"],
name: "shard_ping_milliseconds",
});
// endregion

// region Constants
Expand All @@ -41,8 +51,16 @@ const discord = new Client({
intents: ["Guilds"],
});

const { ws } = discord;
const { shards } = ws;

discord.on(Events.Debug, (debug) => {
logger.debug(debug, "DISCORD_DEBUG");

for (const [shard, { ping }] of shards) {
const labels = { shard };
shardPing.set(labels, ping);
}
});

discord.on(Events.Warn, (warn) => {
Expand Down Expand Up @@ -171,14 +189,18 @@ const getHandler = (interaction: BaseInteraction, uiid?: string) => {
const onInteraction = (
status: "error" | "success",
interaction: BaseInteraction,
startRequestTime: number,
uiid?: string,
) => {
const handler = getHandler(interaction, uiid);
const labels = { handler, status };

return (result: unknown) => {
const endRequestTime = performance.now();
const endRequestTime =
result instanceof InteractionResponse || result instanceof Message
? result.createdTimestamp
: Date.now();

const startRequestTime = interaction.createdTimestamp;
const requestDuration = endRequestTime - startRequestTime;
interactionRequestDuration.observe(labels, requestDuration);

Expand All @@ -200,37 +222,28 @@ const onInteraction = (
};
};

const onCommand = (
interaction: CommandInteraction,
startRequestTime: number,
) => {
const onCommand = (interaction: CommandInteraction) => {
for (const [name, { onCommand }] of commands) {
if (name === interaction.commandName) {
return onCommand(interaction)
.then(onInteraction("success", interaction, startRequestTime))
.catch(onInteraction("error", interaction, startRequestTime));
.then(onInteraction("success", interaction))
.catch(onInteraction("error", interaction));
}
}
};

const onAutocomplete = (
interaction: AutocompleteInteraction,
startRequestTime: number,
) => {
const onAutocomplete = (interaction: AutocompleteInteraction) => {
for (const [name, { onAutocomplete }] of commands) {
if (name === interaction.commandName) {
assert(onAutocomplete !== undefined);
return onAutocomplete(interaction)
.then(onInteraction("success", interaction, startRequestTime))
.catch(onInteraction("error", interaction, startRequestTime));
.then(onInteraction("success", interaction))
.catch(onInteraction("error", interaction));
}
}
};

const onMessageComponent = (
interaction: MessageComponentInteraction,
startRequestTime: number,
) => {
const onMessageComponent = (interaction: MessageComponentInteraction) => {
let { customId } = interaction;
for (const [uiid, onComponent] of components) {
const legacyPrefix = `GLOBAL_${uiid}_`;
Expand All @@ -242,39 +255,34 @@ const onMessageComponent = (
if (customId.startsWith(uiid)) {
const id = customId.slice(uiid.length);
return onComponent(interaction, id)
.then(onInteraction("success", interaction, startRequestTime, uiid))
.catch(onInteraction("error", interaction, startRequestTime, uiid));
.then(onInteraction("success", interaction, uiid))
.catch(onInteraction("error", interaction, uiid));
}
}
};

const onModalSubmit = (
interaction: ModalSubmitInteraction,
startRequestTime: number,
) => {
const onModalSubmit = (interaction: ModalSubmitInteraction) => {
const { customId } = interaction;
for (const [uiid, onModal] of modals) {
if (customId.startsWith(uiid)) {
const id = customId.slice(uiid.length);
return onModal(interaction, id)
.then(onInteraction("success", interaction, startRequestTime, uiid))
.catch(onInteraction("error", interaction, startRequestTime, uiid));
.then(onInteraction("success", interaction, uiid))
.catch(onInteraction("error", interaction, uiid));
}
}
};

discord.on(Events.InteractionCreate, async (interaction) => {
const startRequestTime = performance.now();

let status;
if (interaction.isCommand()) {
status = await onCommand(interaction, startRequestTime);
status = await onCommand(interaction);
} else if (interaction.isAutocomplete()) {
status = await onAutocomplete(interaction, startRequestTime);
status = await onAutocomplete(interaction);
} else if (interaction.isMessageComponent()) {
status = await onMessageComponent(interaction, startRequestTime);
status = await onMessageComponent(interaction);
} else if (interaction.isModalSubmit()) {
status = await onModalSubmit(interaction, startRequestTime);
status = await onModalSubmit(interaction);
}

assert(status !== undefined);
Expand Down
7 changes: 3 additions & 4 deletions src/shared/express.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import express from "express";
import promBundle from "express-prom-bundle";
import loggerFactory from "pino";
import pinoBundle from "pino-http";

import loggerFactory from "../logger.factory";

const server = express();

// region Logger and Metrics
const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

server.use(
promBundle({
Expand Down
6 changes: 2 additions & 4 deletions src/shared/postgresql.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import type { PoolClient } from "pg";

import { Pool } from "pg";
import loggerFactory from "pino";
import { Histogram } from "prom-client";

import type { Caller } from "./caller";

import loggerFactory from "../logger.factory";
import Environment from "./environment";

// region Types
type Callback<T> = (client: PoolClient) => Promise<T>;
// endregion

// region Logger and Metrics
const logger = loggerFactory({
name: __filename,
});
const logger = loggerFactory(module);

const databaseRequestDuration = new Histogram({
help: "Database request duration in milliseconds",
Expand Down
Loading

0 comments on commit 73ba504

Please sign in to comment.