Skip to content
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

No logging message appear (ulog doesn't look to be loaded) #66

Open
toddb opened this issue May 12, 2021 · 22 comments
Open

No logging message appear (ulog doesn't look to be loaded) #66

toddb opened this issue May 12, 2021 · 22 comments

Comments

@toddb
Copy link

toddb commented May 12, 2021

The documentation for running anylogger assumes anylogger as bundled package where it is directly loaded in the browser and globally available. The problem looks to be that ulog is not actually bundled because the only reference to ulog as the implementation is an import. Bundlers will treeshake the package.

Expected

Add logging to a project and logging messages will be written to the console in the browser

Actual

Nothing appears inn the browser console.

Steps to reproduce

Created a brand new Vue project and add logging

  1. vue create logger-demo
  2. yarn install anylogger ulog
  3. add the logging code into main.js
  4. yarn serve
  5. load up the browser, dev tools and look at messages

Based on the sample README, only a reference to anylogger is required.

import anylogger from 'anylogger';

const log = anylogger('Logging');
log.debug('I will not log unless log level is reduced');
log.error('I should log even in default settings');

// result nothing logs

Add ulog import, still doesn't work (under my build system-let's assume "tree shaking" broadly)

import anylogger from 'anylogger';
import ulog from 'ulog';

const log = anylogger('Logging');
log.debug('I will not log unless log level is reduced');
log.error('I should log even in default settings');

// result still nothing logs (as ulog still isn't there)

Of course, the logging library is actually required to implement the interface. Without typings, it all gets hard and picked something random to log that ensures the library is bundled.

import anylogger from 'anylogger';
import ulog from 'ulog';

const log = anylogger('Logging');
// need a reference to include library and ensure no linting errors
log.debug(ulog.levels);  // ah, need typings so added `declare module 'ulog'` (or could use `ulog.d.ts`)
log.debug('I will not log unless log level is reduced');
log.error('I should log even in default settings');

// now I log
@Download
Copy link
Owner

Download commented May 20, 2021

Hi @toddb have a look at this section of the documentation:

Add to entry point

In the entry point of your application import ulog:

index.js

import "ulog"

https://github.com/Download/ulog#add-to-entry-point

You should import ulog (or some other anylogger adapter) as the very first import. That will ensure it is loaded first and then it imports anylogger and overwrites anylogger.ext, making sure that all created loggers will be ulog loggers. If you have a project on Github or somewhere else where I can see it than I can take a look at it to hopefully get it working for you.

I am open to ideas to improve the documentation on this. I kinda have a blind spot here since I know exactly how it works so I am not sure what I should change to make it more clear.

EDIT:

log.debug(ulog.levels); // ah, need typings so added declare module 'ulog' (or could use ulog.d.ts)

Mmm yes.... I am not sure about this part. I am a typescript novice. Does whether or not you use typings have any influence on tree-shaking? I can imagine that the statement import "ulog" is assumed to have side-effects and so never tree-shaked, whereas import ulog from "ulog" is maybe expected to be tree-shakeable if you never actually use the imported ulog object?

@toddb
Copy link
Author

toddb commented May 20, 2021

All your examples are without build chain tools. You just need to be aware of this. IMHO, you are a library builder of a library that is central (to real/professional software) that these days is just about never included as you document. We also use tool chains—thus an import is not enough. Just make a note of this is a bare minimum.

Note: this occurs because you auto register ulog. One way around this is to document manual registration which means that tool chains include the library. I personally did it by using it in a log message.

This is a tiny point. But it questions if the tool builder fully understands the customer and the customers' scenarios :-)

@Download
Copy link
Owner

All your examples are without build chain tools.

I am using Webpack myself in the build of ulog.
Check the webpack config.
Show your code that is not working.

Note: this occurs because you auto register ulog. One way around this is to document manual registration

Which is what the docs about adding to the entry point is supposed to be, If it's not good, please elaborate on how to improve it.

it questions if the tool builder fully understands the customer and the customers' scenarios :-)

So show me your scenario. How can I understand your Typescript scenario if I'm not a regular typescript user and you don't show it? ulog works find i.c.w. build tools. I specifically wrote it so it would work great with that.

@nopmop
Copy link

nopmop commented Jun 11, 2021

You could say:
because ulog auto registers, importing it at the beginning of each entry point of your app can end up not working with complex Webpack/Typescript compiler setups. An alternative then can be to use webpack's ProvidePlugin in the plugins section of your webpack.config.js like so:

        new webpack.ProvidePlugin({
          // ...
          ulog: 'ulog',
        }),

and then write if(ulog) true at the beginning of each module of your app where you want ulog to be available. Alternatively, if you provide also anylogger via ProvidePlugin, you can implicitly trigger auto registration and assign the logger like so: var log = ulog ? anylogger('myModule') : () => {}

Also say:
NOTE: the default level for logging in the browser is set to WARN. If you want to change it, say to ALL, and you encounter some type errors while using Typescript, you can use this syntactic workaround:
log['level'] = (log as any).ALL

@Download perhaps the README focuses a bit too much on discussing how you took so many awesome features from other packages, like when you quote the code from other loggers (DEBUG=test,my:*,-my:lib) a distracted user might be tempted to try that without realizing that it's a configuration option for debug. Actually the configuration via environment variables is unclear to me as well: with webpack running it with log=*=debug webpack ... or log=debug webpack ... or webpack --env log=debug doesn't seem to work. Oddities...
Where is this environment taken from? process.env in NodeJS? I'll have to read the code...

My two cents.

@Download
Copy link
Owner

because ulog auto registers, importing it at the beginning of each entry point of your app can end up not working with complex Webpack/Typescript compiler setups.

I still fail to see which 'complex setups' have an issue.
Also, I don't really think ProvidePlugin is the answer.
But I haven't actually seen the setup you are using that you have prolems with, so I may be wrong. I would still be very interested in seeing (and cloning, testing) the actual setup you have. Maybe you can share a repo for me to look at?

@Download perhaps the README focuses a bit too much on discussing how you took so many awesome features from other packages, like when you quote the code from other loggers (DEBUG=test,my:*,-my:lib) a distracted user might be tempted to try that without realizing that it's a configuration option for debug.

Yes, this may be true. On the other hand debug is the most popular logging package on NPM right now so I want to show people that ulog can be a drop-in replacement.

I have been swamped with work the last few months so I'm not working on ulog at the moment but one day I will come back to this. In the mean time if you want you could make a PR for the docs and or share a repo for me to look at. I am uncomfortable writring tips related to Typescript in the README myself because I am too unfamiliar with it.

@eviltik
Copy link

eviltik commented Sep 17, 2021

Got an issue, probably related to that ticket ?

Not working (no log in the console) :

import ulog from 'ulog';
import anylogger from 'anylogger';

const log = anylogger('Logging');
log.info('yeah');

This works:

import ulog from 'ulog';
import anylogger from 'anylogger';

const log = anylogger('Logging');
setTimeout(() => {
    log.info('yeah');
}, 200);

Same thing everywhere (i.e import ulog in index.js and import anylogger in another file)

@Download
Copy link
Owner

@eviltik
I guess you are including ulog.min.js via a script tag?
That will lazy-load ulog.lazy.min.js and this will give you a short delay in which logging is not yet available.
Please try with ulog.full.min.js and see if it makes a difference for you

@eviltik
Copy link

eviltik commented Sep 22, 2021

@Download no, i've npm install, then i'm using webpack with imports. no lazy load.

@Download
Copy link
Owner

Download commented Oct 5, 2021

Is there something you can share, like a Github project, that I can test out?

@eviltik
Copy link

eviltik commented Oct 12, 2021

yep, let me create a simple case

@eviltik
Copy link

eviltik commented Oct 12, 2021

@eviltik
Copy link

eviltik commented Oct 12, 2021

main code (src/frontend/index.js)

import ulog from 'ulog';
import anylogger from 'anylogger';

const log = anylogger('my app');

localStorage.setItem( 'log', 'info' );

// This fail
log.info('immediate');

setTimeout(() => {
    // This is ok
    log.info('delayed 1sec');
}, 1000);

"immediate" not written into the console as it should
"delayed 1sec" written into the console as expected.

Thank you

@toddb
Copy link
Author

toddb commented Oct 12, 2021

@eviltik here's my code inside a Vue application registration. These logs do get written to the console. There are some very subtle differences and I wonder if that makes a difference (which are the subject of this message). You could try logging 'ulog' to see if you see the same behaviour. (sorry, I see your repo but struggling with time at the moment.)

import anylogger from 'anylogger';
import ulog from 'ulog';

const log = anylogger('app');
log.debug(ulog.levels);
log.debug('Set log level \'%s\'', process.env.NODE_ENV);

@toddb
Copy link
Author

toddb commented Oct 13, 2021

@eviltik I also noticed this bug #56

@eviltik
Copy link

eviltik commented Oct 13, 2021

yes @toddb i noticed this bug too.

@Download what do you think ? thank you

@toddb
Copy link
Author

toddb commented Oct 13, 2021

@eviltik I think @Download has put out his design—ulog will just do its thing to "work". It's just not meeting all needs unfortunately.

I'm seeing others ask for async loading, you are looking for sync, I am looking for explicit. :-)

@Download
Copy link
Owner

Sorry I have been very busy. I will check out your code base later.

We will get this fixed.

@toddb I am open to suggestions for changes / improvements, but please make them actionable. And in the past, some have said things like 'just rewrite this in typescript', which I don't think is a reasonable change to suggest. I do like Typescript and foresee a version 3 written in Typescript in the future, but I intend to finish v2 first, which means solving all the little issues and making sure this is a robust logging library that people can rely on to work. Given how long it took to get here, that may take a lot of time still.

The current design is working pretty well imho and at this stage I intend to keep it like this and just iron out the issues first so we all have a stable 2.0 to work with. My design for this library is trying to meet some very ambitious requirements, many of which are actually contradictory:

  • Tiny footpriny. Current design has a footprint of just 2.7kB (including anylogger) and I'm very proud of that.
  • Drop-in replacement for debug. Imho a very valuable feature that dictates how config works in ulog and that allows us to use ulog / anylogger with all the thousands of libraries out there that have a hardcoded dependency on debug. I haven't gotten around to making an example project, but when I finally release 2.0 stable, I will make an example project that demonstrates how to use a library with a hardcoded dependency on debug and replace debug with ulog without having to make any changes to that library. The current design allows for that and I think that will prove to be a very useful feature that will reduce your bundle size and increase the feature set related to logging both at the same time.
  • Usable without having a dependency on it. No other library has this. Only log4js has something that comes close, but that's just for API changes within log4js itself. All other logging libraries require you to depend on it and we see the average JS app having dependencies on multiple logging libraries as a result. This is a HUGE problem to solve and I spend over 2 years thinking about it, prototyping solutions and building anylogger just to solve this. If you don't care about this it may not be helpful for you but I care deeply about final bundle size for my apps and using anylogger allows me to have only a 300+ bytes dependency and then use any logging library I choose instead of getting multiple 3kB - 6kB logging libraries included in my bundle. This will even allow us to get rid of the logging libraries that other libraries we use depend on and is how we can replace debug with ulog across our entire app.
  • Configurable outputs and formats, which debug does not have, even though it has a 500 bytes larger footprint than ulog.
  • Does not mangle the call stack. AFAIK, ulog is the only library that has formatting without mangling the call stack and this took a long time and is very valuable imho.
  • Extensible with mods. Basically you can do just about anything with ulog by just picking the right mods and adding your own.
  • Live configuration. Allmost all logging libraries out there require you to restart the server or reload the web page to have logging config changes apply. ulog applies them live. That's a very valuable feature imho.
  • Supporting every JS runtime I can get my hands on and test with. ulog supports Node JS 0.x and Internet Explorer and if I can get my hands on old Safari (iOS) versions I will test with that and fix that as well. Because the logger is often the last resort to debug hard issues so a logger should work everywhere in my opinion.

My top priority is this great feature set at a microscopically small size. And if I have to write the code in Chinese or binary to get it, I will write the code in Chinese or binary. Writing readable code is great, but having a tiny and rich logging library is more important to me. Sometimes the design may seem contrived (and I'm sure it can be improved), but if these improvements make the library bigger without adding features, I'm against them. Because in my experience. only a few devs actually read the code. The fast majority just uses it and they could care less on how it was written as long as it works great and doesn't bloat their bundle. And that's exactly what I intend ulog to do.

@Download
Copy link
Owner

@eviltik Took a quick glance at your codebase and it looks fine to me. Don't have the time to dig into it right now but I will. I promise.

Just a heads-up that you cannot combine the lazy loading with the sync behavior that you seek. But afaict from the quick glance at your code, you are not trying to.

I do want sync loading to work. You won't get the 2.7kB footprint (it will be closer to 6kB) but that's life. We have to make hard choices sometimes. But just to let you know, I deeply care about the sync loading scenario to work and if the fact that it's not working at the moment in your code is due to a bug in ulog I will make sure it gets fixed before the 2.0 final release.

@eviltik
Copy link

eviltik commented Oct 22, 2021

thank you @Download

It's important to fix this bug asap, because since a few months, a user who is testing ulog with webpack for this kind of usage will drop your lib immediately. I'm at this point too right now. Waiting for your fix ! ty

@harinair
Copy link

+1
Exact same issue I am experiencing in my React project which is using a npm workspace and monorepo. Any chance this can be fixed?

@harinair
Copy link

harinair commented Jun 4, 2022

Any work arounds? No one else facing this issue. I tried pretty much everything and I decided to remove ulog. My belief is it does not work in a rollup react library setup. Tried a lot of stuff... but I don't want to spend more time on this.

@toddb
Copy link
Author

toddb commented Jun 6, 2022

@harinair I see a couple of practical solutions. Roll back to ulog v1 (it did everything I wanted and mostly worked). I wouldn't recommend rolling your own Console anylogger implementation because IMHO it needs some logging level configuration that start to be a lot of work (ps I did :-().

I hope there is some sense in there that is useful.

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

No branches or pull requests

5 participants