Giter VIP home page Giter VIP logo

elysia-logger's Introduction

@bogeychan/elysia-logger

A plugin for Elysia.js for logging using the pino library.

Installation

bun add @bogeychan/elysia-logger

Usage

import { Elysia } from "elysia";
import { logger } from "@bogeychan/elysia-logger";

const app = new Elysia()
  .use(
    logger({
      level: "error",
    })
  )
  .get("/", (ctx) => {
    ctx.log.error(ctx, "Context");
    ctx.log.info(ctx.request, "Request"); // noop

    return "Hello World";
  })
  .listen(8080);

console.log(`Listening on ${app.server!.url}`);

Log to a file, or

import { fileLogger } from "@bogeychan/elysia-logger";

fileLogger({
  file: "./my.log",
});

Pipe the log entries into a stream

import { logger } from '@bogeychan/elysia-logger';

logger({
  stream: ... // default -> console output
});

Include additional request context info

import { logger, type InferContext } from "@bogeychan/elysia-logger";

const myPlugin = () => new Elysia().decorate("myProperty", 42);

// ...

class MyError extends Error {
  constructor(message: string, public myValue: string) {
    super(message);
  }
}

app = app.error("myError", MyError).use(myPlugin());

app
  .use(
    logger({
      /**
       * This function will be invoked for each `log`-method called
       * where you can pass additional properties that need to be logged
       */
      customProps(ctx: InferContext<typeof app>) {
        if (ctx.isError && ctx.code === "myError") {
          return {
            myValue: ctx.error.myValue,
          };
        }

        return {
          params: ctx.params,
          query: ctx.query,
          myProperty: ctx.myProperty,
        };
      },
    })
  )
  .get("/", (ctx) => {
    ctx.log.info(ctx, "Context");

    return "with-context";
  })
  .get("/error", () => {
    throw new MyError("whelp", "yay");
  });

Use the logger instance both Standalone and inside Context

import { createPinoLogger } from "@bogeychan/elysia-logger";

const log = createPinoLogger(/* ... */);

app
  .use(log.into(/* ... */))
  .onError((ctx) => {
    log.error(ctx, ctx.error.name);
    return "onError";
  })
  .get("/", (ctx) => {
    ctx.log.info(ctx, "Context");

    throw new Error("whelp");
  });

Automatic onAfterResponse & onError logging by default; based on pino-http

import { logger } from "@bogeychan/elysia-logger";

app
  .use(
    logger({
      autoLogging: true, // default
      autoLogging: false, // disabled
      autoLogging: {
        ignore(ctx) {
          return true; // ignore logging for requests based on condition
        },
      },
    })
  )
  .get("/", (ctx) => "autoLogging");

Checkout the examples folder on github for further use cases such as the integration of pino-pretty for readable console outputs.

License

MIT

elysia-logger's People

Contributors

blucky-gh avatar bogeychan avatar loganarnett avatar marinatsuki avatar mmadson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

elysia-logger's Issues

After update Elysia 0.7.18 Type error.

Error
No overload matches this call.
The last overload gave the following error.
Argument of type '_INTERNAL_ElysiaLoggerPlugin<_INTERNAL_ElysiaLoggerPluginAutoLoggingState>' is not assignable to parameter of type 'Promise<{ default: Elysia<any, any, any, any, any, any>; }>'.ts(2769)
index.d.ts(392, 5): The last overload is declared here.
(alias) logger(options?: _INTERNAL_ElysiaLoggerPluginAutoLoggingEnabledOptions | undefined): _INTERNAL_ElysiaLoggerPlugin<...> (+1 overload)
import logger
The StreamLogger is used to write log entries to a stream such as the console output (default behavior).

import { Elysia } from "elysia"
import { logger } from "@bogeychan/elysia-logger"

const app = new Elysia().use(logger()).listen(8081)

console.log(`๐ŸฆŠ Elysia is running at ${app.server?.hostname}:${app.server?.port}`)

image

Error with Node

Im trying to use the plugin with the Node and Polyfills.

I getting this error:

node_modules/@bogeychan/elysia-logger/src/types.ts(3,31): error TS2307: Cannot find module 'bun' or its corresponding type declarations.

Rename `onResponse` to `onAfterResponse` (breaking change in Elysia 1.1)

Hi! ๐Ÿ‘‹

Firstly, thanks for your work on this project! ๐Ÿ™‚

Today I used patch-package to patch @bogeychan/[email protected] for the project I'm working on.

The latest version of Elysia renamed the lifecycle method onResponse to onAfterResponse

Here is the diff that solved my problem:

