Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow a user-provided
logger
for Server, Gateway and AER (#3894)
* Switch multi-argument `logger` pattern to single parameter invocations. Will consider supporting this if I can confirm all loggers support it. * Decompose `GatewayConfigBase` into types in preparation for `logger`. The `logger` will be mutually exclusive to the `debug` property, which means we'll need to (essentially) XOR them in the types with `never` types, which cannot be done with an `interface`. * gateway: Introduce `Logger` type and expose on `logger` config. This is a mutually exclusive option to `debug` which enables logging of our default logger when one is not provided by the user. * tests: test various popular loggers: log4js, winston, bunyan, loglevel. * Add optional `logger` to `GraphQLServiceContext` and `GraphQLRequestContext`. A follow-up commit will make these required! * Introduce optional `logger` property for `apollo-engine-reporting`. This is a more granular part of a larger project to introduce the concept of a `logger` to various parts of the Apollo Server stack - including `ApolloGateway` and `ApolloServer`. Since this extension is most always initiated by `ApolloServer` itself, this will generally be a property that is inherited by the configuration that `ApolloServer` provides. The intention is: if someone provides a `logger` at the `ApolloServer` level, we will propagate it down to various sub-components, including the `apollo-engine-reporting` extension. * Introduce optional `logger` for `ApolloServer` class. In general, Apollo Server itself does very little outputting of messages (either informational or otherwise) to its console. Historically, Apollo Server has simply used various `console` facilities (i.e. `console.log`) to output such messages. Using `console` methods does get the point across quite well in development, though it's less ideal for production environments which often demand a more structured approach to capturing their log messages across various stacks. For example, in containerized environments logs are often siphoned into various centralized log facilities and/or third party log providers (e.g. Datadog, Loggly, etc.). Many users are already using existing loggers (like [`winston`], [`log4js`], [`bunyan`] and more) to report messages from their resolvers by exposing those logger implementations on their "context" using the `context` property to the `ApolloServer` constructor options. However, exposing a logger on the `context` doesn't allow Apollo Server to use it for its own important messaging and users should be able to opt into getting Apollo's own messages in the same log facilities. Apollo Server will continue to be relatively quiet for now, but various sub-components (e.g. Gateway, Engine Reporting) are already outputting more and more important messages and warnings which deserve to get attention. Therefore, this introduces a relatively generic `logger` property to `ApolloServer` which will be made available on the `GraphQLRequestContext` that is already passed around in many places internally, received by various Gateway compoments, and also exposed to plugins, allowing well-considered plugins to utilize the same centralized log sink. This should also allow granular logging at various levels, including scoped or tagged logging, since the request pipeline could be used to create a sub-instance of a logger. For example, different components can accept their own `logger` property which, when set, will override any more-parent `logger` and allow logs to be sorted according to user preference. Apollo Engine will be the first-subcomponent to get this treatment. Similarly, for logger implementations that support the notion of creating a sub-logger from an existing logger, the plugin life-cycle hooks can be used to create a user-specific logger in the `requestDidStart` life-cycle. This can be helpful in applying a user-id tag to all log messages which happened within the scope of a particular request. If the same logger should be made available to resolvers via exposure on the `context, such plugin implementation on `requestDidStart` should also augment the already-created `context` with the scoped-logger. * To support Node.js 6, use older version of `log4js` for testing. We're only testing the interface compatibility here, so the latest version isn't really necessary. Though this would be great to update! * ResponseCache: when available, use `requestContext.logger` to log. * gateway: when set, log using `requestContext.logger` in `executeQueryPlan`. * Make `logger` required on `GraphQLServiceContext` + `GraphQLRequestContext`. As promised in 62e99d76. * Fix all the spelling mistakes. You'd think I dictated these using Siri or something. Thanks, @trevor-scheer. Co-Authored-By: Trevor Scheer <trevor@apollographql.com> * Add CHANGELOG for #3894. * docs: Explain `logger` on `ApolloServer` and `EngineReportingOptions`. * Kinda revert "Decompose `GatewayConfigBase` into types in prep..." This reverts the decomposition introduced by commit 8a19ecc, but also maintains the bit that was added right after it in 780d7f4. Specifically, I misjudged with the direction I was headed. While my intent was to have `debug` and `logger` be mutually exclusive, it turns out that in order to preserve the existing behavior, I need to make sure that `debug: true` is the thing that puts the default logger (`loglevel`) into the appropriate level where it still prints out various legacy messages. cc @trevor-scheer * docs: Explain `logger` on `ApolloGateway` in the API reference. * Apply counter-intuitive severity to `debugPrintReports` messages. In terms of verbosity, and as the name of this option suggests, the output when `debugPrintReports` is enabled is is either an "info" or a "debug" level message. However, we are using `warn` here for compatibility reasons since the `debugPrintReports` flag pre-dated the existence of log-levels and changing this to also require `debug: true` (in addition to `debugPrintReports`) just to reach the level of verbosity to produce the output would be a breaking change. The "warn" level is on by default. There is a similar theory and comment applied below. cc @trevor-scheer * docs: Note presence of `logger` in plugins' lifecycle hooks. Co-authored-by: Trevor Scheer <trevor@apollographql.com>
- Loading branch information