Closed sheoak closed 3 years ago
@sheoak Hi, thanks for filing an issue. I will try to look at it today and give you feedback.
@MarcSchaetz funny you just replied here a few minutes ago. I actually built a little solution for myself here and would like to suggest it as a implementation.
Basically, the behavior of other plugins nowadays seems to be to provide a createLogger
function as a named export.
This createLogger
then builds the logger and also has a key install
which would be used by the app.use
to call with the app
and possible options
.
All this could then be used by the user in a plugins/logger.js
to build their own logger which has the same preferences inside components and outside.
In the mean time, I basically did the same for myself with a bit of a workaround (wrapping the vuejs3-logger
in it's own plugin createLogger 🙈.
Maybe the code below will be helpful (it's workaround):
import VueLogger from 'vuejs3-logger'
const isProduction = process.env.NODE_ENV === 'production'
export const options = {
isEnabled: true,
logLevel: isProduction ? 'error' : 'debug',
stringifyArguments: false,
showLogLevel: true,
showMethodName: true,
separator: ':',
showConsoleColors: true,
}
function createLogger(options) {
return {
install (app, installOptions = {}) {
options = {...options, ...installOptions }
app.use(VueLogger, options)
console.log(`INSTALLING THE LOGGER`)
Object.assign(this, app.$log)
}
}
}
const loggerCreated = createLogger(options)
// outputs only the `{ install: … }` because at this point the logger is not installed and thus the `Object.assign` was not run. This however is also not possible to do any different way without going into the guts of the `vuejs3-logger` because the necessary function (`initLoggerInstance `) is currently `private`.
// console.log(`loggerCreated:`, loggerCreated)
export const logger = loggerCreated
export const log = loggerCreated
The improvement with official support of a createLogger
function would solve all the issues and would make the logger available upon first call and not just after it actually was initiated with app.use
.
Again, hope this helps and am looking forward to an update to this plugin 🌸.
Oh… and P.S.: hi from Germany 👍 just a few hundred km north from you 🚗 .
Quick followup: with a bit more testing, this workaround does not work properly. I am experimenting with a createLogger function in my own local copy of vue3-logger
however, I am not confident in Typescript and all that 🙈 . But maybe I can provide a scaffold based on my findings.
Further findings: This time it actually worked 🙈. The logger is now accessible outside of components and can be loaded by simply doing import { log } from '@/plugins/logger'
in my project.
Please note again, I am not proficient in Typescript so this is probably "ugly" for some 🙈.
Here is the function I added to the vue3-logger.ts
file:
public createLogger(options: ILoggerOptions) {
options = Object.assign(this.getDefaultOptions(), options);
if (this.isValidOptions(options, this.logLevels)) {
const $log = this.initLoggerInstance(options, this.logLevels);
$log.install = function (Vue: any, options: ILoggerOptions) {
Vue.provide('vuejs3-logger', $log);
Vue.config.globalProperties.$log = $log;
}
return $log
} else {
throw new Error(this.errorMessage);
}
}
And below is my plugins/logger.js
file which loads and creates the logger.
I have not found a way to directly export the createLogger
so that I can simply do a import { createLogger } from 'vuejs3-logger'
for now. But maybe a official release will fix that and someone with more understanding can get that done 🥇 .
import VueLogger from 'vuejs3-logger/src'
const isProduction = process.env.NODE_ENV === 'production'
export const options = {
isEnabled: true,
logLevel: isProduction ? 'error' : 'debug',
stringifyArguments: false,
showLogLevel: true,
showMethodName: true,
separator: ':',
showConsoleColors: true,
}
const loggerCreated = VueLogger.createLogger(options)
export const logger = loggerCreated
export const log = loggerCreated
The documention precise how to use vuejs3-logger outside of components, but I get an error when trying to use it outside (vuex store):
Vue warn]: inject() can only be used inside setup() or functional components.
import { inject } from 'vue' … async my_vuex_method() { … const logger = inject('vuejs3-logger') … }
Thanks for porting vuejs-logger to vue3!
@sheoak Ok, so I looked into it. The setup()
is part of the dependency injection system of Vue3 and can only be called by components.
There are two solutions which I think are the simplest to go for.
Vuex comes with it's own logger implementation, which can print useful informations about statechanges out of the box.
import { createLogger } from 'vuex'
const store = new Vuex.Store({
plugins: [createLogger()]
})
mutation trylog @ 18:46:41.820
prev state {}
mutation {type: "trylog", payload: undefined}payload: undefinedtype: "trylog"
next state {}
app.provide()
to store the logger outside components.createApp(App)
returns you a reference to the application. There you can call provide()
to register a value to a key.
The VueLogger stores itself into app.config.globalProperties.$log
. So you could do something like this:
// main.ts
import VueLogger from 'vuejs3-logger';
const app = createApp(App) // Create the application
.use(VueLogger); // Register VueLogger plugin
app.provide('vuejs3-logger-vuex', app.config.globalProperties.$log); // Register the logger instance with another key
app.use(store); // Register Vuex Plugin
app.mount('#app')
// store.ts
// ...
const logger = inject('vuejs3-logger-vuex');
logger.debug('Log message from store');
// ...
Further findings: This time it actually worked see_no_evil. The logger is now accessible outside of components and can be loaded by simply doing
import { log } from '@/plugins/logger'
in my project.Please note again, I am not proficient in Typescript so this is probably "ugly" for some see_no_evil.
Here is the function I added to the
vue3-logger.ts
file:public createLogger(options: ILoggerOptions) { options = Object.assign(this.getDefaultOptions(), options); if (this.isValidOptions(options, this.logLevels)) { const $log = this.initLoggerInstance(options, this.logLevels); $log.install = function (Vue: any, options: ILoggerOptions) { Vue.provide('vuejs3-logger', $log); Vue.config.globalProperties.$log = $log; } return $log } else { throw new Error(this.errorMessage); } }
And below is my
plugins/logger.js
file which loads and creates the logger.I have not found a way to directly export the
createLogger
so that I can simply do aimport { createLogger } from 'vuejs3-logger'
for now. But maybe a official release will fix that and someone with more understanding can get that done 1st_place_medal .import VueLogger from 'vuejs3-logger/src' const isProduction = process.env.NODE_ENV === 'production' export const options = { isEnabled: true, logLevel: isProduction ? 'error' : 'debug', stringifyArguments: false, showLogLevel: true, showMethodName: true, separator: ':', showConsoleColors: true, } const loggerCreated = VueLogger.createLogger(options) export const logger = loggerCreated export const log = loggerCreated
@chrisspiegl Thanks for the suggestion. I created a new issue (#2) for that. Would you please post your last comment there again? Thank you very much.
@MarcSchaetz Thank you for the suggestions with the vuex logger that is incredibly helpful and I did not know about before.
And I have posted my comment in the other issue 👍.
Great! I will try this as soon as possible, very helpful thank you!
The documention precise how to use vuejs3-logger outside of components, but I get an error when trying to use it outside (vuex store):
Vue warn]: inject() can only be used inside setup() or functional components.
import { inject } from 'vue' … async my_vuex_method() { … const logger = inject('vuejs3-logger') … }
Thanks for porting vuejs-logger to vue3!
@sheoak Ok, so I looked into it. The
setup()
is part of the dependency injection system of Vue3 and can only be called by components.There are two solutions which I think are the simplest to go for.
Using the build-in Vuex logger
Vuex comes with it's own logger implementation, which can print useful informations about statechanges out of the box.
import { createLogger } from 'vuex' const store = new Vuex.Store({ plugins: [createLogger()] })
Output:
mutation trylog @ 18:46:41.820 prev state {} mutation {type: "trylog", payload: undefined}payload: undefinedtype: "trylog" next state {}
Call
app.provide()
to store the logger outside components.
createApp(App)
returns you a reference to the application. There you can callprovide()
to register a value to a key. The VueLogger stores itself intoapp.config.globalProperties.$log
. So you could do something like this:// main.ts import VueLogger from 'vuejs3-logger'; const app = createApp(App) // Create the application .use(VueLogger); // Register VueLogger plugin app.provide('vuejs3-logger-vuex', app.config.globalProperties.$log); // Register the logger instance with another key app.use(store); // Register Vuex Plugin app.mount('#app')
// store.ts // ... const logger = inject('vuejs3-logger-vuex'); logger.debug('Log message from store'); // ...
How can I use it in an external js file? for example, a js file encapsulates axios request? According to the api refrence, the provide/inject feature cann't be called outside setup function. Except exporting the app instance createApp
function returned, is there a more elegant way to do this?
I've been having similar issues, I wanted to use vuejs3-logger in Pinia but provide/inject didn't work somehow.. This is how I ended up doing, not sure if this is too hacky..
const app = createApp(App);
const pinia = createPinia();
pinia.use(({ store }) => {
store.$log = markRaw(app.config.globalProperties.$log);
});
app.use(pinia);
app.use(router);
app.use(logger);
app.mount('#app');
The documention precise how to use vuejs3-logger outside of components, but I get an error when trying to use it outside (vuex store):
Thanks for porting vuejs-logger to vue3!