Browse Source

Merge pull request #1047 from gre/better-logger-system

Better logger system, fix race condition, smaller log exports
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
108e3fc302
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      src/components/ExportLogsBtn.js
  2. 12
      src/helpers/pname.js
  3. 16
      src/helpers/resolveLogsDirectory.js
  4. 2
      src/internals/index.js
  5. 1
      src/logger/logger-storybook.js
  6. 56
      src/logger/logger.js
  7. 3
      src/main/bridge.js
  8. 2
      src/renderer/init.js
  9. 4
      src/sentry/install.js

31
src/components/ExportLogsBtn.js

@ -6,22 +6,17 @@ import { webFrame, remote } from 'electron'
import React, { Component } from 'react'
import { translate } from 'react-i18next'
import KeyHandler from 'react-key-handler'
import { getCurrentLogFile } from 'helpers/resolveLogsDirectory'
import Button from './base/Button'
function copyFile(source, target) {
const rd = fs.createReadStream(source)
const wr = fs.createWriteStream(target)
function writeToFile(file, data) {
return new Promise((resolve, reject) => {
rd.on('error', reject)
wr.on('error', reject)
wr.on('finish', resolve)
rd.pipe(wr)
}).catch(error => {
// $FlowFixMe
rd.destroy()
wr.end()
throw error
fs.writeFile(file, data, error => {
if (error) {
reject(error)
} else {
resolve()
}
})
})
}
@ -30,9 +25,7 @@ class ExportLogsBtn extends Component<{
hookToShortcut?: boolean,
}> {
export = async () => {
const srcLogFile = await getCurrentLogFile()
const resourceUsage = webFrame.getResourceUsage()
const ext = srcLogFile.match(/[.]log[.]gz$/) ? 'log.gz' : 'log'
logger.log('exportLogsMeta', {
resourceUsage,
release: __APP_VERSION__,
@ -44,16 +37,18 @@ class ExportLogsBtn extends Component<{
title: 'Export logs',
defaultPath: `ledgerlive-export-${moment().format(
'YYYY.MM.DD-HH.mm.ss',
)}-${__GIT_REVISION__ || 'unversionned'}.${ext}`,
)}-${__GIT_REVISION__ || 'unversionned'}.json`,
filters: [
{
name: 'All Files',
extensions: [ext],
extensions: ['json'],
},
],
})
if (path) {
await copyFile(srcLogFile, path)
const logs = await logger.queryAllLogs()
const json = JSON.stringify(logs)
await writeToFile(path, json)
}
}

12
src/helpers/pname.js

@ -0,0 +1,12 @@
// @flow
// Infer a "pname" aka short id version of process name
const pname =
typeof window === 'undefined'
? process.env.IS_INTERNAL_PROCESS
? 'internal'
: 'main'
: 'renderer'
export default pname

16
src/helpers/resolveLogsDirectory.js

@ -1,6 +1,5 @@
// @flow
import fs from 'fs'
import path from 'path'
const resolveLogsDirectory = () => {
@ -11,18 +10,3 @@ const resolveLogsDirectory = () => {
}
export default resolveLogsDirectory
export const getCurrentLogFile = () =>
new Promise((resolve, reject) => {
const dir = resolveLogsDirectory()
fs.readdir(dir, (err, files) => {
if (err) {
reject(err)
} else {
// last file is always the most up to date log. file will rotate.
const last = files[files.length - 1]
if (!last) reject(new Error('no logs'))
else resolve(path.resolve(dir, last))
}
})
})

2
src/internals/index.js

@ -7,8 +7,6 @@ import sentry from 'sentry/node'
import { EXPERIMENTAL_HTTP_ON_RENDERER } from 'config/constants'
import { serializeError } from 'helpers/errors'
logger.setProcessShortName('internal')
require('../env')
process.title = 'Ledger Live Internal'

1
src/logger/logger-storybook.js

@ -1,7 +1,6 @@
const noop = () => {}
module.exports = {
setProcessShortName: noop,
onCmd: noop,
onDB: noop,
onReduxAction: noop,

56
src/logger/logger.js

@ -4,6 +4,7 @@ import winston from 'winston'
import Transport from 'winston-transport'
import resolveLogsDirectory from 'helpers/resolveLogsDirectory'
import anonymizer from 'helpers/anonymizer'
import pname from 'helpers/pname'
import {
DEBUG_DEVICE,
@ -19,8 +20,6 @@ import {
require('winston-daily-rotate-file')
let pname = '?'
const { format } = winston
const { combine, json, timestamp } = format
@ -29,16 +28,49 @@ const pinfo = format(info => {
return info
})
const transports = [
new winston.transports.DailyRotateFile({
function createDailyRotateFile(processName) {
return new winston.transports.DailyRotateFile({
dirname: resolveLogsDirectory(),
json: true,
zippedArchive: true,
filename: 'application-%DATE%.log',
filename: `ledger-live-${processName}-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
maxSize: '20m',
maxSize: '10m',
maxFiles: '14d',
}),
]
})
}
const transports = [createDailyRotateFile(pname)]
const queryLogs = (processName: string) =>
new Promise((resolve, reject) => {
const dailyRotateFile = createDailyRotateFile(processName)
const options = {
from: new Date() - 60 * 60 * 1000,
until: new Date(),
limit: 100,
start: 0,
order: 'desc',
}
dailyRotateFile.query(options, (err, result) => {
if (err) {
reject(err)
return
}
resolve(result)
})
})
const queryAllLogs = async () => {
const internal = await queryLogs('internal')
const main = await queryLogs('main')
const renderer = await queryLogs('renderer')
const all = internal
.concat(main)
.concat(renderer)
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
return all
}
if (process.env.NODE_ENV !== 'production' || process.env.DEV_TOOLS) {
let consoleT
@ -125,12 +157,6 @@ const blacklistTooVerboseCommandResponse = [
]
export default {
setProcessShortName: (processShortName: string) => {
pname = processShortName
},
getProcessShortName: () => pname,
onCmd: (type: string, id: string, spentTime: number, data?: any) => {
if (logCmds) {
switch (type) {
@ -352,4 +378,6 @@ export default {
}
}
},
queryAllLogs,
}

3
src/main/bridge.js

@ -17,8 +17,6 @@ import { setInternalProcessPID } from './terminator'
import { getMainWindow } from './app'
logger.setProcessShortName('main')
// 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()
@ -51,6 +49,7 @@ const bootInternalProcess = () => {
internalProcess = fork(forkBundlePath, {
env: {
...process.env,
IS_INTERNAL_PROCESS: 1,
LEDGER_LOGS_DIRECTORY,
LEDGER_CONFIG_DIRECTORY,
LEDGER_LIVE_SQLITE_PATH,

2
src/renderer/init.js

@ -32,8 +32,6 @@ import AppError from 'components/AppError'
import 'styles/global'
logger.setProcessShortName('renderer')
const rootNode = document.getElementById('app')
const TAB_KEY = 9

4
src/sentry/install.js

@ -1,5 +1,5 @@
// @flow
import logger from 'logger'
import pname from 'helpers/pname'
import anonymizer from 'helpers/anonymizer'
/* eslint-disable no-continue */
@ -24,7 +24,7 @@ export default (Raven: any, shouldSendCallback: () => boolean, userId: string) =
sentry: true,
},
extra: {
process: logger.getProcessShortName(),
process: pname,
},
dataCallback: (data: mixed) => {
// We are mutating the data to anonymize everything.

Loading…
Cancel
Save