diff --git a/node_modules/@bogeychan/elysia-logger/src/index.ts b/node_modules/@bogeychan/elysia-logger/src/index.ts
index de71b96..11912dd 100644
--- a/node_modules/@bogeychan/elysia-logger/src/index.ts
+++ b/node_modules/@bogeychan/elysia-logger/src/index.ts
@@ -114,7 +114,7 @@ function into(this: Logger, options: ElysiaLoggerOptions = {}) {
       .onRequest((ctx) => {
         ctx.store = { ...ctx.store, startTime: performance.now() };
       })
-      .onResponse({ as: "global" }, (ctx) => {
+      .onAfterResponse({ as: "global" }, (ctx) => {
         const log = getLog(ctx);
 
         if (log.level == "silent") {

Let me if know if I should open a PR to fix this issue.

`autoLogging` of `NOT_FOUND` errors

What versions are running?

{
    "dependencies": {
        "elysia": "1.0.27",
        "@bogeychan/elysia-logger": "0.0.22"
    }
}

What steps can reproduce the bug?

import { Elysia } from "elysia";
import { logger } from "@bogeychan/elysia-logger";

new Elysia()
  .use(logger())
  .get("/", () => "yay")
  .listen(8080);

Open http://localhost:8080/notFound in your browser

What is the expected behavior?

{"level":30,"time":1720538226677,"pid":84064,"hostname":"","request":{"method":"GET","url":"http://localhost:8080/notFound","referrer":null}}

What do you see instead?

// nothing

Additional information

reported on discord by @tanishqmanuja

Property 'log' does not exist on type

Why isn't it available in onError middleware? Is it the logger or Elysia problem? Could you maybe give an advice on how to handle errors globally?

Version: 0.0.6

image image

Property 'log' does not exist on type '{ request: Request; code: "UNKNOWN"; error: Readonly; set: { headers: { [header: string]: string; } & { "Set-Cookie"?: string | string[] | undefined; }; status?: number | undefined; redirect?: string | undefined; }; } | { ...; } | { ...; } | { ...; } | { ...; }'.
Property 'log' does not exist on type '{ request: Request; code: "UNKNOWN"; error: Readonly; set: { headers: { [header: string]: string; } & { "Set-Cookie"?: string | string[] | undefined; }; status?: number | undefined; redirect?: string | undefined; }; }'.ts(2339)

Property 'logger' does not exist on type 'Context

image

Property 'logger' does not exist on type 'Context<{ body: unknown; params: Record<never, string>; query: undefined; headers: undefined; response: unknown; }, {}> & { jwt: { readonly sign: (morePayload: Record<string, string> & JWTPayloadSpec) => Promise<...>; readonly verify: (jwt?: string | undefined) => Promise<...>; }; unsignCookie: (value: string) => { ...'.ts(2339)

inferred type cannot be named without a reference to '../../node_modules/@bogeychan/elysia-logger/dist/types'

this plugin is awesome thanks for making it
when implementing it into my app I get a very strange error

import { Elysia } from "elysia";
import { logger } from "@bogeychan/elysia-logger";

export const ctx = new Elysia({
  name: "@app/ctx",
}).use(logger());
The inferred type of 'ctx' cannot be named without a reference to 
'../../node_modules/@bogeychan/elysia-logger/dist/types'. This is likely not portable. 
A type annotation is necessary. ts(2742)

Basically it wants me to manually annotate it for some reason, so I highlight what is inferred when I hover it and annotate it:

export const ctx: Elysia<
  "",
  {
    error: {};
    request: {
      log: Logger<Omit<LoggerOptions<"log">, "customProps" | "contextKeyName">>;
    };
    store: {};
    schema: {};
    meta: {
      schema: {};
      defs: {};
      exposed: {};
    };
  }
> = new Elysia({
  name: "@app/ctx",
}).use(logger());

and I think the issue is Logger and LoggerOptions are used in the package, but never exposed to the end user:

Module '"@bogeychan/elysia-logger"' declares 'LoggerOptions' locally, but it is not exported.

Default Logging for all HTTP requests

My expectation, considering this is a plugin specifically for Elysia is that this would do request and/or response logging by default. Something similar to https://github.com/pinojs/pino-http. It seems that this mostly just exposes a pino logger on the request context. Not a bad start by any means but if you do have the time / energy a nice enhancement would be to support additional options for auto logging requests and responses ideally with some configuration for suppressing variables or redacting sensitive parts of the request / response. Thanks!

Not working anymore

This is my first time trying this but it doesn't seems to work anymore with the new Elysia

Argument type
_INTERNAL_ElysiaLoggerPlugin<_INTERNAL_ElysiaLoggerPluginAutoLoggingState>
is not assignable to parameter type

Not compatible with 0.7

Hey! Elysia logger doesn't seem to work with Elysia 0.7.

  The last overload gave the following error.
    Argument of type 'Elysia<"", { store: {}; error: {}; request: DeriveReturned; schema: {}; meta: { schema: {}; defs: {}; exposed: {}; }; }>' is not assignable to parameter of type 'Promise<{ default: Elysia<any, any, any, any, any, any>; }>'.
      Type 'Elysia<"", { store: {}; error: {}; request: DeriveReturned; schema: {}; meta: { schema: {}; defs: {}; exposed: {}; }; }>' is missing the following properties from type 'Promise<{ default: Elysia<any, any, any, any, any, any>; }>': then, catch, finally, [Symbol.toStringTag]```

ParseError causes Elysia to crash when using this plugin

What versions are running?

"elysia": "1.0.11",
"@bogeychan/elysia-logger": "0.0.20",

What steps can reproduce the bug?

import { Elysia, t } from "elysia";
import { logger } from "@bogeychan/elysia-logger";

export const app = new Elysia()
    .use(
        logger({
            level: "trace",
            autoLogging: true,
        }),
    )
    .post("/test", (ctx) => "ok", {
        body: t.Object({
            test: t.String(),
        }),
    });

app.listen(3000);

Send empty body to provoke the error:

curl 'http://localhost/test' --data-raw '' -H 'content-type: application/json'

The response is:

Failed to parse body as found: [object Object]%

What is the expected behavior?

No response

What do you see instead?


41 |         return app
42 |             .onRequest((ctx) => {
43 |             ctx.store = { ...ctx.store, startTime: performance.now() };
44 |         })
45 |             .onResponse({ as: "global" }, (ctx) => {
46 |             if (log.level == "silent") {
                     ^
TypeError: undefined is not an object (evaluating 'log.level')
      at /home/haakon/repos/nxtest/node_modules/.pnpm/@[email protected][email protected]/node_modules/@bogeychan/elysia-logger/dist/index.js:46:17

Additional information

No response

`NotFoundError` doesn't log `onAfterResponse`

What versions are running?

{
    "dependencies": {
        "elysia": "1.1.3",
        "@bogeychan/elysia-logger": "0.1.1"
    }
}

What steps can reproduce the bug?

import { Elysia } from "elysia";
import { logger } from "@bogeychan/elysia-logger";

new Elysia()
  .use(logger())
  .get("/", () => "yay")
  .listen(8080);

Open http://localhost:8080/notFound in your browser

What is the expected behavior?

having 2 log entries in console

What do you see instead?

only 1

Additional information

blocked by elysiajs/elysia#713

Support Elysia 1.0.0

What versions are running?

I'm using Elysia version 1.0.0 and the latest version of this package (^0.0.17)

What steps can reproduce the bug?

const app = new Elysia({})
	.use(logger({ autoLogging: true })) // -> results in a type error and logs nothing
        .listen(3000)

What is the expected behavior?

No response

What do you see instead?

No response

Additional information

No response

Type errors and missing pino package..

Error 1

bilde

Argument of type '_INTERNAL_ElysiaLoggerPlugin<_INTERNAL_ElysiaLoggerPluginAutoLoggingState>' is not assignable to parameter of type 'Promise<{ default: (elysia: Elysia<any, any>) => Elysia<any, ElysiaInstance>; }>'.
      Type 'Elysia<"", { request: { log: pino.Logger<Options>; }; store: _INTERNAL_ElysiaLoggerPluginAutoLoggingState; }>' is missing the following properties from type 'Promise<{ default: (elysia: Elysia<any, any>) => Elysia<any, ElysiaInstance>; }>': then, catch, finally, [Symbol.toStringTag]ts(2769)

bilde

Argument of type '_INTERNAL_ElysiaLoggerPlugin<_INTERNAL_ElysiaLoggerPluginAutoLoggingState>' is not assignable to parameter of type 'Promise<{ default: (elysia: Elysia<any, any>) => Elysia<any, ElysiaInstance>; }>'.
      Type 'Elysia<"", { request: { log: pino.Logger<Options>; }; store: _INTERNAL_ElysiaLoggerPluginAutoLoggingState; }>' is missing the following properties from type 'Promise<{ default: (elysia: Elysia<any, any>) => Elysia<any, ElysiaInstance>; }>': then, catch, finally, [Symbol.toStringTag]ts(2769)

Error 2

bun start
$ bun run src/index.ts


error: Cannot find package "pino" from "/mnt/users/username/source/assignment1_chord/src/chord-node/node_modules/@bogeychan/elysia-logger/dist/index.js"
error: script "start" exited with code 1 (SIGHUP)

Info

Bun version: 1.0.6
@bogeychan/elysia-logger version: 0.0.12
vscode: 1.83.1
os: AlmaLinux 9.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.