-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
feat: Add logging action and middleware #13269
feat: Add logging action and middleware #13269
Conversation
Does anyone know why the snapshot fails on Windows only?
|
This looks nice! I actually like it. We probably want to make SET_LOGGER an array which people can hook into so we can have multiple sources like file logger & screen logger but for now this is great (YAGNI). I wonder if we should add "telemetry" to redux as well, instead of adding calls inside our code we could just add a redux middleware that watch events. We could add some metadata to redux so telemtry has some extra data. I ran it locally on windows and all tests passes so unsure what azure does differently. $ jest packages/gatsby/src/redux/__tests__/pages.js
PASS packages/gatsby/src/redux/__tests__/pages.js (9.523s)
Add pages
√ allows you to add pages (121ms)
√ Fails if path is missing (3ms)
√ Fails if component path is missing (3ms)
√ Fails if the component path isn't absolute (3ms)
√ Fails if use a reserved field in the context object (4ms)
√ adds an initial forward slash if the user doesn't (2ms)
√ allows you to add pages with context (115ms)
√ allows you to add pages with matchPath (98ms)
√ allows you to add multiple pages (77ms)
√ allows you to update existing pages (based on path) (42ms)
√ allows you to delete paths (2ms) Some bikeshedding: const { store } = require(`../redux`)
const { actions } = require(`../redux/actions`)
const { dispatch } = store
const { log } = actions I feel that we need some utitlities for this. I actualy liked boundActionCreators 😛. Perhaps it's me just being lazy but I would be happy with. const { dispatch } = require(`../redux`)
const { actions } = require(`../redux/actions`)
const { log } = actions |
Yes. Alternatively we could
I haven't really looked at the telemetry stuff but I'd imagine this would work quite well. I mean I even think the api-runner could work quite well as a middleware.
Why I like dispatching is because it enforces the mental model better. But yes there should be less to import. We wanted to reorganize actions anyway (better separate internal from public ones) -- we could just export them together with the store: const { actions, store: { dispatch } } = require('../redux')
dispatch(actions.log('Hello world')
// actually shorter than
boundActionCreators.log('Hello world') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stefanprobst this is looking good!
Quick question - we'd like this functionality to be seamlessly integrated to even existing applications, and the easiest way to do that is by extending our reporter (e.g. reporter.warn, reporter.error, etc.) to integrate with e.g. our redux store.
Have you thought about a way we could make this functionality backwards compatible in these cases, and in doing so, require no changes for the end user/plugin author?
@DSchau
EDIT: What's currently missing is |
yeah @stefanprobst we don't want to add new APIs for this. |
@KyleAMathews i don't understand, what new APIs? |
@stefanprobst after taking a deeper look at this--I understand what you're doing now! reporter.warn, reporter.info, etc. all proxy to the log action, which is exactly what we want. My main question is why are we swapping things to a dispatch instead of just invoking the same methods in some areas? For example, in this file why not just keep it |
What I mean is we want people to keep using the reporter in their plugins as well as us in core. We want the reporter to add its own redux implemention for to store data and print out logs. Then core can send logs to it as needed. This way we can do a gradual migration to more structured logging via overloading the first prop to the reporter to also accept an object for more detailed log entries. |
@KyleAMathews
Question:
|
My assumption is that we need to keep everything in gatsby-cli as there's plenty of plugins and places in core and I'm sure people's sites that use it for logging — we want to be sure all data is going through the same code. If we can successfully send everything through our core redux, that'd be great as it'd be simpler. What I don't like is changing the API for passing in data — moving from Also not sure why action creators should have to return an action? Another desired feature we need to account for is we'll be changing the CLI design to persistent errors/warnings at the bottom of the screen — this will mean that code that logs an error/warning will also need to be able to detect when that's fixed. This will probably be an opt-in feature but we can already do stuff like this like with e.g. xstate, we know if a component has a babel or graphql error now and when it's fixed and can use that to show/remove warnings gatsby/packages/gatsby/src/redux/machines/page-component.js Lines 25 to 26 in a93963b
|
I think for plugins it has always been bad practice to directly import from
I agree, which is why directly importing from
It's hard to respond to this, except that I disagree. It's just standard redux, which imho is a good fit for us and we should use it much more consequently than we currently do.
Action creators must create an action, because redux will throw if you try to dispatch something that is not an action (i.e. an object with a const { createStore } = require('redux')
const store = createStore(state => state)
const doSomething = () => 'Error' // throws
// const doSomething = () => ({ type: 'ERROR' }) // works
store.dispatch(doSomething())
I like that. And I think it's actually a lot easier with a middleware approach because that is a place that already knows about every action flowing through core. Btw imho in the future it would we good to have these kinds of discussions as part of the RFC process. |
This is part of the RFC process :-P many RFCs need a POC PR put up to flesh out the ideas enough to discuss things deeply. E.g. @m-allanson's RFC has a lot of open questions at the end that we should resolve before the RFC is accepted. You've also changed the API here from what he wrote which, if we accept it, would need reflected there, etc. Beyond changing APIs, I don't think we want middleware but to keep things in a reducer. We want to be able to compare old state to new state as to e.g. persist errors at the bottom, we'd need to avoid printing out a given error multiple times which would require knowing that the error is already being displayed. |
Ok cool, I feel like it hasn't been 100% clear to me how this is supposed to work. In any case we should ensure that discussions happening in issue comments stay discoverable from the RFC.
Middleware and reducer are for different things -- middleware is for side-effect handling, and you have access to the whole store & can dispatch actions from there, e.g. to put things in the store with a reducer, which might make sense for the removing-notifications-case depending on how the new reporter would implement this exactly. I think a logging middleware would mean very few constraints on how this can be evolved in the future, but we can discuss further in an alternative proposal. |
This is an implementation proposal for the Structured logging RFC, based on @m-allanson 's work there.
It adds:
SET_LOGGER
action: for setting the logger instance. currently this just takes thereporter
from the cli. The only place where the reporter is still directly imported is inbootstrap/index
(and in the commands which haven't been touched).LOG_MESSAGE
action: to log a message