Skip to content

Configurable loggers / json logging#1339

Merged
ematipico merged 8 commits into
mainfrom
logger
Jun 8, 2026
Merged

Configurable loggers / json logging#1339
ematipico merged 8 commits into
mainfrom
logger

Conversation

@ematipico

@ematipico ematipico commented Apr 8, 2026

Copy link
Copy Markdown
Member

Summary

// astro.config.mjs
import { defineConfig, logHandlers } from "astro/config";

export default defineConfig({
  experimental: {
    logger: logHandlers.json({ pretty: true }),
  },
});
astro dev --json

Links

@ematipico ematipico marked this pull request as ready for review April 8, 2026 13:47
@ematipico ematipico changed the title feat: astro logger Configurable loggers / json logging Apr 8, 2026
Comment thread proposals/0059-custom-logger.md
Comment thread proposals/0059-custom-logger.md Outdated
Comment thread proposals/0059-custom-logger.md Outdated

# Unresolved Questions

- `flush` and `close` are asynchronous functions, and in the presence of multiple handlers we might need to await them. Should we call them without await? I wouldn't want to delay rendering. How do we catch errors if they fail?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine an adapter could provide something like waitUntil which doesn't block the request, otherwise block the request

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, but probably we can forget of the flush function. We will revisit once waitUntil lands in the next minor

Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
});
```

### `logHandlers.node(config?)`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the user perspective, is there any real difference between the console and node loggers? They do the same, right, one just only works in Node, in which case, why have it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They don't do the same thing.

Node.js uses stdout/stderr to print the messages.

Console prints to console via info/warn/error

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console always prints to stdout/stderr though. Do you know if there's an advantage to having both? Or did you do it that way because we already had both in the codebase (which IIRC is just historical and not purposefully designed).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console always prints to stdout/stderr though

Do you mean that the runtime (Node.js, workderd, etc.) does that? If so, then it's an implementation detail.

Or did you do it that way because we already had both in the codebase (which IIRC is just historical and not purposefully designed).

Yes we do. CLI and Pipeline use two different loggers. CLI uses a node.js logger, while the pipeline uses the console logger. Additionally, I didn't exclude the idea that a user could create a client logger, so I wanted to keep things open ended for now.

Comment thread proposals/0059-custom-logger.md
Comment thread proposals/0059-custom-logger.md Outdated
Comment thread proposals/0059-custom-logger.md Outdated
@ematipico

Copy link
Copy Markdown
Member Author

Call for consensus is now open.

@ascorbic

Copy link
Copy Markdown
Contributor

👍🏻 looks good

@matthewp

Copy link
Copy Markdown
Contributor

👍 sounds good to me

Comment thread proposals/0059-custom-logger.md Outdated
Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
@ematipico

Copy link
Copy Markdown
Member Author

@matthewp and @ascorbic please approve the PR :)

@delucis

delucis commented May 27, 2026

Copy link
Copy Markdown
Member

Just used a user query to dogfood this API — really handy way for people to customise stuff!

Here’s the custom logger I made in case it’s of interest: https://stackblitz.com/edit/github-cf392aa7?file=astro.config.mjs,custom-logger.js
And the Discord thread: https://discord.com/channels/830184174198718474/1509285901791006942

Some quick feedback/ideas based on trying it:

  • It would be nice to have a defineLogger() utility similar to our other type helpers. That would simplify some of the docs examples a bit potentially by not requiring as much manual typing.
  • It feels a shame that the options to a logger aren’t safely typed — definitely tricky because of the entrypoint pattern though.
  • The "SKIP_FORMAT" label might need to be documented or redesigned? Feels unexpected to have the label be used for something that isn’t actually a display label and likely for users to end up logging it instead of filtering it out like Astro’s implementations do.
  • I ended up copying Astro’s getEventPrefix() logic to be able to replicate Astro’s behaviour — I basically wanted a logger that was 1:1 to Astro’s default behaviour but had custom control over skipping some messages. Don’t know if that suggests there are more utilities that could be useful to users.

Take all that with a grain of salt as just the experience for a specific kind of logger. But thought it would be helpful to share.

@florian-lefebvre

Copy link
Copy Markdown
Member

We decided against having defineLogger() because all similar APIs just use types FYI.

For the options type safety, that's good feedback. I think the RFC and the docs on custom loggers should be updated to match the official pattern:

function pinoLogger(config: Options): LoggerHandlerConfig {
	return {
		entrypoint: '...',
		config
	}
}

We have a similar situation for session drivers. You don't have to use this pattern but we only document this one because it's better DX

@delucis

delucis commented May 28, 2026

Copy link
Copy Markdown
Member

Oh, and just remembered another thing that tripped me up getting started:

The docs show adding a custom logger from an npm package entry point

      entrypoint: "@org/custom-logger",

But most often people will be adding a local file to their project when building a custom logger, I’d guess. Or at least would do so initially before bundling it up to be published. It took me quite a bit of trial and error to find a way to specify a local file that worked in all contexts, ending up with:

      entrypoint: fileURLToPath(new URL('./custom-logger.js', import.meta.url)),

That is definitely not super friendly — for most our APIs, e.g. like injectRoute(), we support passing a relative path like './custom-logger.js'. Would be good to support that here too.

@ematipico ematipico merged commit 590b89c into main Jun 8, 2026
@ematipico ematipico deleted the logger branch June 8, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants