From e08add956ed8e2d7f49c4ae97eeb4dbf3a6c4307 Mon Sep 17 00:00:00 2001 From: Georg Krause Date: Tue, 5 Sep 2023 17:01:12 +0200 Subject: [PATCH] Revert refactoring of frontend logging since its crashing #2215 #2214 #2212 Revert "refactor(front): rename logger timing stop functions to `measureLoading`" This reverts commit 9abdcb5ff7104e440d27013515b0a9f70773150c. Revert "chore(front): remove unused dependency and add eslint rule to prevent console usage" This reverts commit d1f9a99e1b35876bcb1b44330e33d0cf9f32c2b6. Revert "feat(front): use logger instead of console.log" This reverts commit b59e29883f2e277493ad8b8944551b9267d92f19. --- changes/changelog.d/2212.bugfix | 1 + front/.eslintrc.js | 3 - front/package.json | 1 + front/src/api/player.ts | 20 ++- front/src/components/Home.vue | 4 +- front/src/components/RemoteSearchForm.vue | 4 +- front/src/components/admin/SettingsGroup.vue | 9 +- front/src/components/auth/ApplicationNew.vue | 5 +- front/src/components/auth/SignupForm.vue | 2 +- front/src/components/common/ContentForm.vue | 6 +- front/src/components/favorites/List.vue | 4 +- front/src/components/library/AlbumBase.vue | 5 +- front/src/components/library/Albums.vue | 4 +- front/src/components/library/Artists.vue | 4 +- front/src/components/library/Home.vue | 4 +- front/src/components/library/Podcasts.vue | 4 +- front/src/components/library/Radios.vue | 4 +- .../manage/moderation/ReportCard.vue | 6 +- front/src/composables/audio/player.ts | 9 +- front/src/composables/audio/queue.ts | 12 +- front/src/composables/audio/tracks.ts | 11 +- front/src/composables/audio/visualizer.ts | 8 +- front/src/composables/onKeyboardShortcut.ts | 5 +- front/src/composables/useLogger.ts | 119 ++---------------- front/src/init/axios.ts | 2 +- front/src/init/webSocket.ts | 5 +- front/src/router/guards.ts | 7 +- front/src/store/auth.ts | 6 +- front/src/store/ui.ts | 6 +- front/src/views/Search.vue | 6 +- .../views/admin/moderation/ReportsList.vue | 5 +- front/src/views/content/remote/Card.vue | 5 +- front/src/views/playlists/List.vue | 4 +- front/yarn.lock | 5 + 34 files changed, 76 insertions(+), 229 deletions(-) create mode 100644 changes/changelog.d/2212.bugfix diff --git a/changes/changelog.d/2212.bugfix b/changes/changelog.d/2212.bugfix new file mode 100644 index 000000000..6672c6dfd --- /dev/null +++ b/changes/changelog.d/2212.bugfix @@ -0,0 +1 @@ +Revert changed logging to fix crashes diff --git a/front/.eslintrc.js b/front/.eslintrc.js index 6a2ecc376..c9ea0eb18 100644 --- a/front/.eslintrc.js +++ b/front/.eslintrc.js @@ -26,9 +26,6 @@ module.exports = { // NOTE: Nicer for the eye 'operator-linebreak': ['error', 'before'], - // NOTE: We have a logger instance - 'no-console': 'error', - // NOTE: Handled by typescript '@typescript-eslint/no-unused-vars': 'off', 'no-use-before-define': 'off', diff --git a/front/package.json b/front/package.json index 1ec1c5819..7bf331cd5 100644 --- a/front/package.json +++ b/front/package.json @@ -34,6 +34,7 @@ "fomantic-ui-css": "2.9.2", "howler": "2.2.3", "idb-keyval": "6.2.1", + "js-logger": "1.6.1", "lodash-es": "4.17.21", "lru-cache": "7.14.1", "moment": "2.29.4", diff --git a/front/src/api/player.ts b/front/src/api/player.ts index 97b91a851..53c72d5a0 100644 --- a/front/src/api/player.ts +++ b/front/src/api/player.ts @@ -4,10 +4,6 @@ import { createEventHook, refDefault, type EventHookOn, useEventListener } from import { createAudioSource } from '~/composables/audio/audio-api' import { effectScope, reactive, ref, type Ref } from 'vue' -import useLogger from '~/composables/useLogger' - -const logger = useLogger() - export interface SoundSource { uuid: string mimetype: string @@ -77,7 +73,7 @@ export class HTMLSound implements Sound { this.#audio.src = source this.#audio.preload = 'auto' - logger.log('CREATED SOUND INSTANCE', this) + console.log('CREATED SOUND INSTANCE', this) this.#scope.run(() => { useEventListener(this.#audio, 'ended', () => this.#soundEndEventHook.trigger(this)) @@ -88,19 +84,19 @@ export class HTMLSound implements Sound { }) useEventListener(this.#audio, 'waiting', () => { - logger.log('>> AUDIO WAITING', this) + console.log('>> AUDIO WAITING', this) }) useEventListener(this.#audio, 'playing', () => { - logger.log('>> AUDIO PLAYING', this) + console.log('>> AUDIO PLAYING', this) }) useEventListener(this.#audio, 'stalled', () => { - logger.log('>> AUDIO STALLED', this) + console.log('>> AUDIO STALLED', this) }) useEventListener(this.#audio, 'suspend', () => { - logger.log('>> AUDIO SUSPEND', this) + console.log('>> AUDIO SUSPEND', this) }) useEventListener(this.#audio, 'loadeddata', () => { @@ -110,7 +106,7 @@ export class HTMLSound implements Sound { useEventListener(this.#audio, 'error', (err) => { if (this.#ignoreError) return - logger.error('>> AUDIO ERRORED', err, this) + console.error('>> AUDIO ERRORED', err, this) this.isErrored.value = true this.isLoaded.value = true }) @@ -120,7 +116,7 @@ export class HTMLSound implements Sound { async preload () { this.isDisposed.value = false this.isErrored.value = false - logger.log('CALLING PRELOAD ON', this) + console.log('CALLING PRELOAD ON', this) this.#audio.load() } @@ -145,7 +141,7 @@ export class HTMLSound implements Sound { try { await this.#audio.play() } catch (err) { - logger.error('>> AUDIO PLAY ERROR', err, this) + console.error('>> AUDIO PLAY ERROR', err, this) this.isErrored.value = true } } diff --git a/front/src/components/Home.vue b/front/src/components/Home.vue index 23e16ea77..7cabd3cc6 100644 --- a/front/src/components/Home.vue +++ b/front/src/components/Home.vue @@ -5,7 +5,6 @@ import ChannelsWidget from '~/components/audio/ChannelsWidget.vue' import LoginForm from '~/components/auth/LoginForm.vue' import SignupForm from '~/components/auth/SignupForm.vue' import useMarkdown from '~/composables/useMarkdown' -import useLogger from '~/composables/useLogger' import { humanSize } from '~/utils/filters' import { useStore } from '~/store' import { computed } from 'vue' @@ -19,7 +18,6 @@ const labels = computed(() => ({ })) const store = useStore() -const logger = useLogger() const nodeinfo = computed(() => store.state.instance.nodeinfo) const podName = computed(() => get(nodeinfo.value, 'metadata.nodeName') || 'Funkwhale') @@ -56,7 +54,7 @@ const headerStyle = computed(() => { // TODO (wvffle): Check if needed const router = useRouter() whenever(() => store.state.auth.authenticated, () => { - logger.log('Authenticated, redirecting to /library…') + console.log('Authenticated, redirecting to /library…') router.push('/library') }) diff --git a/front/src/components/RemoteSearchForm.vue b/front/src/components/RemoteSearchForm.vue index 00e0c858b..7d3859d71 100644 --- a/front/src/components/RemoteSearchForm.vue +++ b/front/src/components/RemoteSearchForm.vue @@ -9,7 +9,6 @@ import { useStore } from '~/store' import axios from 'axios' import updateQueryString from '~/composables/updateQueryString' -import useLogger from '~/composables/useLogger' type Type = 'rss' | 'artists' | 'both' @@ -38,7 +37,6 @@ const type = ref(props.initialType) const id = ref(props.initialId) const errors = ref([] as string[]) -const logger = useLogger() const { t } = useI18n() const labels = computed(() => ({ title: type.value === 'rss' @@ -104,7 +102,7 @@ const submit = () => { const isLoading = ref(false) const createFetch = async () => { - logger.debug(id.value, props.standalone) + console.log(id.value, props.standalone) if (!id.value) return if (props.standalone) { history.replaceState(history.state, '', updateQueryString(location.href, 'id', id.value)) diff --git a/front/src/components/admin/SettingsGroup.vue b/front/src/components/admin/SettingsGroup.vue index ae05e1e48..609dd8a6e 100644 --- a/front/src/components/admin/SettingsGroup.vue +++ b/front/src/components/admin/SettingsGroup.vue @@ -18,16 +18,15 @@ const values = reactive({} as Record) const result = ref(null) const errors = ref([] as string[]) -const logger = useLogger() -const store = useStore() - -// TODO (wvffle): Use VueUse const fileRefs = reactive({} as Record) const setFileRef = (identifier: string) => (el: FunctionRef) => { - logger.debug(el) + console.log(el) fileRefs[identifier] = el as HTMLInputElement } +const logger = useLogger() +const store = useStore() + const settings = computed(() => { const byIdentifier = props.settingsData.reduce((acc, entry) => { acc[entry.identifier] = entry diff --git a/front/src/components/auth/ApplicationNew.vue b/front/src/components/auth/ApplicationNew.vue index 9cb2ac956..b099263fd 100644 --- a/front/src/components/auth/ApplicationNew.vue +++ b/front/src/components/auth/ApplicationNew.vue @@ -9,8 +9,6 @@ import { useStore } from '~/store' import ApplicationForm from '~/components/auth/ApplicationForm.vue' -import useLogger from '~/composables/useLogger' - interface Props { name?: string scopes?: string @@ -29,7 +27,6 @@ const defaults = reactive({ redirectUris: props.redirectUris }) -const logger = useLogger() const { t } = useI18n() const labels = computed(() => ({ title: t('components.auth.ApplicationNew.title') @@ -40,7 +37,7 @@ const store = useStore() const created = (application: Application) => { store.state.auth.applicationSecret = application.client_secret - logger.debug(application) + console.log(application) return router.push({ name: 'settings.applications.edit', params: { diff --git a/front/src/components/auth/SignupForm.vue b/front/src/components/auth/SignupForm.vue index 71c37543c..e08cbb1a7 100644 --- a/front/src/components/auth/SignupForm.vue +++ b/front/src/components/auth/SignupForm.vue @@ -42,7 +42,7 @@ const labels = computed(() => ({ const signupRequiresApproval = computed(() => props.signupApprovalEnabled ?? store.state.instance.settings.moderation.signup_approval_enabled.value) const formCustomization = computed(() => props.customization ?? store.state.instance.settings.moderation.signup_form_customization.value) -watchEffect(() => logger.debug(store.state.instance.settings.moderation.signup_approval_enabled.value)) +watchEffect(() => console.log(store.state.instance.settings.moderation.signup_approval_enabled.value)) const payload = reactive({ username: '', diff --git a/front/src/components/common/ContentForm.vue b/front/src/components/common/ContentForm.vue index afa02f994..3905cdb55 100644 --- a/front/src/components/common/ContentForm.vue +++ b/front/src/components/common/ContentForm.vue @@ -4,8 +4,6 @@ import { useVModel, watchDebounced, useTextareaAutosize, syncRef } from '@vueuse import { ref, computed, watchEffect, onMounted, nextTick, watch } from 'vue' import { useI18n } from 'vue-i18n' -import useLogger from '~/composables/useLogger' - interface Events { (e: 'update:modelValue', value: string): void } @@ -28,8 +26,6 @@ const props = withDefaults(defineProps(), { required: false }) -const logger = useLogger() - const { t } = useI18n() const { textarea, input } = useTextareaAutosize() const value = useVModel(props, 'modelValue', emit) @@ -51,7 +47,7 @@ const loadPreview = async () => { const response = await axios.post('text-preview/', { text: value.value, permissive: props.permissive }) preview.value = response.data.rendered } catch (error) { - logger.error(error) + console.error(error) } isLoadingPreview.value = false } diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index c14d2b0e5..83f6b23a0 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -64,8 +64,8 @@ const fetchFavorites = async () => { ordering: orderingString.value } - const measureLoading = logger.time('Loading user favorites') try { + logger.time('Loading user favorites') const response = await axios.get('tracks/', { params }) results.length = 0 @@ -81,7 +81,7 @@ const fetchFavorites = async () => { } catch (error) { useErrorHandler(error as Error) } finally { - measureLoading() + logger.timeEnd('Loading user favorites') isLoading.value = false } } diff --git a/front/src/components/library/AlbumBase.vue b/front/src/components/library/AlbumBase.vue index a03100672..257d4a9e7 100644 --- a/front/src/components/library/AlbumBase.vue +++ b/front/src/components/library/AlbumBase.vue @@ -15,7 +15,6 @@ import TagsList from '~/components/tags/List.vue' import AlbumDropdown from './AlbumDropdown.vue' import useErrorHandler from '~/composables/useErrorHandler' -import useLogger from '~/composables/useLogger' interface Events { (e: 'deleted'): void @@ -40,8 +39,6 @@ const isSerie = computed(() => object.value?.artist.content_category === 'podcas const totalDuration = computed(() => sum((object.value?.tracks ?? []).map(track => track.uploads[0]?.duration ?? 0))) const publicLibraries = computed(() => libraries.value?.filter(library => library.privacy_level === 'everyone') ?? []) -const logger = useLogger() - const { t } = useI18n() const labels = computed(() => ({ title: t('components.library.AlbumBase.title') @@ -96,7 +93,7 @@ const fetchTracks = async () => { tracks.push(...response.data.results) } } catch (error) { - logger.error(error) + console.error(error) } finally { isLoadingTracks.value = false } diff --git a/front/src/components/library/Albums.vue b/front/src/components/library/Albums.vue index 1e3f5c6b6..aab3ef9f3 100644 --- a/front/src/components/library/Albums.vue +++ b/front/src/components/library/Albums.vue @@ -72,7 +72,7 @@ const fetchData = async () => { content_category: 'music' } - const measureLoading = logger.time('Fetching albums') + logger.time('Fetching albums') try { const response = await axios.get('albums/', { params, @@ -86,7 +86,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - measureLoading() + logger.timeEnd('Fetching albums') isLoading.value = false } } diff --git a/front/src/components/library/Artists.vue b/front/src/components/library/Artists.vue index 17f38ee3e..4bfd1935b 100644 --- a/front/src/components/library/Artists.vue +++ b/front/src/components/library/Artists.vue @@ -73,7 +73,7 @@ const fetchData = async () => { has_albums: excludeCompilation.value } - const measureLoading = logger.time('Fetching artists') + logger.time('Fetching artists') try { const response = await axios.get('artists/', { params, @@ -87,7 +87,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - measureLoading() + logger.timeEnd('Fetching artists') isLoading.value = false } } diff --git a/front/src/components/library/Home.vue b/front/src/components/library/Home.vue index 49109f610..8ff6b2552 100644 --- a/front/src/components/library/Home.vue +++ b/front/src/components/library/Home.vue @@ -32,7 +32,7 @@ const labels = computed(() => ({ const isLoading = ref(false) const fetchData = async () => { isLoading.value = true - const measureLoading = logger.time('Loading latest artists') + logger.time('Loading latest artists') const params = { ordering: '-creation_date', @@ -47,7 +47,7 @@ const fetchData = async () => { } isLoading.value = false - measureLoading() + logger.timeEnd('Loading latest artists') } fetchData() diff --git a/front/src/components/library/Podcasts.vue b/front/src/components/library/Podcasts.vue index 0925a802d..c01ee6a1c 100644 --- a/front/src/components/library/Podcasts.vue +++ b/front/src/components/library/Podcasts.vue @@ -74,7 +74,7 @@ const fetchData = async () => { content_category: 'podcast' } - const measureLoading = logger.time('Fetching podcasts') + logger.time('Fetching podcasts') try { const response = await axios.get('artists/', { params, @@ -88,7 +88,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - measureLoading() + logger.timeEnd('Fetching podcasts') isLoading.value = false } } diff --git a/front/src/components/library/Radios.vue b/front/src/components/library/Radios.vue index f12b41b39..9ebb1a02b 100644 --- a/front/src/components/library/Radios.vue +++ b/front/src/components/library/Radios.vue @@ -64,7 +64,7 @@ const fetchData = async () => { ordering: orderingString.value } - const measureLoading = logger.time('Fetching radios') + logger.time('Fetching radios') try { const response = await axios.get('radios/radios/', { params @@ -75,7 +75,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - measureLoading() + logger.timeEnd('Fetching radios') isLoading.value = false } } diff --git a/front/src/components/manage/moderation/ReportCard.vue b/front/src/components/manage/moderation/ReportCard.vue index c68989b40..8305710ab 100644 --- a/front/src/components/manage/moderation/ReportCard.vue +++ b/front/src/components/manage/moderation/ReportCard.vue @@ -15,7 +15,6 @@ import NoteForm from '~/components/manage/moderation/NoteForm.vue' import useReportConfigs from '~/composables/moderation/useReportConfigs' import useErrorHandler from '~/composables/useErrorHandler' import useMarkdown from '~/composables/useMarkdown' -import useLogger from '~/composables/useLogger' interface Events { (e: 'updated', updating: { type: string }): void @@ -30,7 +29,6 @@ const emit = defineEmits() const props = defineProps() const configs = useReportConfigs() -const logger = useLogger() const obj = ref(props.initObj) const summary = useMarkdown(() => obj.value.summary ?? '') @@ -79,11 +77,11 @@ const actions = computed(() => { handler: async () => { try { await axios.delete(deleteUrl) - logger.info('Target deleted') + console.log('Target deleted') obj.value.target = undefined resolveReport(true) } catch (error) { - logger.error('Error while deleting target', error) + console.log('Error while deleting target', error) useErrorHandler(error as Error) } } diff --git a/front/src/composables/audio/player.ts b/front/src/composables/audio/player.ts index e9291b3f7..d2704e9e4 100644 --- a/front/src/composables/audio/player.ts +++ b/front/src/composables/audio/player.ts @@ -9,8 +9,6 @@ import { useStore } from '~/store' import axios from 'axios' import { useClamp } from '@vueuse/math' -import useLogger from '~/composables/useLogger' - // Looping export enum LoopingMode { None, @@ -19,6 +17,7 @@ export enum LoopingMode { } // Pausing + export enum PauseReason { UserInput, EndOfQueue, @@ -27,8 +26,6 @@ export enum PauseReason { EndOfRadio } -const logger = useLogger() - const MODE_MAX = 1 + Math.max(...Object.values(LoopingMode).filter(mode => typeof mode === 'number') as number[]) export const looping: Ref = useStorage('player:looping', LoopingMode.None) @@ -134,12 +131,12 @@ export const usePlayer = createGlobalState(() => { const trackListenSubmissions = () => { const store = useStore() whenever(listenSubmitted, async () => { - logger.log('Listening submitted!') + console.log('Listening submitted!') if (!store.state.auth.authenticated) return if (!currentTrack.value) return await axios.post('history/listenings/', { track: currentTrack.value.id }) - .catch((error) => logger.error('Could not record track in history', error)) + .catch((error) => console.error('Could not record track in history', error)) }) } diff --git a/front/src/composables/audio/queue.ts b/front/src/composables/audio/queue.ts index b906612a4..dd415a371 100644 --- a/front/src/composables/audio/queue.ts +++ b/front/src/composables/audio/queue.ts @@ -11,8 +11,6 @@ import { delMany, getMany, setMany } from '~/composables/data/indexedDB' import { setGain } from '~/composables/audio/audio-api' import { useTracks } from '~/composables/audio/tracks' -import useLogger from '~/composables/useLogger' - import axios from 'axios' export interface QueueTrackSource { @@ -38,8 +36,6 @@ export interface QueueTrack { sources: QueueTrackSource[] } -const logger = useLogger() - // Queue const tracks = useStorage('queue:tracks', [] as number[]) const shuffledIds = useStorage('queue:tracks:shuffled', [] as number[]) @@ -73,7 +69,7 @@ watchEffect(async () => { tracksById.set(track.id, track) } } catch (error) { - logger.error(error) + console.error(error) } finally { fetchingTracks.value = false } @@ -348,7 +344,7 @@ export const useQueue = createGlobalState(() => { const store = useStore() watchEffect(() => { if (store.state.radios.running && currentIndex.value === tracks.value.length - 1) { - logger.log('POPULATING QUEUE FROM RADIO') + console.log('POPULATING QUEUE FROM RADIO') return store.dispatch('radios/populateQueue') } }) @@ -383,7 +379,7 @@ export const useQueue = createGlobalState(() => { currentIndex.value = index delete localStorage.queue - })().catch((error) => logger.error('Could not successfully migrate between queue versions', error)) + })().catch((error) => console.error('Could not successfully migrate between queue versions', error)) } if (localStorage.player) { @@ -393,7 +389,7 @@ export const useQueue = createGlobalState(() => { setGain(volume ?? 0.7) delete localStorage.player } catch (error) { - logger.error('Could not successfully migrate between player versions', error) + console.error('Could not successfully migrate between player versions', error) } } } diff --git a/front/src/composables/audio/tracks.ts b/front/src/composables/audio/tracks.ts index 8ea991867..95b1214bb 100644 --- a/front/src/composables/audio/tracks.ts +++ b/front/src/composables/audio/tracks.ts @@ -11,7 +11,6 @@ import { useQueue } from '~/composables/audio/queue' import { soundImplementation } from '~/api/player' import useLRUCache from '~/composables/data/useLRUCache' -import useLogger from '~/composables/useLogger' import store from '~/store' import axios from 'axios' @@ -19,8 +18,6 @@ import axios from 'axios' const ALLOWED_PLAY_TYPES: (CanPlayTypeResult | undefined)[] = ['maybe', 'probably'] const AUDIO_ELEMENT = document.createElement('audio') -const logger = useLogger() - const soundPromises = new Map>() const soundCache = useLRUCache({ max: 3, @@ -98,7 +95,7 @@ export const useTracks = createGlobalState(() => { const sound = new SoundImplementation(sources) sound.onSoundEnd(() => { - logger.log('TRACK ENDED, PLAYING NEXT') + console.log('TRACK ENDED, PLAYING NEXT') // NOTE: We push it to the end of the job queue setTimeout(() => playNext(), 0) @@ -143,7 +140,7 @@ export const useTracks = createGlobalState(() => { return sound } - logger.log('NO TRACK IN CACHE, CREATING', track) + console.log('NO TRACK IN CACHE, CREATING', track) const soundPromise = createSoundPromise() soundPromises.set(track.id, soundPromise) return soundPromise @@ -174,7 +171,7 @@ export const useTracks = createGlobalState(() => { const { queue, currentIndex } = useQueue() if (queue.value.length <= index || index === -1) return - logger.log('LOADING TRACK', index) + console.log('LOADING TRACK', index) const track = queue.value[index] const sound = await createSound(track) @@ -184,7 +181,7 @@ export const useTracks = createGlobalState(() => { return } - logger.log('CONNECTING NODE', sound) + console.log('CONNECTING NODE', sound) sound.audioNode.disconnect() connectAudioSource(sound.audioNode) diff --git a/front/src/composables/audio/visualizer.ts b/front/src/composables/audio/visualizer.ts index 14c518a29..e59f23e13 100644 --- a/front/src/composables/audio/visualizer.ts +++ b/front/src/composables/audio/visualizer.ts @@ -4,8 +4,6 @@ import { AUDIO_CONTEXT, GAIN_NODE } from './audio-api' import { useResizeObserver, useStorage } from '@vueuse/core' import { watchEffect, ref, markRaw } from 'vue' -import useLogger from '~/composables/useLogger' - // @ts-expect-error butterchurn has no typings import butterchurnPresets from 'butterchurn-presets' @@ -13,8 +11,6 @@ import butterchurnPresets from 'butterchurn-presets' import butterchurn from 'butterchurn' export const useMilkDrop = (canvas: Ref) => { - const logger = useLogger() - const presets = Object.keys(butterchurnPresets) const visualizer = ref() @@ -28,7 +24,7 @@ export const useMilkDrop = (canvas: Ref) => { const name = presetName.value if (name === undefined) return - logger.log(`Switching to preset: '${name}'`) + console.log(`Switching to preset: '${name}'`) visualizer.value?.loadPreset(butterchurnPresets[name], 1) }) @@ -71,7 +67,7 @@ export const useMilkDrop = (canvas: Ref) => { try { visualizer.value?.render() } catch (error) { - logger.error(error) + console.error(error) loadRandomPreset() } } diff --git a/front/src/composables/onKeyboardShortcut.ts b/front/src/composables/onKeyboardShortcut.ts index b54d428d3..2f066775e 100644 --- a/front/src/composables/onKeyboardShortcut.ts +++ b/front/src/composables/onKeyboardShortcut.ts @@ -2,8 +2,6 @@ import { DefaultMagicKeysAliasMap, tryOnScopeDispose, useEventListener } from '@ import { isEqual, isMatch } from 'lodash-es' import { reactive } from 'vue' -import useLogger from './useLogger' - type KeyFilter = string | string[] interface Entry { @@ -12,7 +10,6 @@ interface Entry { __location?: string } -const logger = useLogger() const combinations = reactive(new Map()) const current = new Set() @@ -62,7 +59,7 @@ export default (key: KeyFilter, handler: () => unknown, prevent = false) => { } if (collisions.length) { - logger.warn([ + console.warn([ 'onKeyboardShortcut detected a possible collision in:', `${entry.__location}: ${combination.join(' + ')}`, ...collisions diff --git a/front/src/composables/useLogger.ts b/front/src/composables/useLogger.ts index d1c86c13a..660c79385 100644 --- a/front/src/composables/useLogger.ts +++ b/front/src/composables/useLogger.ts @@ -1,112 +1,11 @@ -type LogLevel = 'info' | 'warn' | 'error' | 'debug' | 'time' +import Logger from 'js-logger' -const LOG_LEVEL_LABELS: Record = { - info: ' INFO', - warn: ' WARN', - error: 'ERROR', - debug: 'DEBUG', - time: ' TIME' -} +Logger.useDefaults({ + defaultLevel: import.meta.env.DEV + ? Logger.DEBUG + : Logger.WARN +}) -const LOG_LEVEL_BACKGROUND: Record = { - info: '#a6e22e', - warn: '#FF9800', - error: '#F44336', - debug: '#00BCD4', - time: '#00BCD4' -} - -const LOG_LEVEL_COLOR: Record = { - info: '#000', - warn: '#000', - error: '#fff', - debug: '#000', - time: '#000' -} - -const TIMESTAMP_COLOR = '#9E9E9E' - -const FILETYPE_BACKGROUND: Record = { - js: '#f1e05a', - ts: '#2b7489', - vue: '#41b883', - html: '#e34c26', - default: '#ccc' -} - -const FILETYPE_COLOR: Record = { - js: '#000', - ts: '#fff', - vue: '#fff', - html: '#fff', - default: '#000' -} - -const getFile = () => { - const { stack } = new Error() - const line = stack?.split('\n')[2] ?? '' - const [, method, url, lineNo] = line.match(/^(\w+)?(?:\/<)*@(.+?)(?:\?.*)?:(\d+):\d+$/) ?? [] - const file = url.startsWith(location.origin) ? url.slice(location.origin.length) : url - return { method, file, lineNo } -} - -// NOTE: We're pushing all logs to the end of the event loop -const createLoggerFn = (level: LogLevel) => { - // NOTE: We don't want to handle logs ourselves in tests - // eslint-disable-next-line no-console - if (import.meta.env.VITEST) return console[level] - - return (...args: any[]) => { - const timestamp = new Date().toUTCString() - const { method, file, lineNo } = getFile() - - const ext = file?.split('.').pop() ?? 'default' - - // NOTE: Don't log time and debug in production - if (level === 'time' || level === 'debug') { - if (import.meta.env.PROD) return - } - - // eslint-disable-next-line no-console - console[level === 'time' ? 'debug' : level]( - '%c %c [%s] %c %s %c%s', - `background: ${LOG_LEVEL_BACKGROUND[level]};border-radius:1em`, - `color: ${TIMESTAMP_COLOR}`, - timestamp, - `background: ${LOG_LEVEL_BACKGROUND[level]}; color: ${LOG_LEVEL_COLOR[level]}; border-radius: 1em 0 0 1em`, - LOG_LEVEL_LABELS[level], - `background: ${FILETYPE_BACKGROUND[ext]}; color: ${FILETYPE_COLOR[ext]}; border-radius: 0 1em 1em 0`, - method !== undefined - ? ` ${file}:${lineNo} ${method}() ` - : ` ${file}:${lineNo} `, - ...args - ) - } -} - -const infoLogger = createLoggerFn('info') -const warnLogger = createLoggerFn('warn') -const timeLogger = createLoggerFn('time') - -const errorLogger = createLoggerFn('error') -const debugLogger = createLoggerFn('debug') - -export const logger = { - log: infoLogger, - info: infoLogger, - warn: warnLogger, - error: errorLogger, - debug: debugLogger, - time: (label: string) => { - const now = performance.now() - - timeLogger(`${label}: start`) - - return () => { - const duration = performance.now() - now - timeLogger(`${label}: ${duration.toFixed(2)}ms`) - } - } -} - -export default () => logger +export default (logger?: string) => logger + ? Logger.get(logger) + : Logger diff --git a/front/src/init/axios.ts b/front/src/init/axios.ts index 35d17deb1..6b474fd14 100644 --- a/front/src/init/axios.ts +++ b/front/src/init/axios.ts @@ -118,7 +118,7 @@ export const install: InitModule = ({ store, router }) => { const refreshAuth = async (failedRequest: AxiosError) => { if (store.state.auth.oauth.accessToken) { - logger.warn('Failed request, refreshing auth…') + console.log('Failed request, refreshing auth…') try { // maybe the token was expired, let's try to refresh it diff --git a/front/src/init/webSocket.ts b/front/src/init/webSocket.ts index 0033a893f..b8fe0c151 100644 --- a/front/src/init/webSocket.ts +++ b/front/src/init/webSocket.ts @@ -3,12 +3,9 @@ import type { InitModule } from '~/types' import { watchEffect, watch } from 'vue' import { useWebSocket, whenever } from '@vueuse/core' import useWebSocketHandler from '~/composables/useWebSocketHandler' -import useLogger from '~/composables/useLogger' import { CLIENT_RADIOS } from '~/utils/clientRadios' export const install: InitModule = ({ store }) => { - const logger = useLogger() - watch(() => store.state.instance.instanceUrl, () => { const url = store.getters['instance/absoluteUrl']('api/v1/activity') .replace(/^http/, 'ws') @@ -28,7 +25,7 @@ export const install: InitModule = ({ store }) => { }) watchEffect(() => { - logger.log('Websocket status:', status.value) + console.log('Websocket status:', status.value) }) }, { immediate: true }) diff --git a/front/src/router/guards.ts b/front/src/router/guards.ts index 46804b98c..f9084416a 100644 --- a/front/src/router/guards.ts +++ b/front/src/router/guards.ts @@ -1,23 +1,20 @@ import type { NavigationGuardNext, RouteLocationNamedRaw, RouteLocationNormalized } from 'vue-router' import type { Permission } from '~/store/auth' -import useLogger from '~/composables/useLogger' import store from '~/store' -const logger = useLogger() - export const hasPermissions = (permission: Permission) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { if (store.state.auth.authenticated && store.state.auth.availablePermissions[permission]) { return next() } - logger.warn('Not authenticated. Redirecting to library.') + console.log('Not authenticated. Redirecting to library.') next({ name: 'library.index' }) } export const requireLoggedIn = (fallbackLocation?: RouteLocationNamedRaw) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { if (store.state.auth.authenticated) return next() - logger.debug('!', to) + console.log('!', to) return next(fallbackLocation ?? { name: 'login', query: { next: to.fullPath } }) } diff --git a/front/src/store/auth.ts b/front/src/store/auth.ts index d2a3f1530..a8b581890 100644 --- a/front/src/store/auth.ts +++ b/front/src/store/auth.ts @@ -168,7 +168,7 @@ const store: Module = { try { await axios.post('users/logout') } catch (error) { - logger.error('Error while logging out, probably logged in via oauth', error) + console.log('Error while logging out, probably logged in via oauth') } const modules = [ @@ -249,11 +249,11 @@ const store: Module = { const redirectUri = encodeURIComponent(`${location.origin}/auth/callback`) const params = `response_type=code&scope=${encodeURIComponent(NEEDED_SCOPES)}&redirect_uri=${redirectUri}&state=${next}&client_id=${state.oauth.clientId}` const authorizeUrl = `${rootState.instance.instanceUrl}authorize?${params}` - logger.log('Redirecting user...', authorizeUrl) + console.log('Redirecting user...', authorizeUrl) window.location.href = authorizeUrl }, async handleOauthCallback ({ state, commit, dispatch }, authorizationCode) { - logger.log('Fetching token...') + console.log('Fetching token...') const payload = { client_id: state.oauth.clientId, client_secret: state.oauth.clientSecret, diff --git a/front/src/store/ui.ts b/front/src/store/ui.ts index f7ad005df..9baf941ce 100644 --- a/front/src/store/ui.ts +++ b/front/src/store/ui.ts @@ -5,8 +5,6 @@ import type { SUPPORTED_LOCALES } from '~/init/locale' import axios from 'axios' import moment from 'moment' -import useLogger from '~/composables/useLogger' - type SupportedExtension = 'flac' | 'ogg' | 'mp3' | 'opus' | 'aac' | 'm4a' | 'aiff' | 'aif' export type WebSocketEventName = 'inbox.item_added' | 'import.status_updated' | 'mutation.created' | 'mutation.updated' @@ -52,8 +50,6 @@ export interface State { websocketEventsHandlers: Record } -const logger = useLogger() - const store: Module = { namespaced: true, state: { @@ -240,7 +236,7 @@ const store: Module = { websocketEvent ({ state }, event: WebSocketEvent) { const handlers = state.websocketEventsHandlers[event.type] - logger.log('Dispatching websocket event', event, handlers) + console.log('Dispatching websocket event', event, handlers) if (!handlers) { return } diff --git a/front/src/views/Search.vue b/front/src/views/Search.vue index 4288e5d97..f187894cc 100644 --- a/front/src/views/Search.vue +++ b/front/src/views/Search.vue @@ -19,7 +19,6 @@ import RadioCard from '~/components/radios/Card.vue' import TagsList from '~/components/tags/List.vue' import useErrorHandler from '~/composables/useErrorHandler' -import useLogger from '~/composables/useLogger' type QueryType = 'artists' | 'albums' | 'tracks' | 'playlists' | 'tags' | 'radios' | 'podcasts' | 'series' | 'rss' @@ -36,8 +35,6 @@ syncRef(pageQuery, page, { direction: 'both' }) -const logger = useLogger() - const q = useRouteQuery('q', '') const query = ref(q.value) syncRef(q, query, { direction: 'ltr' }) @@ -212,7 +209,8 @@ const radioConfig = computed(() => { } as RadioConfig } - logger.warn('This type is not yet supported for radio') + // TODO (wvffle): Use logger + console.info('This type is not yet supported for radio') } return null diff --git a/front/src/views/admin/moderation/ReportsList.vue b/front/src/views/admin/moderation/ReportsList.vue index d1ab1d1e0..40e40e7b9 100644 --- a/front/src/views/admin/moderation/ReportsList.vue +++ b/front/src/views/admin/moderation/ReportsList.vue @@ -20,7 +20,6 @@ import useSharedLabels from '~/composables/locale/useSharedLabels' import useOrdering from '~/composables/navigation/useOrdering' import useErrorHandler from '~/composables/useErrorHandler' import usePage from '~/composables/navigation/usePage' -import useLogger from '~/composables/useLogger' interface Props extends SmartSearchProps, OrderingProps { mode?: 'card' @@ -38,8 +37,6 @@ const props = withDefaults(defineProps(), { orderingConfigName: undefined }) -const logger = useLogger() - const search = ref() const page = usePage() @@ -71,7 +68,7 @@ const fetchData = async () => { result.value = response.data if (query.value === 'resolved:no') { - logger.log('Refreshing sidebar notifications') + console.log('Refreshing sidebar notifications') store.commit('ui/incrementNotifications', { type: 'pendingReviewReports', value: response.data.count diff --git a/front/src/views/content/remote/Card.vue b/front/src/views/content/remote/Card.vue index ef95ba805..5ed2fa0eb 100644 --- a/front/src/views/content/remote/Card.vue +++ b/front/src/views/content/remote/Card.vue @@ -12,7 +12,6 @@ import RadioButton from '~/components/radios/Button.vue' import useErrorHandler from '~/composables/useErrorHandler' import useReport from '~/composables/moderation/useReport' -import useLogger from '~/composables/useLogger' interface Emits { (e: 'followed'): void @@ -32,8 +31,6 @@ const props = withDefaults(defineProps(), { displayCopyFid: true }) -const logger = useLogger() - const { report, getReportableObjects } = useReport() const store = useStore() @@ -83,7 +80,7 @@ const follow = async () => { library.value.follow = response.data emit('followed') } catch (error) { - logger.error(error) + console.error(error) store.commit('ui/addMessage', { content: t('views.content.remote.Card.error.follow', { error }), date: new Date() diff --git a/front/src/views/playlists/List.vue b/front/src/views/playlists/List.vue index bcd463bf7..feba0aeb9 100644 --- a/front/src/views/playlists/List.vue +++ b/front/src/views/playlists/List.vue @@ -65,7 +65,7 @@ const fetchData = async () => { playable: true } - const measureLoading = logger.time('Fetching albums') + logger.time('Fetching albums') try { const response = await axios.get('playlists/', { params @@ -76,7 +76,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - measureLoading() + logger.timeEnd('Fetching albums') isLoading.value = false } } diff --git a/front/yarn.lock b/front/yarn.lock index 40f5758b5..1e98ea3ee 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -4714,6 +4714,11 @@ jquery@^3.4.0: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== +js-logger@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/js-logger/-/js-logger-1.6.1.tgz#8f09671b515e4a6f31dced8fdb8923432e2c60af" + integrity sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA== + js-sdsl@^4.1.4: version "4.4.2" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847"