Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[frontend-infra] Javascript frontend logging/debugging/error library?

21 views
Skip to first unread message

Kyle Lahnakoski

unread,
Mar 19, 2019, 7:00:16 PM3/19/19
to mozill...@lists.mozilla.org
mozill...@lists.mozilla.org

Good day frontend-infra team!

In my experience, every reasonably sized application uses a logging
library of some sort.  Even the health dashboard has one hidden one
called `reportOrLog` [1]:  it is used to shunt errors from the console
to the "Raven" library (whatever that does).  I would like for us to
settle on one for all our javascript projects.

Please submit what you use for logging, debugging and errors so we have
a short list to choose from.


The rest of this email is my submission:

The API I have been using has three functions:

    Log.note(reason, data) - log message
    Log.warning(reason, data, cause) - log error details, no longer an error
    Log.error(reason, data, cause) - slightly simpler way to throw an error


Here is an example of throwing an error:
    
    Log.error(
        '{{func}} is an unknown string function for template expansion',
        { func }
    );

Here is an example of logging an error, along with the original `cause`:

    }catch(cause){
        Log.warning("Can not evaluate {{variable|json}}", { variable },
cause);
    }


Below is link to a PR with my first attempt [2]. 


I am agnostic about the names, or the actual library that implements
this functionality, so here are the features I am looking for:

* **support structured logging** - Stop using template literals:
The `reason` and the `data` are kept separate so that the `data` remains
machine readable and can be put into a datastore to be queried. I do not
expect to query logs on the first day, but we should pick a library that
does not interfere with that possibility.
* **chain exceptions** - When I catch an error, and I can't actually
deal with it, I would like to add some context (what is the code
supposed to be doing) and raise a new error. Keep the old error (and
stack trace), and chain it as the `cause`.
* **send detailed warnings** - Sometimes my code CAN deal with the
exception, but it is not ideal. In those cases I might show something to
the user, but I definitely want a full description logged so it can be
diagnosed at some later time.
* **switch error mitigation based on reason** - Sometimes exception
classes are made so the exception handler can switch based on the type
of error. One benefit of
separating `reason` from `data` is  the `reason` can be used to perform
that same switch; no special exception classes are needed, and logging
continues to stay lightweight.
* **avoid linting errors** - Using `console.log()` makes the linter
angry! I can imagine there are reasons why you would want to log
information, either for debugging, or for production (eg client-side
query response timings). We make logging easier, at the same time these
methods ensure all logs are shunted to the proper location.  

The `note`, `warning` and `error` may not implement these features, but
they allow these features to be implemented.


[1] reportOrLog
https://github.com/mozilla-frontend-infra/firefox-health-dashboard/blob/650ef39b64174d0aa4477c18395108a08127c83a/src/hocs/withErrorBoundary.jsx#L6

[2] add logging
https://github.com/mozilla-frontend-infra/firefox-health-dashboard/pull/355



Armen Zambrano Gasparnian

unread,
Mar 25, 2019, 3:35:46 PM3/25/19
to mozill...@lists.mozilla.org
On Tuesday, 19 March 2019 19:00:16 UTC-4, Kyle Lahnakoski wrote:
> mozill...@lists.mozilla.org
>
> Good day frontend-infra team!
>
> In my experience, every reasonably sized application uses a logging
> library of some sort.  Even the health dashboard has one hidden one
> called `reportOrLog` [1]:  it is used to shunt errors from the console
> to the "Raven" library (whatever that does).  I would like for us to
> settle on one for all our javascript projects.
I don't think we will settle on a library because we're aiming to follow the same practice as in AirBnb to not log anything to the console. I failed to follow that in my reportOrLog code out of lazyness.

Instead we might want to settle on a recommended practice (for example):

* Use a top app error boundary for app level issues
* Use a component error boundary
* If an error reaches the error boundary report it to Sentry or GCP
* Use the `ErrorPanel` component [1] for the UI to report issues
* It supports showing full stack trace in development mode

[1] https://mozilla-frontend-infra.github.io/components/#errorpanel

Kyle Lahnakoski

unread,
Apr 17, 2019, 9:09:18 AM4/17/19
to to...@lists.mozilla.org
frontend-infra team,

Our last Treeherder meeting brought up the question of using Sentry, or
some other tool, to report our UI problems. This goes along the lines of
a need for a logging/debugging/error library. Let me stick to discussing
error handling; with the understanding that logging is analogous.

There are two sides to error handling; the raising and the catching. My
first post was only concerned about raising errors in some standard way;
my code is raising errors now, so I would like a standard way to raise
errors before I write too much code. I am looking for an API to raise
errors. An API will allow us to write error raising code now, while
remaining agnostic about the tools can catch those errors.

Armen's post is concerned with catching errors, so was our discussion on
Sentry; either, or both, can be fed with errors. Neither are dealing
with the subject I am most concerned with: Some convention for raising
errors.

Since the mention of Sentry has brought back the subject of error
handling, I hope this discussion can resume. Please submit the
techniques you may have used to raise errors, or comment on what I
proposed below.

Thank you



On 2019-03-25 15:35, Armen Zambrano Gasparnian wrote:
> On Tuesday, 19 March 2019 19:00:16 UTC-4, Kyle Lahnakoski wrote:
>> mozill...@lists.mozilla.org
>>
>> Good day frontend-infra team!
>>
>> In my experience, every reasonably sized application uses a logging
>> library of some sort.  Even the health dashboard has one hidden one
>> called `reportOrLog` [1]:  it is used to shunt errors from the console
>> to the "Raven" library (whatever that does).  I would like for us to
>> settle on one for all our javascript projects.
> I don't think we will settle on a library because we're aiming to follow the same practice as in AirBnb to not log anything to the console. I failed to follow that in my reportOrLog code out of lazyness.
>
> Instead we might want to settle on a recommended practice (for example):
>
> * Use a top app error boundary for app level issues
> * Use a component error boundary
> * If an error reaches the error boundary report it to Sentry or GCP
> * Use the `ErrorPanel` component [1] for the UI to report issues
> * It supports showing full stack trace in development mode
>
> [1] https://mozilla-frontend-infra.github.io/components/#errorpanel
>
> _______________________________________________
> tools mailing list
> to...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/tools

Hassan Ali

unread,
Apr 21, 2019, 8:22:44 PM4/21/19
to Kyle Lahnakoski, to...@lists.mozilla.org
For raising errors, I've historically relied on
`console.{log|warn|error|info|trace}` for raising errors. In order to use
the `console` object in production, you could disable the `no-console`
linting rule in `.neutrinorc.js`. In order to support adding a reason to an
error, I've previously created a class that overrites the `name` property
of the Error instance. Something like
https://gist.github.com/helfi92/8718899cc99002f7f5f211dc677ae80b. If this
is not good enough, have we considered using a third party library? From a
quick search I found

* https://github.com/visionmedia/debug
* https://pimterry.github.io/loglevel/
* https://github.com/structured-log/structured-log

Thoughts?

On Wed, Apr 17, 2019 at 9:09 AM Kyle Lahnakoski <klahn...@mozilla.com>
wrote:

> frontend-infra team,
>
> Our last Treeherder meeting brought up the question of using Sentry, or
> some other tool, to report our UI problems. This goes along the lines of
> a need for a logging/debugging/error library. Let me stick to discussing
> error handling; with the understanding that logging is analogous.
>
> There are two sides to error handling; the raising and the catching. My
> first post was only concerned about raising errors in some standard way;
> my code is raising errors now, so I would like a standard way to raise
> errors before I write too much code. I am looking for an API to raise
> errors. An API will allow us to write error raising code now, while
> remaining agnostic about the tools can catch those errors.
>
> Armen's post is concerned with catching errors, so was our discussion on
> Sentry; either, or both, can be fed with errors. Neither are dealing
> with the subject I am most concerned with: Some convention for raising
> errors.
>
> Since the mention of Sentry has brought back the subject of error
> handling, I hope this discussion can resume. Please submit the
> techniques you may have used to raise errors, or comment on what I
> proposed below.
>
> Thank you
>
>
>
> On 2019-03-25 15:35, Armen Zambrano Gasparnian wrote:
> > On Tuesday, 19 March 2019 19:00:16 UTC-4, Kyle Lahnakoski wrote:
> >> mozill...@lists.mozilla.org
> >>
> >> Good day frontend-infra team!
> >>
> >> In my experience, every reasonably sized application uses a logging
> >> library of some sort. Even the health dashboard has one hidden one
> >> called `reportOrLog` [1]: it is used to shunt errors from the console
> >> to the "Raven" library (whatever that does). I would like for us to
> >> settle on one for all our javascript projects.
> > I don't think we will settle on a library because we're aiming to follow
> the same practice as in AirBnb to not log anything to the console. I failed
> to follow that in my reportOrLog code out of lazyness.
> >
> > Instead we might want to settle on a recommended practice (for example):
> >
> > * Use a top app error boundary for app level issues
> > * Use a component error boundary
> > * If an error reaches the error boundary report it to Sentry or GCP
> > * Use the `ErrorPanel` component [1] for the UI to report issues
> > * It supports showing full stack trace in development mode
> >
> > [1] https://mozilla-frontend-infra.github.io/components/#errorpanel
> >

Kyle Lahnakoski

unread,
Apr 22, 2019, 10:38:09 AM4/22/19
to Hassan Ali, to...@lists.mozilla.org

Hassan,

Each of your third party suggestions are much like Armen's: They are
specific implementations that catch errors, and each has a different API
for raising those errors.  Let me say that again, but on the subject of
logging: Your third party suggestions are specific implementations that
handle logging messages, and each has a different API for emitting log
messages.

I do not know how well any work with Sentry.

Is it possible for us to decide on a logging API without knowing what
the specific implementation is going to be?  How much combined
experience do we have on the subject of logging?  Can we agree our
combined experience is complete?  if not, can we agree that the subject
of logging is small enough that, combined, we know enough to make/select
a good API?  Given we have a good understanding of the domain, can we
declare/find a logging API that covers all our use cases?  I think the
answer is *yes*.

By declaring a logging/error API we have a layer of indirection that
allows us to match the choice of logging library with the needs of the
application without changing the application code.  It would be
disappointing if each application had its own logging library, and I had
to know about the anomalies and conventions of each.

On the subject of your specific recommendations:

* I do not think `console.*` is a good choice.  It already interferes
with linters, but also there is no way the shunt those calls to a useful
logging library (or have a centralized place to turn them on/off).  The
reason we all use `console.log` is because it is easy; I wholly expect a
logging API to also be easy.  Maybe you are suggesting using "console"
as our canonical logging API?  in which case you are suggesting `import
console from "./our_logging_lib"` be used to shunt those calls to the
desired location?

*The `name` and `message` properties in your Error instance are a bit
vague, but you mention it is a solution to the need to have a reason
associated with error.  Can we phase this as a use case?


Thanks
> <mailto:mozill...@lists.mozilla.org>
> >>
> >> Good day frontend-infra team!
> >>
> >> In my experience, every reasonably sized application uses a logging
> >> library of some sort.  Even the health dashboard has one hidden one
> >> called `reportOrLog` [1]:  it is used to shunt errors from the
> console
> >> to the "Raven" library (whatever that does).  I would like for
> us to
> >> settle on one for all our javascript projects.
> > I don't think we will settle on a library because we're aiming
> to follow the same practice as in AirBnb to not log anything to
> the console. I failed to follow that in my reportOrLog code out of
> lazyness.
> >
> > Instead we might want to settle on a recommended practice (for
> example):
> >
> > * Use a top app error boundary for app level issues
> > * Use a component error boundary
> > * If an error reaches the error boundary report it to Sentry or GCP
> > * Use the `ErrorPanel` component [1] for the UI to report issues
> >   * It supports showing full stack trace in development mode
> >
> > [1] https://mozilla-frontend-infra.github.io/components/#errorpanel
> >
> > _______________________________________________
> > tools mailing list
> > to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> > https://lists.mozilla.org/listinfo/tools
> _______________________________________________
> tools mailing list
> to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> https://lists.mozilla.org/listinfo/tools
>

Armen Zambrano Gasparnian

unread,
Apr 24, 2019, 4:14:55 PM4/24/19
to Kyle Lahnakoski, Hassan Ali, to...@lists.mozilla.org
This is how I try to do it these days (the reportOrLog function is old and
these days I would only report the error).

Do not log and let errors bubble up. At the top level, report the error to
Sentry so you know how frequently is happening on the wild.
If I catch an error on lower components, it is to show a small fallback UI
for that specific component. However, after catching it, I throw the error
again which will get to the top component and be reported via Sentry.

The only place I use a logging library is with a script:
https://github.com/mozilla/firefox-health-backend/commit/942c680778816534b92536ebab9a6b6afd41964f
The package used is called 'debug' and it allows for adjusting different
levels of logging.

On the general topic, I don't believe trying to agree on APIs at this low
level will actually help us reduce the development cost across projects.

regards,
Armen


On Mon, 22 Apr 2019 at 10:38, Kyle Lahnakoski <klahn...@mozilla.com>
wrote:
> > <mailto:mozill...@lists.mozilla.org>
> > >>
> > >> Good day frontend-infra team!
> > >>
> > >> In my experience, every reasonably sized application uses a
> logging
> > >> library of some sort. Even the health dashboard has one hidden
> one
> > >> called `reportOrLog` [1]: it is used to shunt errors from the
> > console
> > >> to the "Raven" library (whatever that does). I would like for
> > us to
> > >> settle on one for all our javascript projects.
> > > I don't think we will settle on a library because we're aiming
> > to follow the same practice as in AirBnb to not log anything to
> > the console. I failed to follow that in my reportOrLog code out of
> > lazyness.
> > >
> > > Instead we might want to settle on a recommended practice (for
> > example):
> > >
> > > * Use a top app error boundary for app level issues
> > > * Use a component error boundary
> > > * If an error reaches the error boundary report it to Sentry or GCP
> > > * Use the `ErrorPanel` component [1] for the UI to report issues
> > > * It supports showing full stack trace in development mode
> > >
> > > [1]
> https://mozilla-frontend-infra.github.io/components/#errorpanel
> > >
> > > _______________________________________________
> > > tools mailing list
> > > to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> > > https://lists.mozilla.org/listinfo/tools
> > _______________________________________________
> > tools mailing list
> > to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> > https://lists.mozilla.org/listinfo/tools
> >
> _______________________________________________
> tools mailing list
> to...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/tools
>


--
Armen Zambrano G.
https://armenzg.com

Kyle Lahnakoski

unread,
Apr 25, 2019, 7:53:57 AM4/25/19
to Armen Zambrano Gasparnian, to...@lists.mozilla.org

On 2019-04-24 16:14, Armen Zambrano Gasparnian wrote:
> The only place I use a logging library is with a script:
> https://github.com/mozilla/firefox-health-backend/commit/942c680778816534b92536ebab9a6b6afd41964f
> The package used is called 'debug' and it allows for adjusting
> different levels of logging.
>
I see you changed all the call sites to satisfy the particular debugging
library you used.  I see that `debug` does not cover the use cases I
listed; maybe the logging will be changed again? 


> On the general topic, I don't believe trying to agree on APIs at this
> low level will actually help us reduce the development cost across
> projects.
>
I can consider the argument that we do not need a standard logging lib:
We let each developer choose whatever makes sense for the project they
work in.  If we decide on "no standard" then I imagine it will increase
the learning curve for each app in some small way.  I would like to hear
what others think.


The rest is how I serendipitously, encountered this learning curve the
other day:

In your example above,

const debugLog = debug('script:debug');
const infoLog = debug('script:info');
const errorLog = debug('script:error');

I am not certain what these lines are doing, I assume they are setting
up different channels for logging, but I have no idea what mini-language
is being passed as a string argument to the `debug()` function.  Here
are some rhetorical questions:

* Why are there three channels?  Does every module need to have these
lines to log?
* What is the "script" prefix refer to?  Is it indicating a destination
stream?  Is it a unique name for this source file?  Is it a feature
selection (like can I `debug('structured:debug')`?).
* What is the suffix refer to?  It is a log level? Is it a unique name
for this source file? Does it indicate log destination?  Maybe it refers
to a builtin function?
* How do I turn the logging on? I could not get the logging lib to
actually provide output; so I resorted to using `console.log()`.   I
guess the logging is off by default.
https://github.com/mozilla/firefox-health-backend/pull/61/files#diff-f8f458b019e0f21d56c67451cd17728fR72

For me, every function has many unknowns; minimizing the number of
functions is important. Deciding on a standard set of APIs, even if they
are low level, reduces the learning curve.  A good API can be used
across applications and across languages. A good API is also a guide to
help avoid pathological implementations.

Encountering your use of `debug` makes me think of more requirements for
a logging library:

**ease of use** - the logging library should require only a single line
of code for ad-hoc logging logging (to the console)

**default on** - logging defaults to "on", and/or emits instructions on
how to turn it on if it is "off".

**easy to mock** - this will allow quick implementation in the event a
full library is not available. 
https://github.com/klahnakoski/MoDevMetrics/blob/e10ac02b3c7120f0f779072743fa5ba612d62362/html/modevlib/threads/thread.js#L557
> <mailto:klahn...@mozilla.com <mailto:klahn...@mozilla.com>>>
> >     <mailto:mozill...@lists.mozilla.org
> <mailto:mozill...@lists.mozilla.org>>
> >     >>
> >     >> Good day frontend-infra team!
> >     >>
> >     >> In my experience, every reasonably sized application uses
> a logging
> >     >> library of some sort.  Even the health dashboard has one
> hidden one
> >     >> called `reportOrLog` [1]:  it is used to shunt errors
> from the
> >     console
> >     >> to the "Raven" library (whatever that does).  I would
> like for
> >     us to
> >     >> settle on one for all our javascript projects.
> >     > I don't think we will settle on a library because we're aiming
> >     to follow the same practice as in AirBnb to not log anything to
> >     the console. I failed to follow that in my reportOrLog code
> out of
> >     lazyness.
> >     >
> >     > Instead we might want to settle on a recommended practice (for
> >     example):
> >     >
> >     > * Use a top app error boundary for app level issues
> >     > * Use a component error boundary
> >     > * If an error reaches the error boundary report it to
> Sentry or GCP
> >     > * Use the `ErrorPanel` component [1] for the UI to report
> issues
> >     >   * It supports showing full stack trace in development mode
> >     >
> >     > [1]
> https://mozilla-frontend-infra.github.io/components/#errorpanel
> >     >
> >     > _______________________________________________
> >     > tools mailing list
> >     > to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> <mailto:to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>>
> >     > https://lists.mozilla.org/listinfo/tools
> >     _______________________________________________
> >     tools mailing list
> >     to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> <mailto:to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>>
> >     https://lists.mozilla.org/listinfo/tools
> >
> _______________________________________________
> tools mailing list
> to...@lists.mozilla.org <mailto:to...@lists.mozilla.org>
> https://lists.mozilla.org/listinfo/tools
>
>
>
0 new messages