-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add Logging API #5026
Add Logging API #5026
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Thank you for your contribution! ❤️You can try out this pull request locally by installing Rollup via npm install rollup/rollup#logging or load it into the REPL: |
Codecov Report
@@ Coverage Diff @@
## master #5026 +/- ##
==========================================
+ Coverage 98.96% 98.97% +0.01%
==========================================
Files 222 225 +3
Lines 8210 8295 +85
Branches 2258 2277 +19
==========================================
+ Hits 8125 8210 +85
Misses 30 30
Partials 55 55
|
This is great ❤️ Ideas: once wrapperI think patak already mentioned it, but a enabled flagAnother helper we use is inject plugin name,timestamp into logIf you have many plugins and some might log similar things, it can get hard to tell logs apart. formatting the logs to include plugin name and timestamp always would be nice. debug scopesLast but not least, the npm package If you scope this.debug calls to |
@dominikg Thanks for the feedback! once wrapper That is something we could add later, though I am still not convinced how necessary this feature is. It may be nice for debugging a plugin, but for logs that permanently stay in the plugin it should not be difficult to deduplicate within the plugin with a flag. On Rollup side, it would add some complexity that I would like to avoid. And if we implement it with this chaining style, it would also create runtime overhead as the handler functions need to be recreated for some of the hooks for each invocation and plugin, which also means we need to always add the enabled flag I see the utility, but again runtime overhead is something I would like to reduce. I would have a different suggestion to address the same issue: Allow the log functions to receive a function creating the string/object instead of the log itself. Then your example would just become this.debug(() => expensiveCompute())
// or this.debug(expensiveCompute) and this would just incur a minimal overhead when actually logging instead of needing to create those "enabled" properties every time a transform hook runs. debug scopes I am not sure I would want to reuse the This is the one idea I really want to push, but maybe I should make this even clearer in the docs: Rollup logs are objects, and you should give logs a While you cannot do it from the command line, at the moment you can easily use the export default {
//...
onLog(level, log, handler) {
if (log.plugin === 'node-resolve' && log.meta.scope === 'my-scope') {
handler(level, log);
}
}
} The Maybe I should add such an example to the docs. One could consider turning this filtering into a CLI option, e.g. |
I have added the ability to use functions as logs and updated the documentation. |
From my side, everything is finalized now. If there are no further comments, I would like to release it tomorrow. |
I like the ability to do it with env vars as you can do that even if rollup is called in a way where you can't pass args to it or would have to edit a config file. The more generic way to filter logs by prop is nice! |
Makes sense. I would add this as an additional improvement to not block the initial PR. |
@gajus This will make side effect logs filterable as they have a code of |
How about making let f = undefined
f?.(console.log('foo')) I don't know which is better in terms of overhead. |
This PR has been released as part of rollup@3.25.0. You can test it via |
Ah, that makes sense 👍 |
This PR contains:
Are tests included?
Breaking Changes?
List any relevant issue numbers:
Description
This implements a logging API as outlined in #4981. There are some differences from the outline that I want to highlight, though.
First, there is a new
onLog
input option, that receives three arguments:level
,log
anddefaultHandler
. The default handler is again called with two argumentslevel
andlog
. If it is not called, the log is filtered, otherwise it is forwarded toonwarn
if it is a warning and ultimately printed to the console. Here, level is eitherwarn
,info
ordebug
. Errors are not passed through the Logging API, but logs can easily be turned into errors by calling the default handler with a level oferror
.To filter logs by level, there is a new
logLevel
option that supportswarn
,info,
debugor
silent`.Plugins can generate logs by calling either
this.warn
,this.info
, orthis.debug
. Using separate functions per log level allows us to keep object identities between the generated logs and what is passed toonLog
while also allowing us to efficiently replace those functions with noop handlers depending on the log level.Plugins have an
onLog
hook that can easily filter logs by returning false, or emit new/additional logs like any other hook.The console logs generated by
experimentalMinChunkSize
andexperimentalLogSideEffects
are turned into properinfo
logs with the codesOPTIMIZE_CHUNK_STATUS
andFIRST_SIDE_EFFECT
.Please see the documentation changes for additional information, feedback welcome! cc @patak-dev @sapphi-red @marvinhagemeister @yyx990803 @antfu
configuration options
logLevel
LogLevel | "silent"
--logLevel <level>
"info"
Determine which logs to process. See
onLog
for the available log levels. The defaultlogLevel
of"info"
means that info and warnings logs will be processed while debug logs will be swallowed, which means that they are neither passed to pluginonLog
hooks nor theonLog
option or printed to the console.When using the CLI, errors will still be printed to the console as they are not processed via the logging system. See the
--silent
flag for how to suppress error logs.onLog
(level: LogLevel, log: RollupLog, defaultHandler: LogOrStringHandler) => void;
A function that intercepts log messages. If not supplied, logs are printed to the console, whereby Rollup CLI aggregates certain
"warn"
logs and prints consolidated warnings after the build to reduce noise. This handler is also triggered when using the--silent
CLI option.The function receives three arguments: the log level, the log object and the default handler. Log objects have, at a minimum, a
code
and amessage
property, allowing you to control how different kinds of logs are handled. Other properties are added depending on the type of log. Seeutils/logs.ts
for a complete list of built-in errors and logs together with their codes and properties.If the default handler is not invoked, the log will not be printed to the console. Moreover, you can change the log level by invoking the default handler with a different level. Using the additional level
"error"
will turn the log into a thrown error that has all properties of the log attached.This handler will not be invoked if logs are filtered out by the
logLevel
option. I.e. by default,"debug"
logs will be swallowed.Some logs also have a
loc
property and aframe
allowing you to locate the source of the log:plugin development
onLog
(level: LogLevel, log: RollupLog) => boolean | null
See the
onLog
option for the availableLoglevel
values and theRollupLog
type.A function that receives and filters logs and warnings generated by Rollup and plugins before they are passed to the
onLog
option or printed to the console.If
false
is returned from this hook, the log will be filtered. Otherwise, the log will be handed to theonLog
hook of the next plugin, theonLog
option, or printed to the console. Plugins can also change the log level of a log or turn a log into an error by passing the log tothis.error
,this.warn
,this.info
orthis.debug
and returningfalse
. Note that unlike other plugin hooks that add e.g. the plugin name to the log, those functions will not add or change properties of the log. Additionally, logs generated by anonLog
hook will not be passed back to theonLog
hook of the same plugin. If another plugin generates a log in response to such a log in its ownonLog
hook, this log will not be passed to the originalonLog
hook, either.Like the
options
hook, this hook does not have access to most plugin context utility functions as it may be run before Rollup is fully configured. The only supported properties arethis.meta
as well asthis.error
,this.warn
,this.info
andthis.debug
for logging and errors.this.debug
(log: string | RollupLog | (() => RollupLog | string), position?: number | { column: number; line: number }) => void
Generate a
"debug"
log. Seethis.warn
for details. Debug logs always getcode: "PLUGIN_LOG"
added by Rollup. Make sure to add a distinctivepluginCode
to those logs for easy filtering.These logs are only processed if the
logLevel
option is explicitly set to"debug"
, otherwise it does nothing. Therefore, it is encouraged to add helpful debug logs to plugins as that can help spot issues while they will be efficiently muted by default. If you need to do expensive computations to generate the log, make sure to use the function form so that these computations are only performed if the log is actually processed.this.info
(log: string | RollupLog | (() => RollupLog | string), position?: number | { column: number; line: number }) => void
Generate an
"info"
log. Seethis.warn
for details. Info logs always getcode: "PLUGIN_LOG"
added by Rollup. As these logs are displayed by default, use them for information that is not a warning but makes sense to display to all users on every build.If the
logLevel
option is set to"warn"
or"silent"
, this method will do nothing.this.warn
(log: string | RollupLog | (() => RollupLog | string), position?: number | { column: number; line: number }) => void
Using this method will generate warnings for a build, which are logs with log level
"warn"
. See theonLog
option for information about theRollupLog
type. To generate other logs, see alsothis.info
andthis.debug
. To generate errors, seethis.error
.Just like internally generated warnings, these logs will be first passed to and filtered by plugin
onLog
hooks before they are forwarded to customonLog
oronwarn
handlers or printed to the console.The
warning
argument can be astring
or an object with (at minimum) amessage
property:We encourage you to use objects with a
pluginCode
property as that will allow users to easily filter for those logs in anonLog
handler. If you need to add additional information, you can use themeta
property. If the log contains acode
and does not yet have apluginCode
property, it will be renamed topluginCode
as plugin warnings always get acode
ofPLUGIN_WARNING
added by Rollup. To prevent this behavior, plugins can instead use the normalizedonLog
option passed to thebuildStart
hook. Calling this option from a plugin will not change properties when passing the log to pluginonLog
handlers andonLog
oronwarn
handlers.If you need to do expensive computations to generate a log, you can also pass a function returning either a
string
or aRollupLog
object. This function will only be called if the log is not filtered by thelogLevel
option.When used in the
transform
hook, theid
of the current module will also be added and aposition
can be supplied. This is a character index or file location which will be used to augment the log withpos
,loc
(a standard{ file, line, column }
object) andframe
(a snippet of code showing the location).If the
logLevel
option is set to"silent"
, this method will do nothing.