DEV Community

Cover image for How to improve your console.logs without additional code
Andy Jiang for Deno

Posted on

3 1 1

How to improve your console.logs without additional code

Too often, we’re presented with logs like this:

[http] GET /api/book/1
[http] GET /api/book/2
[db] SELECT * FROM books WHERE id = 1
[db] SELECT * FROM books WHERE id = 2
error: Uncaught (in promise) PostgresError: 'name' column is null
  throw new PostgresError(`'name' column is null`);

    at query (file:///tmp/main.ts:29:9)
    at queryBook (file:///tmp/main.ts:25:3)
    at handleRequest (file:///tmp/main.ts:21:3)
    at file:///tmp/main.ts:18:1
Enter fullscreen mode Exit fullscreen mode

So, does book 1 or book 2 have a null name field? 🤔

Without context, these logs are noisy and difficult to parse. However, if we associate a request ID with each log, then we can determine which book had the null name field:

[req:1] [http] GET /api/book/1
[req:2] [http] GET /api/book/2
[req:1] [db] SELECT * FROM books WHERE id = 1
[req:2] [db] SELECT * FROM books WHERE id = 2
[req:1] error: Uncaught (in promise) PostgresError: 'name' column is null
  throw new PostgresError(`'name' column is null`);

    at query (file:///tmp/main.ts:29:9)
    at queryBook (file:///tmp/main.ts:25:3)
    at handleRequest (file:///tmp/main.ts:21:3)
    at file:///tmp/main.ts:18:1
Enter fullscreen mode Exit fullscreen mode

Now, we’re able to immediately understand the problem causing the error. Book 1 is missing a name!

We could manually pass a dynamically generated requestId across our functions so that they're included in each console.log:

// Express app

export async function handle(req: Request): Promise<Response> {
  const requestId = Math.random();

  console.log(`[req:${requestId}] [http] ${req.method} ${req.url}`);

  const url = new URL(req.url);
  const bookId = url.pathname.split("/")[2];
  const data = await getData(requestId, bookId);

  return Response.json(data);
}

async function getData(requestId: number, bookId: string): Promise<Book> {
  console.log(`[req:${requestId}] [db] get book ${bookId}`);
  try {
    return await db.selectFrom("books").where("id", "=", bookId).first();
  } catch (err) {
    console.error(`[req:${requestId}] ${err}`);
    throw err;
  }
}
Enter fullscreen mode Exit fullscreen mode

But that is annoying and difficult to scale/maintain.

Instead, running the program with Deno (and it's built-in OpenTelemetry support) will automatically apply unique request IDs to each log:

$ deno run -A --unstable-otel app.js
Enter fullscreen mode Exit fullscreen mode

And in our Grafana Loki, we can see that while our logs don't include the request ID in the logs themselves:

Structured logging with Deno

Clicking on a single log will show us a trace_id:

Trace id in log

And when we click on the trace_id, we will see all the logs associated with that specific request:

All logs associated with a single request

Now it is much easier to parse the logs and know how to identify problems in our code.


Watch the full 20 minute talk on zero config debugging with Deno and OpenTelemetry.

Learn more about getting deep traces in Node.js with Deno, OpenTelemetry support in Deno, and Deno v2.2.

Top comments (0)

11 Tips That Make You a Better Typescript Programmer

typescript

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay