stacker.news/components/logger.js

311 lines
9.5 KiB
JavaScript
Raw Normal View History

Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
import { useMe } from './me'
import fancyNames from '@/lib/fancy-names.json'
import { gql, useMutation, useQuery } from '@apollo/client'
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
import { WALLET_LOGS } from '@/fragments/wallet'
import { getWalletBy } from '@/lib/constants'
const generateFancyName = () => {
// 100 adjectives * 100 nouns * 10000 = 100M possible names
const pickRandom = (array) => array[Math.floor(Math.random() * array.length)]
const adj = pickRandom(fancyNames.adjectives)
const noun = pickRandom(fancyNames.nouns)
const id = Math.floor(Math.random() * fancyNames.maxSuffix)
return `${adj}-${noun}-${id}`
}
export function detectOS () {
if (!window.navigator) return ''
const userAgent = window.navigator.userAgent
const platform = window.navigator.userAgentData?.platform || window.navigator.platform
const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K']
const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE']
const iosPlatforms = ['iPhone', 'iPad', 'iPod']
let os = null
if (macosPlatforms.indexOf(platform) !== -1) {
os = 'Mac OS'
} else if (iosPlatforms.indexOf(platform) !== -1) {
os = 'iOS'
} else if (windowsPlatforms.indexOf(platform) !== -1) {
os = 'Windows'
} else if (/Android/.test(userAgent)) {
os = 'Android'
} else if (/Linux/.test(platform)) {
os = 'Linux'
}
return os
}
export const LoggerContext = createContext()
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
export const LoggerProvider = ({ children }) => {
return (
<ServiceWorkerLoggerProvider>
<WalletLoggerProvider>
{children}
</WalletLoggerProvider>
</ServiceWorkerLoggerProvider>
)
}
const ServiceWorkerLoggerContext = createContext()
function ServiceWorkerLoggerProvider ({ children }) {
const me = useMe()
const [name, setName] = useState()
const [os, setOS] = useState()
useEffect(() => {
let name = window.localStorage.getItem('fancy-name')
if (!name) {
name = generateFancyName()
window.localStorage.setItem('fancy-name', name)
}
setName(name)
setOS(detectOS())
}, [])
const log = useCallback(level => {
return async (message, context) => {
if (!me || !me.privates?.diagnostics) return
const env = {
userAgent: window.navigator.userAgent,
// os may not be initialized yet
os: os || detectOS()
}
const body = {
level,
env,
// name may be undefined if it wasn't stored in local storage yet
// we fallback to local storage since on page reloads, the name may wasn't fetched from local storage yet
name: name || window.localStorage.getItem('fancy-name'),
message,
context
}
await fetch('/api/log', {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(body)
}).catch(console.error)
}
}, [me?.privates?.diagnostics, name, os])
const logger = useMemo(() => ({
info: log('info'),
warn: log('warn'),
error: log('error'),
name
}), [log, name])
useEffect(() => {
// for communication between app and service worker
const channel = new MessageChannel()
navigator?.serviceWorker?.controller?.postMessage({ action: 'MESSAGE_PORT' }, [channel.port2])
channel.port1.onmessage = (event) => {
const { message, level, context } = Object.assign({ level: 'info' }, event.data)
logger[level](message, context)
}
}, [logger])
return (
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
<ServiceWorkerLoggerContext.Provider value={logger}>
{children}
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
</ServiceWorkerLoggerContext.Provider>
)
}
export function useServiceWorkerLogger () {
return useContext(ServiceWorkerLoggerContext)
}
const WalletLoggerContext = createContext()
const WalletLogsContext = createContext()
const initIndexedDB = async (dbName, storeName) => {
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
return new Promise((resolve, reject) => {
if (!window.indexedDB) {
return reject(new Error('IndexedDB not supported'))
}
// https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
const request = window.indexedDB.open(dbName, 1)
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
let db
request.onupgradeneeded = () => {
// this only runs if version was changed during open
db = request.result
if (!db.objectStoreNames.contains(storeName)) {
const objectStore = db.createObjectStore(storeName, { autoIncrement: true })
objectStore.createIndex('ts', 'ts')
objectStore.createIndex('wallet_ts', ['wallet', 'ts'])
}
}
request.onsuccess = () => {
// this gets called after onupgradeneeded finished
db = request.result
resolve(db)
}
request.onerror = () => {
reject(new Error('failed to open IndexedDB'))
}
})
}
const WalletLoggerProvider = ({ children }) => {
const me = useMe()
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
const [logs, setLogs] = useState([])
let dbName = 'app:storage'
if (me) {
dbName = `${dbName}:${me.id}`
}
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
const idbStoreName = 'wallet_logs'
const idb = useRef()
const logQueue = useRef([])
useQuery(WALLET_LOGS, {
fetchPolicy: 'network-only',
// required to trigger onCompleted on refetches
notifyOnNetworkStatusChange: true,
onCompleted: ({ walletLogs }) => {
setLogs((prevLogs) => {
const existingIds = prevLogs.map(({ id }) => id)
const logs = walletLogs
.filter(({ id }) => !existingIds.includes(id))
.map(({ createdAt, wallet: walletType, ...log }) => {
return {
ts: +new Date(createdAt),
wallet: getWalletBy('type', walletType).logTag,
...log
}
})
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
return [...prevLogs, ...logs].sort((a, b) => a.ts - b.ts)
})
}
})
const [deleteServerWalletLogs] = useMutation(
gql`
mutation deleteWalletLogs($wallet: String) {
deleteWalletLogs(wallet: $wallet)
}
`,
{
onCompleted: (_, { variables: { wallet: walletType } }) => {
setLogs((logs) => {
return logs.filter(l => walletType ? l.wallet !== getWalletBy('type', walletType).logTag : false)
})
}
}
)
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
const saveLog = useCallback((log) => {
if (!idb.current) {
// IDB may not be ready yet
return logQueue.current.push(log)
}
const tx = idb.current.transaction(idbStoreName, 'readwrite')
const request = tx.objectStore(idbStoreName).add(log)
request.onerror = () => console.error('failed to save log:', log)
}, [])
useEffect(() => {
initIndexedDB(dbName, idbStoreName)
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
.then(db => {
idb.current = db
// load all logs from IDB
const tx = idb.current.transaction(idbStoreName, 'readonly')
const store = tx.objectStore(idbStoreName)
const index = store.index('ts')
const request = index.getAll()
request.onsuccess = () => {
const logs = request.result
setLogs((prevLogs) => {
// sort oldest first to keep same order as logs are appended
return [...prevLogs, ...logs].sort((a, b) => a.ts - b.ts)
})
}
// flush queued logs to IDB
logQueue.current.forEach(q => {
const isLog = !!q.wallet
if (isLog) saveLog(q)
})
logQueue.current = []
})
.catch(console.error)
return () => idb.current?.close()
}, [])
const appendLog = useCallback((wallet, level, message) => {
const log = { wallet: wallet.logTag, level, message, ts: +new Date() }
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
saveLog(log)
setLogs((prevLogs) => [...prevLogs, log])
}, [saveLog])
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
const deleteLogs = useCallback(async (wallet) => {
if (!wallet || wallet.server) {
await deleteServerWalletLogs({ variables: { wallet: wallet?.type } })
}
if (!wallet || !wallet.server) {
const tx = idb.current.transaction(idbStoreName, 'readwrite')
const objectStore = tx.objectStore(idbStoreName)
const idx = objectStore.index('wallet_ts')
const request = wallet ? idx.openCursor(window.IDBKeyRange.bound([wallet.logTag, -Infinity], [wallet.logTag, Infinity])) : idx.openCursor()
request.onsuccess = function (event) {
const cursor = event.target.result
if (cursor) {
cursor.delete()
cursor.continue()
} else {
// finished
setLogs((logs) => logs.filter(l => wallet ? l.wallet !== wallet.logTag : false))
}
}
}
}, [setLogs])
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
return (
<WalletLogsContext.Provider value={logs}>
<WalletLoggerContext.Provider value={{ appendLog, deleteLogs }}>
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
{children}
</WalletLoggerContext.Provider>
</WalletLogsContext.Provider>
)
}
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
export function useWalletLogger (wallet) {
const { appendLog, deleteLogs: innerDeleteLogs } = useContext(WalletLoggerContext)
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
const log = useCallback(level => message => {
// TODO:
// also send this to us if diagnostics was enabled,
// very similar to how the service worker logger works.
appendLog(wallet, level, message)
console[level !== 'error' ? 'info' : 'error'](`[${wallet.logTag}]`, message)
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
}, [appendLog, wallet])
const logger = useMemo(() => ({
ok: (...message) => log('ok')(message.join(' ')),
info: (...message) => log('info')(message.join(' ')),
error: (...message) => log('error')(message.join(' '))
}), [log, wallet])
const deleteLogs = useCallback((w) => innerDeleteLogs(w || wallet), [innerDeleteLogs, wallet])
return { logger, deleteLogs }
Wallet Logs (#994) * nwc wallet logs * persist logs in IndexedDB * Potential fix for empty error message * load logs limited to 5m ago from IDB * load logs from past via query param * Add 5m, 1h, 6h links for earlier logs * Show end of log * Clamp to logStart * Add log.module.css * Remove TODO about persistence * Use table for logs * <table> fixes bad format with fixed width and message overflow into start of next row * also using ---start of log--- instead of ---end of log--- now * removed time string in header nav * Rename .header to .logNav * Simply load all logs and remove navigation I realized the code for navigation was most likely premature optimization which even resulted in worse UX: Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago. That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it. But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like. I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization. WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this. If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited. But for now, this works fine. * Add follow checkbox * Create WalletLogs component * Embed wallet logs * Remove test error * Fix level padding * Add LNbits logs * Add logs for attaching LND and lnAddr * Use err.message || err.toString?.() consistently * Autowithdrawal logs * Use details from LND error * Don't log test invoice individually * Also refetch logs on error * Remove obsolete and annoying toasts * Replace scrollIntoView with scroll * Use constant embedded max-height * Fix missing width: 100% for embedded logs * Show full payment hash and preimage in logs * Also parse details from LND errors on autowithdrawal failures * Remove TODO * Fix accidental removal of wss:// check * Fix alignment of start marker and show empty if empty * Fix sendPayment loop * Split context in two
2024-04-03 22:27:21 +00:00
}
export function useWalletLogs (wallet) {
const logs = useContext(WalletLogsContext)
return logs.filter(l => !wallet || l.wallet === wallet.logTag)
}