diff --git a/electron/package.json b/electron/package.json index 8bc4b53a..5e126a2b 100644 --- a/electron/package.json +++ b/electron/package.json @@ -53,7 +53,7 @@ "eslint-plugin-import": "^2.22.1" }, "dependencies": { - "@lightningrodlabs/electron-holochain": "=0.7.8", + "@lightningrodlabs/electron-holochain": "=0.7.12", "electron-context-menu": "^3.5.0", "electron-default-menu": "^1.0.2", "electron-log": "^4.3.5", diff --git a/electron/src/holochain.ts b/electron/src/holochain.ts index 73cffc22..fba31ccb 100644 --- a/electron/src/holochain.ts +++ b/electron/src/holochain.ts @@ -1,9 +1,6 @@ -import * as path from 'path' -import { app } from 'electron' import { ElectronHolochainOptions, StateSignal, - PathOptions, } from '@lightningrodlabs/electron-holochain' import { DATASTORE_PATH, KEYSTORE_PATH, PROFILES_HAPP_PATH } from './paths' @@ -53,6 +50,7 @@ const devOptions: ElectronHolochainOptions = { keystorePath: KEYSTORE_PATH, passphrase: 'test-passphrase', bootstrapUrl: 'https://bootstrap.holo.host', + logging: 'Json', } const prodOptions: ElectronHolochainOptions = { happPath: PROFILES_HAPP_PATH, // preload @@ -63,6 +61,7 @@ const prodOptions: ElectronHolochainOptions = { keystorePath: KEYSTORE_PATH, passphrase: 'test-passphrase', bootstrapUrl: 'https://bootstrap.holo.host', + logging: 'Json', } export { devOptions, prodOptions } diff --git a/electron/src/index.ts b/electron/src/index.ts index 43bb52d3..1dcd2604 100644 --- a/electron/src/index.ts +++ b/electron/src/index.ts @@ -1,17 +1,13 @@ -import { - app, - BrowserWindow, - ipcMain, - shell, - autoUpdater, - Menu, -} from 'electron' +import { app, BrowserWindow, ipcMain, shell, autoUpdater, Menu } from 'electron' import * as contextMenu from 'electron-context-menu' import * as path from 'path' import * as fs from 'fs' import initAgent, { + ERROR_EVENT, StateSignal, STATUS_EVENT, + HOLOCHAIN_LOG_EVENT, + WASM_LOG_EVENT, } from '@lightningrodlabs/electron-holochain' import { devOptions, prodOptions, stateSignalToText } from './holochain' @@ -45,8 +41,6 @@ contextMenu.default({ showSaveImageAs: true, }) - - // Handle creating/removing shortcuts on Windows when installing/uninstalling. // if (require('electron-squirrel-startup')) { // eslint-disable-line global-require @@ -177,19 +171,37 @@ app.on('ready', async () => { const splashWindow = createSplashWindow() const opts = app.isPackaged ? prodOptions : devOptions const { statusEmitter, shutdown } = await initAgent(app, opts, BINARY_PATHS) + let mainWindow: BrowserWindow | null = null statusEmitter.on(STATUS_EVENT, (state: StateSignal) => { switch (state) { case StateSignal.IsReady: // important that this line comes before the next one // otherwise this triggers the 'all-windows-closed' // event - createMainWindow() + mainWindow = createMainWindow() splashWindow.close() break default: splashWindow.webContents.send('status', stateSignalToText(state)) } }) + statusEmitter.on(ERROR_EVENT, (error: Error) => { + if (!error.message.includes('no project meta exists')) { + if (mainWindow) { + mainWindow.webContents.send('holochainError', error.message) + } + } + }) + statusEmitter.on(HOLOCHAIN_LOG_EVENT, (log: string) => { + if (mainWindow) { + mainWindow.webContents.send('holochainLog', log) + } + }) + statusEmitter.on(WASM_LOG_EVENT, (log: string) => { + if (mainWindow) { + mainWindow.webContents.send('wasmLog', log) + } + }) }) // Quit when all windows are closed, except on macOS. There, it's common @@ -285,7 +297,7 @@ ipcMain.handle('checkForMigrationData', (event) => { ) return { file: existingMigrationPath, - data: prevVersionMigrationDataString + data: prevVersionMigrationDataString, } } else { return null diff --git a/web/src/components/NetworkInfo/NetworkInfo.tsx b/web/src/components/NetworkInfo/NetworkInfo.tsx index 58a9cb44..c0e578b0 100644 --- a/web/src/components/NetworkInfo/NetworkInfo.tsx +++ b/web/src/components/NetworkInfo/NetworkInfo.tsx @@ -6,14 +6,33 @@ import { VersionInfo } from '../../hooks/useVersionChecker' export type NetworkInfoProps = { versionInfo: VersionInfo + wasmLogs: string[] + holochainLogs: { + info: object[] + warn: object[] + error: object[] + debug: object[] + unknown: string[] + } + errors: string[] } -const NetworkInfo: React.FC = ( - { - versionInfo - } -) => { +enum LogsToShow { + Info = 'Info', + Warn = 'Warn', + Debug = 'Debug', + Error = 'Error', + Unknown = 'Unknown', +} + +const NetworkInfo: React.FC = ({ + versionInfo, + holochainLogs, + wasmLogs, + errors, +}) => { const [networkStats, setNetworkStats] = useState({}) + const [logsToShow, setLogsToShow] = useState(LogsToShow.Info) useEffect(() => { const getNetworkStats = async () => { @@ -28,6 +47,9 @@ const NetworkInfo: React.FC = ( return () => clearInterval(interval) }, []) + const logs = + holochainLogs[logsToShow.toLowerCase() as keyof typeof holochainLogs] + return (
@@ -46,6 +68,44 @@ const NetworkInfo: React.FC = ( updates every 5 seconds
+ +

Errors

+ {errors.map((error) => ( +

{error}

+ ))} + +

Wasm Logs

+ + {wasmLogs.map((log) => ( +

{log}

+ ))} +

Holochain Logs

+ + + + + +

{logsToShow} Logs

+ {logs.map((log: string | object, index: number) => { + return ( +

+ {typeof log === 'object' + ? log['fields']['message'] || + log['fields']['msg'] || + log['fields']['err'] + : log} + {'\n'}({typeof log === 'object' ? log['module_path'] : ''}) +

+ ) + })}
) } diff --git a/web/src/hooks/useHolochainErrorAndLog.ts b/web/src/hooks/useHolochainErrorAndLog.ts new file mode 100644 index 00000000..65766104 --- /dev/null +++ b/web/src/hooks/useHolochainErrorAndLog.ts @@ -0,0 +1,55 @@ +import { useEffect, useState } from 'react' + +export default function useHolochainErrorAndLog() { + const [wasmLogs, setWasmLogs] = useState([]) + const [holochainInfo, setHolochainInfo] = useState([]) + const [holochainWarn, setHolochainWarn] = useState([]) + const [holochainDebug, setHolochainDebug] = useState([]) + const [holochainError, setHolochainError] = useState([]) + const [holochainUnknown, setHolochainUnknown] = useState([]) + const [errors, setErrors] = useState([]) + + const subscribeToEvents = async () => { + if (window.require) { + const { ipcRenderer } = window.require('electron') + ipcRenderer.on('wasmLog', (event: object, log: string) => { + setWasmLogs((logs) => [...logs, log]) + }) + ipcRenderer.on('holochainLog', (event: object, log: string) => { + try { + let parsedLog: object = JSON.parse(log) + if (parsedLog['level'] === 'INFO') { + setHolochainInfo((logs) => [...logs, parsedLog]) + } else if (parsedLog['level'] === 'WARN') { + setHolochainWarn((logs) => [...logs, parsedLog]) + } else if (parsedLog['level'] === 'DEBUG') { + setHolochainDebug((logs) => [...logs, parsedLog]) + } else if (parsedLog['level'] === 'ERROR') { + setHolochainError((logs) => [...logs, parsedLog]) + } + } catch (e) { + setHolochainUnknown((logs) => [...logs, log]) + } + }) + ipcRenderer.on('holochainError', (event: object, error: string) => { + setErrors((errors) => [...errors, error]) + }) + } + } + + useEffect(() => { + subscribeToEvents() + }, []) + + return { + wasmLogs, + holochainLogs: { + info: holochainInfo, + warn: holochainWarn, + debug: holochainDebug, + error: holochainError, + unknown: holochainUnknown, + }, + errors, + } +} diff --git a/web/src/routes/App.component.tsx b/web/src/routes/App.component.tsx index e6f539da..22331ab9 100644 --- a/web/src/routes/App.component.tsx +++ b/web/src/routes/App.component.tsx @@ -56,6 +56,7 @@ import { } from '../redux/ephemeral/local-preferences/reducer.js' import { ProjectMetaState } from '../redux/persistent/projects/project-meta/reducer' import { MembersState } from '../redux/persistent/projects/members/reducer' +import useHolochainErrorAndLog from '../hooks/useHolochainErrorAndLog' export type AppStateProps = { projectMetas: ProjectMetaState @@ -154,6 +155,7 @@ const App: React.FC = ({ // const updateVersionInfo = useVersionChecker(true) const finishMigrationChecker = useFinishMigrationChecker() const { fileDownloaded, setFileDownloaded } = useFileDownloaded() + const { wasmLogs, holochainLogs, errors: holochainErrors } = useHolochainErrorAndLog() useEffect(() => { if (fileDownloaded) { @@ -337,7 +339,7 @@ const App: React.FC = ({ - {networkInfoOpen && } + {networkInfoOpen && } ) } diff --git a/yarn.lock b/yarn.lock index 1b87d8f0..86c451ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1670,10 +1670,10 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== -"@lightningrodlabs/electron-holochain@=0.7.8": - version "0.7.8" - resolved "https://registry.yarnpkg.com/@lightningrodlabs/electron-holochain/-/electron-holochain-0.7.8.tgz#7ef0ade47a720d96180ce847de9269e4f55c5b08" - integrity sha512-rJ3ashN7Qz6NLz/J19+O7rLDUB++4aAkBlSNI5xe9++3pLRs0WGxR8YWwiSO3FX4VsiPeTx+sZn9yLBkfiaXgQ== +"@lightningrodlabs/electron-holochain@=0.7.12": + version "0.7.12" + resolved "https://registry.yarnpkg.com/@lightningrodlabs/electron-holochain/-/electron-holochain-0.7.12.tgz#010bf6837b738b9245800ab61220ca34da93b2a7" + integrity sha512-p1TKr5FYYfFlNgeeT5tCCjDPOJ9hHqUPySj7iv50bOyIe1Ch+Rq5DniJEpV9NYCcPDGfZ1eoua2EUeHML2r/4g== dependencies: request "^2.88.2" split "^1.0.1"