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

Ensure pino-pretty works in built app and can be configured in browser #505

Merged
merged 2 commits into from
Nov 28, 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
2 changes: 1 addition & 1 deletion apps/api/mvm.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"@akashnetwork/database": "1.0.0",
"@akashnetwork/env-loader": "1.0.1",
"@akashnetwork/http-sdk": "1.0.8",
"@akashnetwork/logging": "2.0.1"
"@akashnetwork/logging": "2.0.2"
}
}
1 change: 1 addition & 0 deletions apps/deploy-web/mvm.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"dependencies": {
"@akashnetwork/env-loader": "1.0.1",
"@akashnetwork/http-sdk": "1.0.8",
"@akashnetwork/logging": "2.0.2",
"@akashnetwork/network-store": "1.0.1",
"@akashnetwork/ui": "1.0.0"
},
Expand Down
20 changes: 16 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions packages/logging/package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"name": "@akashnetwork/logging",
"version": "2.0.1",
"version": "2.0.2",
"description": "Package containing logging tools",
"license": "ISC",
"author": "",
"main": "src/index.ts",
"scripts": {
"format": "prettier --write ./*.{ts,json} **/*.{ts,json}",
"lint": "eslint .",
"update-apps-local-deps": "mvm-update",
"test": "jest"
"test": "jest",
"update-apps-local-deps": "mvm-update"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/jest": "^29.5.14",
"dotenv": "^16.4.5",
Expand All @@ -19,14 +19,14 @@
"pino": "^9.5.0",
"pino-cloud-logging": "^1.0.6",
"pino-fluentd": "^0.2.4",
"pino-pretty": "^11.3.0",
"stream": "^0.0.3",
"ts-jest": "^29.1.4",
"zod": "^3.23.8"
},
"devDependencies": {
"@b12k/mvm": "^0.0.10",
"@types/http-errors": "^2.0.4",
"@types/node": "^22.8.6"
"@types/node": "^22.8.6",
"pino-pretty": "^11.3.0"
}
}
7 changes: 2 additions & 5 deletions packages/logging/src/config/env.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ dotenv.config();

const envSchema = z.object({
LOG_LEVEL: z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).optional().default("info"),
STD_OUT_LOG_FORMAT: z.enum(["json", "pretty"]).optional().default("json"),
FLUENTD_TAG: z.string().optional().default("pino"),
FLUENTD_HOST: z.string().optional(),
FLUENTD_PORT: z.number({ coerce: true }).optional().default(24224),
STD_OUT_LOG_FORMAT: z.enum(["json", "pretty"]).optional().default("json")
});

export const envConfig = envSchema.parse(process.env);
export const envConfig = envSchema.parse(process.env);
6 changes: 4 additions & 2 deletions packages/logging/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { envConfig } from "./env.config"
import { envConfig } from "./env.config";

export const config = {
...envConfig
}
};

export type Config = typeof config;
26 changes: 16 additions & 10 deletions packages/logging/src/servicies/logger/logger.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import createHttpError from "http-errors";
import pino from "pino";
import { Transform } from "node:stream";
import pino, { LoggerOptions } from "pino";
import { gcpLogOptions } from "pino-cloud-logging";

import { config } from "../../config";
Expand All @@ -12,6 +13,11 @@ jest.mock("pino-cloud-logging");

