Browse Source

Ledger Live app logs are no longer saved in files but kept in memory

gre-patch-1
Gaëtan Renaudeau 6 years ago
parent
commit
5c6fcf03b5
No known key found for this signature in database GPG Key ID: 7B66B85F042E5451
  1. 1
      package.json
  2. 13
      src/components/ExportLogsBtn.js
  3. 6
      src/components/SettingsPage/sections/Help.js
  4. 8
      src/helpers/log.js
  5. 3
      src/internals/index.js
  6. 16
      src/logger/logger-transport-internal.js
  7. 17
      src/logger/logger-transport-main.js
  8. 15
      src/logger/logger-transport-renderer.js
  9. 66
      src/logger/logger.js
  10. 19
      src/main/bridge.js
  11. 3
      src/renderer/init.js
  12. 36
      yarn.lock

1
package.json

@ -109,7 +109,6 @@
"uncontrollable": "^6.0.0",
"uuid": "^3.2.1",
"winston": "^3.0.0",
"winston-daily-rotate-file": "^3.2.3",
"winston-transport": "^4.2.0",
"write-file-atomic": "^2.3.0",
"ws": "^5.1.1",

13
src/components/ExportLogsBtn.js

@ -2,12 +2,20 @@
import logger from 'logger'
import moment from 'moment'
import fs from 'fs'
import { webFrame, remote } from 'electron'
import { ipcRenderer, webFrame, remote } from 'electron'
import React, { Component } from 'react'
import { translate } from 'react-i18next'
import KeyHandler from 'react-key-handler'
import Button from './base/Button'
const queryLogs = () =>
new Promise(success => {
ipcRenderer.once('logs', (event: any, { logs }) => {
success(logs)
})
ipcRenderer.send('queryLogs')
})
function writeToFile(file, data) {
return new Promise((resolve, reject) => {
fs.writeFile(file, data, error => {
@ -33,7 +41,6 @@ class ExportLogsBtn extends Component<{
environment: __DEV__ ? 'development' : 'production',
userAgent: window.navigator.userAgent,
})
const date = new Date() // we don't want all the logs that happen after the Export was pressed ^^
const path = remote.dialog.showSaveDialog({
title: 'Export logs',
defaultPath: `ledgerlive-export-${moment().format(
@ -47,7 +54,7 @@ class ExportLogsBtn extends Component<{
],
})
if (path) {
const logs = await logger.queryAllLogs(date)
const logs = await queryLogs()
const json = JSON.stringify(logs)
await writeToFile(path, json)
}

6
src/components/SettingsPage/sections/Help.js

@ -5,7 +5,6 @@ import { translate } from 'react-i18next'
import type { T } from 'types/common'
import TrackPage from 'analytics/TrackPage'
import IconHelp from 'icons/Help'
import { resolveLogsDirectory } from 'helpers/log'
import { urls } from 'config/urls'
import ExportLogsBtn from 'components/ExportLogsBtn'
@ -52,10 +51,7 @@ class SectionHelp extends PureComponent<Props> {
>
<CleanButton />
</Row>
<Row
title={t('settings.exportLogs.title')}
desc={t('settings.exportLogs.desc', { logsDirectory: resolveLogsDirectory() })}
>
<Row title={t('settings.exportLogs.title')} desc={t('settings.exportLogs.desc')}>
<ExportLogsBtn />
</Row>
<Row

8
src/helpers/log.js

@ -4,14 +4,6 @@ import path from 'path'
import rimraf from 'rimraf'
import resolveUserDataDirectory from './resolveUserDataDirectory'
export const resolveLogsDirectory = () => {
const { LEDGER_LOGS_DIRECTORY } = process.env
if (LEDGER_LOGS_DIRECTORY) return LEDGER_LOGS_DIRECTORY
const electron = require('electron')
return path.resolve((electron.app || electron.remote.app).getPath('userData'), 'logs')
}
export const cleanUpBeforeClosingSync = () => {
rimraf.sync(resolveLogsDirectory(), { disableGlob: true })
rimraf.sync(path.resolve(resolveUserDataDirectory(), 'sqlite/*.log'))
}

3
src/internals/index.js

@ -2,12 +2,15 @@
import '@babel/polyfill'
import commands from 'commands'
import logger from 'logger'
import LoggerTransport from 'logger/logger-transport-internal'
import uuid from 'uuid/v4'
import { setImplementation } from 'api/network'
import sentry from 'sentry/node'
import { EXPERIMENTAL_HTTP_ON_RENDERER } from 'config/constants'
import { serializeError } from 'helpers/errors'
logger.add(new LoggerTransport())
require('../env')
process.title = 'Ledger Live Internal'

16
src/logger/logger-transport-internal.js

@ -0,0 +1,16 @@
import Transport from 'winston-transport'
export default class InternalTransport extends Transport {
log(info, callback) {
setImmediate(() => {
this.emit('logged', info)
})
process.send({
type: 'log',
log: info,
})
callback()
}
}

17
src/logger/logger-transport-main.js

@ -0,0 +1,17 @@
import Transport from 'winston-transport'
export default class MainTransport extends Transport {
logs = []
capacity = 2000
log(info, callback) {
setImmediate(() => {
this.emit('logged', info)
})
this.logs.unshift(info)
this.logs.splice(this.capacity)
callback()
}
}

15
src/logger/logger-transport-renderer.js

@ -0,0 +1,15 @@
import Transport from 'winston-transport'
export default class RendererTransport extends Transport {
ipcRenderer = require('electron').ipcRenderer
log(info, callback) {
setImmediate(() => {
this.emit('logged', info)
})
this.ipcRenderer.send('log', { log: info })
callback()
}
}

66
src/logger/logger.js

@ -2,7 +2,6 @@
import winston from 'winston'
import Transport from 'winston-transport'
import { resolveLogsDirectory } from 'helpers/log'
import anonymizer from 'helpers/anonymizer'
import pname from 'helpers/pname'
@ -18,66 +17,17 @@ import {
DEBUG_ANALYTICS,
} from 'config/constants'
require('winston-daily-rotate-file')
const { format } = winston
const { combine, json, timestamp } = format
let logIndex = 0
const pinfo = format(info => {
if (!info.pname) {
info.pname = pname
info.index = logIndex++
}
return info
})
function createDailyRotateFile(processName) {
return new winston.transports.DailyRotateFile({
dirname: resolveLogsDirectory(),
json: true,
filename: `ledger-live-${processName}-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
maxSize: '20m',
maxFiles: '7d',
})
}
const transports = [createDailyRotateFile(pname)]
const queryLogs = (processName: string, date: Date) =>
new Promise((resolve, reject) => {
const dailyRotateFile = createDailyRotateFile(processName)
const options = {
from: date - 10 * 60 * 1000,
until: date,
limit: 2000,
start: 0,
order: 'desc',
}
dailyRotateFile.query(options, (err, result) => {
if (err) {
reject(err)
return
}
resolve(result)
})
})
const queryAllLogs = async (date: Date = new Date()) => {
const internal = await queryLogs('internal', date)
const main = await queryLogs('main', date)
const renderer = await queryLogs('renderer', date)
const all = internal
.concat(main)
.concat(renderer)
.sort((a, b) => {
if (a.timestamp !== b.timestamp) {
return new Date(b.timestamp) - new Date(a.timestamp)
}
return b.index - a.index
})
return all
}
const transports = []
if (process.env.NODE_ENV !== 'production' || process.env.DEV_TOOLS) {
let consoleT
@ -130,6 +80,10 @@ const logger = winston.createLogger({
transports,
})
const add = (transport: *) => {
logger.add(transport)
}
const captureBreadcrumb = (breadcrumb: any) => {
if (!process.env.STORYBOOK_ENV) {
try {
@ -404,5 +358,9 @@ export default {
}
},
queryAllLogs,
add,
onLog: (log: *) => {
logger.log(log)
},
}

19
src/main/bridge.js

@ -7,9 +7,10 @@ import { ipcMain, app } from 'electron'
import { ipcMainListenReceiveCommands } from 'helpers/ipc'
import path from 'path'
import logger from 'logger'
import LoggerTransport from 'logger/logger-transport-main'
import sentry, { captureException } from 'sentry/node'
import user from 'helpers/user'
import { resolveLogsDirectory, cleanUpBeforeClosingSync } from 'helpers/log'
import { cleanUpBeforeClosingSync } from 'helpers/log'
import { deserializeError } from 'helpers/errors'
import setupAutoUpdater, { quitAndInstall } from './autoUpdate'
@ -17,9 +18,11 @@ import { setInternalProcessPID } from './terminator'
import { getMainWindow } from './app'
const loggerTransport = new LoggerTransport()
logger.add(loggerTransport)
// sqlite files will be located in the app local data folder
const LEDGER_LIVE_SQLITE_PATH = path.resolve(app.getPath('userData'), 'sqlite')
const LEDGER_LOGS_DIRECTORY = process.env.LEDGER_LOGS_DIRECTORY || resolveLogsDirectory()
const LEDGER_CONFIG_DIRECTORY = app.getPath('userData')
let internalProcess
@ -55,7 +58,6 @@ const bootInternalProcess = () => {
env: {
...process.env,
IS_INTERNAL_PROCESS: 1,
LEDGER_LOGS_DIRECTORY,
LEDGER_CONFIG_DIRECTORY,
LEDGER_LIVE_SQLITE_PATH,
INITIAL_SENTRY_ENABLED: sentryEnabled,
@ -76,6 +78,10 @@ ipcMain.on('clean-processes', () => {
killInternalProcess()
})
ipcMain.on('log', (e, { log }) => {
logger.onLog(log)
})
ipcMainListenReceiveCommands({
onUnsubscribe: requestId => {
if (!internalProcess) return
@ -118,6 +124,9 @@ function handleGlobalInternalMessage(payload) {
captureException(err)
break
}
case 'log':
logger.onLog(payload.log)
break
case 'setLibcoreBusy':
case 'setDeviceBusy':
case 'executeHttpQueryOnRenderer': {
@ -133,6 +142,10 @@ function handleGlobalInternalMessage(payload) {
}
}
ipcMain.on('queryLogs', event => {
event.sender.send('logs', { logs: loggerTransport.logs })
})
ipcMain.on('executeHttpQueryPayload', (event, payload) => {
const p = internalProcess
if (!p) return

3
src/renderer/init.js

@ -1,6 +1,7 @@
// @flow
import logger from 'logger'
import LoggerTransport from 'logger/logger-transport-renderer'
import React from 'react'
import { remote, webFrame } from 'electron'
import { render } from 'react-dom'
@ -34,6 +35,8 @@ import AppError from 'components/AppError'
import 'styles/global'
logger.add(new LoggerTransport())
const rootNode = document.getElementById('app')
const userDataDirectory = resolveUserDataDirectory()

36
yarn.lock

@ -5856,11 +5856,6 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
cycle@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI=
cyclist@~0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
@ -7807,13 +7802,6 @@ file-loader@^1.1.11:
loader-utils "^1.0.2"
schema-utils "^0.4.5"
file-stream-rotator@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/file-stream-rotator/-/file-stream-rotator-0.2.1.tgz#0d6fea1a9a7aba25a87cfd31b6e269e44e8f0af2"
integrity sha1-DW/qGpp6uiWofP0xtuJp5E6PCvI=
dependencies:
moment "^2.11.2"
filename-regex@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@ -10740,7 +10728,7 @@ log-update@^1.0.2:
ansi-escapes "^1.0.0"
cli-cursor "^1.0.2"
logform@^1.6.0, logform@^1.9.0:
logform@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/logform/-/logform-1.9.1.tgz#58b29d7b11c332456d7a217e17b48a13ad69d60a"
integrity sha512-ZHrZE8VSf7K3xKxJiQ1aoTBp2yK+cEbFcgarsjzI3nt3nE/3O0heNSppoOQMUJVMZo/xiVwCxiXIabaZApsKNQ==
@ -11218,7 +11206,7 @@ modify-filename@^1.1.0:
resolved "https://registry.yarnpkg.com/modify-filename/-/modify-filename-1.1.0.tgz#9a2dec83806fbb2d975f22beec859ca26b393aa1"
integrity sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=
moment@^2.11.2, moment@^2.21.0, moment@^2.22.2:
moment@^2.21.0, moment@^2.22.2:
version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
@ -16643,26 +16631,6 @@ window-size@^0.2.0:
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=
winston-compat@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/winston-compat/-/winston-compat-0.1.4.tgz#599b4ce807ffe728713ecc25ede3f6b89425b739"
integrity sha512-mMEfFsSm6GmkFF+f4/0UJtG4N1vSaczGmXLVJYmS/+u2zUaIPcw2ZRuwUg2TvVBjswgiraN+vNnAG8z4fRUZ4w==
dependencies:
cycle "~1.0.3"
logform "^1.6.0"
triple-beam "^1.2.0"
winston-daily-rotate-file@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-3.2.3.tgz#9f80e7a421ab32b073c1217bae62e762001197d6"
integrity sha512-BOvmvQH2WaiexOjzj14YNHSc18IDyZJ9t4pMsbTERjpjMltoBVijM8DDJJPr2jSqELSNnbgGPBk3kDQSRgOAtQ==
dependencies:
file-stream-rotator "^0.2.1"
semver "^5.5.0"
triple-beam "^1.3.0"
winston-compat "^0.1.4"
winston-transport "^4.2.0"
winston-transport@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.2.0.tgz#a20be89edf2ea2ca39ba25f3e50344d73e6520e5"

Loading…
Cancel
Save