Feature: add logFileSizeLimit for log file

ISSUES CLOSED: #935, #945
This commit is contained in:
PiEgg
2022-07-31 17:47:15 +08:00
parent 3102d7b1ea
commit 219b367f7c
12 changed files with 122 additions and 54 deletions

View File

@@ -19,6 +19,8 @@ import { T } from '~/universal/i18n'
import fse from 'fs-extra'
import path from 'path'
import { privacyManager } from '~/main/utils/privacyManager'
import writeFile from 'write-file-atomic'
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
const waitForShow = (webcontent: WebContents) => {
return new Promise<void>((resolve) => {
@@ -126,8 +128,8 @@ class Uploader {
const buffer = nativeImage.toPNG()
const baseDir = picgo.baseDir
const fileName = `${dayjs().format('YYYYMMDDHHmmSSS')}.png`
filePath = path.join(baseDir, fileName)
await fse.writeFile(filePath, buffer)
filePath = path.join(baseDir, CLIPBOARD_IMAGE_FOLDER, fileName)
await writeFile(filePath, buffer)
return await this.upload([filePath])
} catch (e: any) {
logger.error(e)

View File

@@ -1,4 +1,5 @@
import fs from 'fs-extra'
import writeFile from 'write-file-atomic'
import path from 'path'
import { app as APP } from 'electron'
import { getLogger } from '@core/utils/localLogger'
@@ -50,7 +51,7 @@ function dbChecker () {
try {
configFile = fs.readFileSync(configFileBackupPath, { encoding: 'utf-8' })
JSON.parse(configFile)
fs.writeFileSync(configFilePath, configFile, { encoding: 'utf-8' })
writeFile.sync(configFilePath, configFile, { encoding: 'utf-8' })
const stats = fs.statSync(configFileBackupPath)
optionsTpl.body = `${errorMsg.brokenButBackup}\n${T('TIPS_PICGO_BACKUP_FILE_VERSION', {
v: dayjs(stats.mtime).format('YYYY-MM-DD HH:mm:ss')
@@ -67,7 +68,7 @@ function dbChecker () {
global.notificationList?.push(optionsTpl)
return
}
fs.writeFileSync(configFileBackupPath, configFile, { encoding: 'utf-8' })
writeFile.sync(configFileBackupPath, configFile, { encoding: 'utf-8' })
}
}
@@ -97,7 +98,7 @@ function dbPathChecker (): string {
}
return _configFilePath
} catch (e) {
const picgoLogPath = path.join(STORE_PATH, 'picgo.log')
const picgoLogPath = path.join(STORE_PATH, 'picgo-gui-local.log')
const logger = getLogger(picgoLogPath)
if (!hasCheckPath) {
const optionsTpl = {
@@ -108,7 +109,6 @@ function dbPathChecker (): string {
hasCheckPath = true
}
logger('error', e)
console.error(e)
_configFilePath = defaultConfigPath
return _configFilePath
}

View File

@@ -2,6 +2,32 @@ import fs from 'fs-extra'
import dayjs from 'dayjs'
import util from 'util'
const checkLogFileIsLarge = (logPath: string): {
isLarge: boolean
logFileSize?: number
logFileSizeLimit?: number
} => {
if (fs.existsSync(logPath)) {
const logFileSize = fs.statSync(logPath).size
const logFileSizeLimit = 10 * 1024 * 1024 // 10 MB default
return {
isLarge: logFileSize > logFileSizeLimit,
logFileSize,
logFileSizeLimit
}
}
return {
isLarge: false
}
}
const recreateLogFile = (logPath: string): void => {
if (fs.existsSync(logPath)) {
fs.unlinkSync(logPath)
fs.createFileSync(logPath)
}
}
/**
* for local log before picgo inited
*/
@@ -9,21 +35,29 @@ const getLogger = (logPath: string) => {
if (!fs.existsSync(logPath)) {
fs.ensureFileSync(logPath)
}
if (checkLogFileIsLarge(logPath).isLarge) {
recreateLogFile(logPath)
}
return (type: string, ...msg: any[]) => {
let log = `${dayjs().format('YYYY-MM-DD HH:mm:ss')} [PicGo ${type.toUpperCase()}] `
msg.forEach((item: ILogArgvTypeWithError) => {
if (typeof item === 'object' && type === 'error') {
log += `\n------Error Stack Begin------\n${util.format(item.stack)}\n-------Error Stack End------- `
} else {
if (typeof item === 'object') {
item = JSON.stringify(item)
try {
let log = `${dayjs().format('YYYY-MM-DD HH:mm:ss')} [PicGo ${type.toUpperCase()}] `
msg.forEach((item: ILogArgvTypeWithError) => {
if (typeof item === 'object' && type === 'error') {
log += `\n------Error Stack Begin------\n${util.format(item.stack)}\n-------Error Stack End------- `
} else {
if (typeof item === 'object') {
item = JSON.stringify(item)
}
log += `${item} `
}
log += `${item} `
}
})
log += '\n'
// A synchronized approach to avoid log msg sequence errors
fs.appendFileSync(logPath, log)
})
log += '\n'
console.log(log)
// A synchronized approach to avoid log msg sequence errors
fs.appendFileSync(logPath, log)
} catch (e) {
console.error(e)
}
}
}

View File

@@ -1,36 +1,17 @@
import fse from 'fs-extra'
import path from 'path'
import dayjs from 'dayjs'
import util from 'util'
import { dbPathDir } from 'apis/core/datastore/dbChecker'
import { getLogger } from 'apis/core/utils/localLogger'
const STORE_PATH = dbPathDir()
const LOG_PATH = path.join(STORE_PATH, '/picgo.log')
const LOG_PATH = path.join(STORE_PATH, 'picgo-gui-local.log')
const logger = getLogger(LOG_PATH)
// since the error may occur in picgo-core
// so we can't use the log from picgo
export const loggerWriter = (error: Error) => {
try {
const time = dayjs().format('YYYY-MM-DD HH:mm:ss')
let log = `${time} [PicGo ERROR] process error begin`
if (error?.stack) {
log += `\n------Error Stack Begin------\n${util.format(error.stack)}\n-------Error Stack End-------\n`
} else {
const msg = JSON.stringify(error)
log += `${msg}\n`
}
log += `${time} [PicGo ERROR] process error end`
if (!fse.existsSync(LOG_PATH)) {
fse.ensureFileSync(LOG_PATH)
}
fse.appendFileSync(LOG_PATH, log)
} catch (e) {
console.error(e)
}
}
const handleProcessError = (error: Error) => {
console.error(error)
loggerWriter(error)
logger('error', error)
}
process.on('uncaughtException', error => {

View File

@@ -285,10 +285,11 @@
:title="$T('SETTINGS_SET_LOG_FILE')"
:visible.sync="logFileVisible"
:modal-append-to-body="false"
width="500px"
>
<el-form
label-position="right"
label-width="100px"
label-width="150px"
>
<el-form-item
:label="$T('SETTINGS_LOG_FILE')"
@@ -302,6 +303,7 @@
v-model="form.logLevel"
multiple
collapse-tags
style="width: 100%;"
>
<el-option
v-for="(value, key) of logLevel"
@@ -312,6 +314,17 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item
:label="`${$T('SETTINGS_LOG_FILE_SIZE')} (MB)`"
>
<el-input-number
style="width: 100%;"
v-model="form.logFileSizeLimit"
:placeholder="`${$T('SETTINGS_TIPS_SUCH_AS')}10`"
:controls="false"
:min="1"
></el-input-number>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="cancelLogLevelSetting" round>{{ $T('CANCEL') }}</el-button>
@@ -379,6 +392,7 @@ import {
} from 'electron'
import { Component, Vue } from 'vue-property-decorator'
import { T, languageList } from '~/universal/i18n'
import { enforceNumber } from '~/universal/utils/common'
// import db from '#/datastore'
const releaseUrl = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
const releaseUrlBackup = 'https://cdn.jsdelivr.net/gh/Molunerfinn/PicGo@latest/package.json'
@@ -407,7 +421,8 @@ export default class extends Vue {
autoCopyUrl: true,
checkBetaUpdate: true,
useBuiltinClipboard: false,
language: 'zh-CN'
language: 'zh-CN',
logFileSizeLimit: 10
}
languageList = languageList.map(item => ({
@@ -501,6 +516,7 @@ export default class extends Vue {
host: '127.0.0.1',
enable: true
}
this.form.logFileSizeLimit = enforceNumber(settings.logFileSizeLimit) || 10
}
}
@@ -686,7 +702,8 @@ export default class extends Vue {
return this.$message.error(this.$T('TIPS_PLEASE_CHOOSE_LOG_LEVEL'))
}
this.saveConfig({
'settings.logLevel': this.form.logLevel
'settings.logLevel': this.form.logLevel,
'settings.logFileSizeLimit': this.form.logFileSizeLimit
})
const successNotification = new Notification(this.$T('SETTINGS_SET_LOG_FILE'), {
body: this.$T('TIPS_SET_SUCCEED')
@@ -700,6 +717,7 @@ export default class extends Vue {
async cancelLogLevelSetting () {
this.logFileVisible = false
let logLevel = await this.getConfig<string | string[]>('settings.logLevel')
const logFileSizeLimit = await this.getConfig<number>('settings.logFileSizeLimit') || 10
if (!Array.isArray(logLevel)) {
if (logLevel && logLevel.length > 0) {
logLevel = [logLevel]
@@ -708,6 +726,7 @@ export default class extends Vue {
}
}
this.form.logLevel = logLevel
this.form.logFileSizeLimit = logFileSizeLimit
}
confirmServerSetting () {

View File

@@ -88,6 +88,7 @@ export const EN: ILocales = {
SETTINGS_TIPS_HAS_NEW_VERSION: 'PicGo has a new version, please click confirm to open download page',
SETTINGS_LOG_FILE: 'Log File',
SETTINGS_LOG_LEVEL: 'Log Level',
SETTINGS_LOG_FILE_SIZE: 'Log File Size',
SETTINGS_SET_PICGO_SERVER: 'Set PicGo Server',
SETTINGS_TIPS_SERVER_NOTICE: 'If you don\'t know what is the server\'s function, please read the document, or don\'t modify the configuration.',
SETTINGS_ENABLE_SERVER: 'Enable Server',

View File

@@ -87,6 +87,7 @@ export const ZH_CN = {
SETTINGS_TIPS_HAS_NEW_VERSION: 'PicGo更新啦请点击确定打开下载页面',
SETTINGS_LOG_FILE: '日志文件',
SETTINGS_LOG_LEVEL: '日志记录等级',
SETTINGS_LOG_FILE_SIZE: '日志文件大小',
SETTINGS_SET_PICGO_SERVER: '设置PicGo-Server',
SETTINGS_TIPS_SERVER_NOTICE: '如果你不知道Server的作用请阅读文档或者不用修改配置。',
SETTINGS_ENABLE_SERVER: '是否开启Server',

View File

@@ -11,6 +11,7 @@ interface ISettingForm {
checkBetaUpdate: boolean
useBuiltinClipboard: boolean
language: string
logFileSizeLimit: number
}
interface IShortKeyMap {

View File

@@ -37,3 +37,7 @@ export const handleStreamlinePluginName = (name: string) => {
export const simpleClone = (obj: any) => {
return JSON.parse(JSON.stringify(obj))
}
export const enforceNumber = (num: number | string) => {
return isNaN(Number(num)) ? 0 : Number(num)
}

View File

@@ -0,0 +1 @@
export const CLIPBOARD_IMAGE_FOLDER = 'picgo-clipboard-images'