describe("LoggerService", () => {
const defaultLogFormat = config.STD_OUT_LOG_FORMAT;
const COMMON_EXPECTED_OPTIONS: LoggerOptions = {
level: "info",
mixin: undefined,
timestamp: expect.any(Function)
};

afterEach(() => {
config.STD_OUT_LOG_FORMAT = defaultLogFormat;
Expand All @@ -23,19 +29,19 @@ describe("LoggerService", () => {
config.STD_OUT_LOG_FORMAT = "pretty";
new LoggerService();

expect(pino).toHaveBeenCalledWith({
level: "info",
mixin: undefined,
transport: { target: "pino-pretty", options: { colorize: true, sync: true } }
});
expect(pino).toHaveBeenCalledWith(COMMON_EXPECTED_OPTIONS, expect.any(Transform));
expect(gcpLogOptions).not.toHaveBeenCalled();
});

it("should initialize pino without pretty formatting for other formats", () => {
config.STD_OUT_LOG_FORMAT = "json";
new LoggerService();

expect(pino).toHaveBeenCalledWith({ level: "info", mixin: undefined });
expect(pino).toHaveBeenCalledWith({
level: "info",
mixin: undefined,
timestamp: expect.any(Function)
});
expect(gcpLogOptions).toHaveBeenCalled();
});

Expand All @@ -46,7 +52,7 @@ describe("LoggerService", () => {
LoggerService.mixin = globalMixin;
new LoggerService();

expect(pino).toHaveBeenCalledWith({ level: "info", mixin: globalMixin });
expect(pino).toHaveBeenCalledWith({ ...COMMON_EXPECTED_OPTIONS, mixin: globalMixin });

LoggerService.mixin = undefined;
});
Expand All @@ -61,15 +67,15 @@ describe("LoggerService", () => {
LoggerService.mixin = globalMixin;
new LoggerService({ mixin: localMixin });

expect(pino).toHaveBeenCalledWith({ level: "info", mixin: localMixin });
expect(pino).toHaveBeenCalledWith({ ...COMMON_EXPECTED_OPTIONS, mixin: localMixin });

LoggerService.mixin = undefined;
});

it("should initialize pino with provided log level overriding global log level", () => {
new LoggerService({ level: "debug" });

expect(pino).toHaveBeenCalledWith({ level: "debug" });
expect(pino).toHaveBeenCalledWith({ ...COMMON_EXPECTED_OPTIONS, level: "debug" });

LoggerService.mixin = undefined;
});
Expand Down
55 changes: 38 additions & 17 deletions packages/logging/src/servicies/logger/logger.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { isHttpError } from "http-errors";
import pino from "pino";
import { gcpLogOptions } from "pino-cloud-logging";
import type { PinoPretty } from "pino-pretty";

import { config } from "../../config";
import { Config, config as envConfig } from "../../config";

export type Logger = Pick<pino.Logger, "info" | "error" | "warn" | "debug">;

Expand All @@ -15,6 +16,15 @@ interface LoggerOptions extends pino.LoggerOptions {
}

export class LoggerService implements Logger {
static config: Config = envConfig;

static configure(config: Partial<Config>) {
this.config = {
...this.config,
...config
};
}

static forContext(context: string) {
return new LoggerService().setContext(context);
}
Expand All @@ -23,38 +33,49 @@ export class LoggerService implements Logger {

protected pino: pino.Logger;

constructor(options?: LoggerOptions) {
this.pino = this.initPino(options);
constructor(private readonly options?: LoggerOptions) {
this.pino = this.initPino();
}

private initPino(inputOptions: LoggerOptions = {}): pino.Logger {
let options: LoggerOptions = {
level: config.LOG_LEVEL,
private initPino(): pino.Logger {
const options: LoggerOptions = {
level: LoggerService.config.LOG_LEVEL,
mixin: LoggerService.mixin,
timestamp: () => `,"time":"${new Date().toISOString()}"`,
...inputOptions
...this.options
};

if (typeof window === "undefined" && config.STD_OUT_LOG_FORMAT === "pretty") {
options.transport = {
target: "pino-pretty",
options: { colorize: true, sync: true }
};
} else {
options = gcpLogOptions(options as any) as LoggerOptions;
const pretty = this.getPrettyIfPresent();

if (pretty) {
return pino(options, pretty);
}

return pino(options);
return pino(gcpLogOptions(options as any));
}

private getPrettyIfPresent(): PinoPretty.PrettyStream | undefined {
if (typeof window !== "undefined" || LoggerService.config.STD_OUT_LOG_FORMAT !== "pretty") {
return;
}

try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
return require("pino-pretty")({ colorize: true, sync: true });
} catch (e) {
this.debug({ context: LoggerService.name, message: "Failed to load pino-pretty", error: e });
/* empty */
}
}

setContext(context: string) {
this.pino.setBindings({ context });
this.bind({ context });

return this;
}

bind(bindings: pino.Bindings) {
this.pino.setBindings(bindings);
this.pino = this.pino.child(bindings);

return this;
}
Expand Down
Loading