feat: rotating log files by time instead of file size

This commit is contained in:
acgnhik 2022-11-06 12:15:11 +08:00
parent 3a7facce0b
commit d4a4904d54
10 changed files with 24 additions and 56 deletions

View File

@ -10,6 +10,6 @@
<body> <body>
<app-root></app-root> <app-root></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript> <noscript>Please enable JavaScript to continue using this application.</noscript>
<script src="runtime.af0deb37647841b9.js" type="module"></script><script src="polyfills.4b08448aee19bb22.js" type="module"></script><script src="main.dbd09d2079405adc.js" type="module"></script> <script src="runtime.0560bf422fb1ab67.js" type="module"></script><script src="polyfills.4b08448aee19bb22.js" type="module"></script><script src="main.dbd09d2079405adc.js" type="module"></script>
</body></html> </body></html>

View File

@ -1,6 +1,6 @@
{ {
"configVersion": 1, "configVersion": 1,
"timestamp": 1666085654716, "timestamp": 1667707262978,
"index": "/index.html", "index": "/index.html",
"assetGroups": [ "assetGroups": [
{ {
@ -15,14 +15,14 @@
"/146.5a8902910bda9e87.js", "/146.5a8902910bda9e87.js",
"/183.ee55fc76717674c3.js", "/183.ee55fc76717674c3.js",
"/45.c90c3cea2bf1a66e.js", "/45.c90c3cea2bf1a66e.js",
"/548.5d742bcea753ec09.js", "/548.91bbb60199d9e944.js",
"/91.3c224fe84835dadd.js", "/91.3c224fe84835dadd.js",
"/common.858f777e9296e6f2.js", "/common.858f777e9296e6f2.js",
"/index.html", "/index.html",
"/main.dbd09d2079405adc.js", "/main.dbd09d2079405adc.js",
"/manifest.webmanifest", "/manifest.webmanifest",
"/polyfills.4b08448aee19bb22.js", "/polyfills.4b08448aee19bb22.js",
"/runtime.af0deb37647841b9.js", "/runtime.0560bf422fb1ab67.js",
"/styles.2e152d608221c2ee.css" "/styles.2e152d608221c2ee.css"
], ],
"patterns": [] "patterns": []
@ -1638,7 +1638,7 @@
"/146.5a8902910bda9e87.js": "d9c33c7073662699f00f46f3a384ae5b749fdef9", "/146.5a8902910bda9e87.js": "d9c33c7073662699f00f46f3a384ae5b749fdef9",
"/183.ee55fc76717674c3.js": "2628c996ec80a6c6703d542d34ac95194283bcf8", "/183.ee55fc76717674c3.js": "2628c996ec80a6c6703d542d34ac95194283bcf8",
"/45.c90c3cea2bf1a66e.js": "e5bfb8cf3803593e6b8ea14c90b3d3cb6a066764", "/45.c90c3cea2bf1a66e.js": "e5bfb8cf3803593e6b8ea14c90b3d3cb6a066764",
"/548.5d742bcea753ec09.js": "1ae82ced33a49e48520babe08fcc030fb8f595e6", "/548.91bbb60199d9e944.js": "062b3a6424284294e5774bcb08ca76df7b0c4216",
"/91.3c224fe84835dadd.js": "2e3cdb6c44a8cf3241fe8dd89b27c37f212768f8", "/91.3c224fe84835dadd.js": "2e3cdb6c44a8cf3241fe8dd89b27c37f212768f8",
"/assets/animal/panda.js": "fec2868bb3053dd2da45f96bbcb86d5116ed72b1", "/assets/animal/panda.js": "fec2868bb3053dd2da45f96bbcb86d5116ed72b1",
"/assets/animal/panda.svg": "bebd302cdc601e0ead3a6d2710acf8753f3d83b1", "/assets/animal/panda.svg": "bebd302cdc601e0ead3a6d2710acf8753f3d83b1",
@ -3234,11 +3234,11 @@
"/assets/twotone/warning.js": "fb2d7ea232f3a99bf8f080dbc94c65699232ac01", "/assets/twotone/warning.js": "fb2d7ea232f3a99bf8f080dbc94c65699232ac01",
"/assets/twotone/warning.svg": "8c7a2d3e765a2e7dd58ac674870c6655cecb0068", "/assets/twotone/warning.svg": "8c7a2d3e765a2e7dd58ac674870c6655cecb0068",
"/common.858f777e9296e6f2.js": "b68ca68e1e214a2537d96935c23410126cc564dd", "/common.858f777e9296e6f2.js": "b68ca68e1e214a2537d96935c23410126cc564dd",
"/index.html": "77dfa5e5defa4b9918c19b2bef05ca991bdec934", "/index.html": "17482e27906b5ae0447920edbf4bf4f4c0c1838b",
"/main.dbd09d2079405adc.js": "2f7284b616ed9fc433b612c9dca53dc06a0f3aa1", "/main.dbd09d2079405adc.js": "2f7284b616ed9fc433b612c9dca53dc06a0f3aa1",
"/manifest.webmanifest": "62c1cb8c5ad2af551a956b97013ab55ce77dd586", "/manifest.webmanifest": "62c1cb8c5ad2af551a956b97013ab55ce77dd586",
"/polyfills.4b08448aee19bb22.js": "8e73f2d42cc13ca353cea5c886d930bd6da08d0d", "/polyfills.4b08448aee19bb22.js": "8e73f2d42cc13ca353cea5c886d930bd6da08d0d",
"/runtime.af0deb37647841b9.js": "79436e2995b15139193a457ad96e453a00af6844", "/runtime.0560bf422fb1ab67.js": "74c07903a5fd6d43a0d7690a93b0927f8eead22c",
"/styles.2e152d608221c2ee.css": "9830389a46daa5b4511e0dd343aad23ca9f9690f" "/styles.2e152d608221c2ee.css": "9830389a46daa5b4511e0dd343aad23ca9f9690f"
}, },
"navigationUrls": [ "navigationUrls": [

View File

@ -1 +1 @@
(()=>{"use strict";var e,v={},m={};function r(e){var f=m[e];if(void 0!==f)return f.exports;var t=m[e]={exports:{}};return v[e].call(t.exports,t,t.exports,r),t.exports}r.m=v,e=[],r.O=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],c=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[l]))?t.splice(l--,1):(c=!1,o<a&&(a=o));if(c){e.splice(n--,1);var d=i();void 0!==d&&(f=d)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.n=e=>{var f=e&&e.__esModule?()=>e.default:()=>e;return r.d(f,{a:f}),f},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>(592===e?"common":e)+"."+{45:"c90c3cea2bf1a66e",91:"3c224fe84835dadd",103:"5b5d2a6e5a8a7479",146:"5a8902910bda9e87",183:"ee55fc76717674c3",548:"5d742bcea753ec09",592:"858f777e9296e6f2"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="blrec:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==o)for(var l=document.getElementsByTagName("script"),d=0;d<l.length;d++){var u=l[d];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==f+o){a=u;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+o),a.src=r.tu(t)),e[t]=[i];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),_&&_.forEach(h=>h(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tu=f=>(void 0===e&&(e={createScriptURL:t=>t},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(f))})(),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(666!=i){var a=new Promise((u,s)=>n=e[i]=[u,s]);o.push(n[2]=a);var c=r.p+r.u(i),l=new Error;r.l(c,u=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+s+": "+p+")",l.name="ChunkLoadError",l.type=s,l.request=p,n[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var l,d,[n,a,c]=o,u=0;if(n.some(p=>0!==e[p])){for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(c)var s=c(r)}for(i&&i(o);u<n.length;u++)r.o(e,d=n[u])&&e[d]&&e[d][0](),e[n[u]]=0;return r.O(s)},t=self.webpackChunkblrec=self.webpackChunkblrec||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})(); (()=>{"use strict";var e,v={},m={};function r(e){var f=m[e];if(void 0!==f)return f.exports;var t=m[e]={exports:{}};return v[e].call(t.exports,t,t.exports,r),t.exports}r.m=v,e=[],r.O=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],c=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(p=>r.O[p](t[l]))?t.splice(l--,1):(c=!1,o<a&&(a=o));if(c){e.splice(n--,1);var d=i();void 0!==d&&(f=d)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.n=e=>{var f=e&&e.__esModule?()=>e.default:()=>e;return r.d(f,{a:f}),f},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>(592===e?"common":e)+"."+{45:"c90c3cea2bf1a66e",91:"3c224fe84835dadd",103:"5b5d2a6e5a8a7479",146:"5a8902910bda9e87",183:"ee55fc76717674c3",548:"91bbb60199d9e944",592:"858f777e9296e6f2"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="blrec:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,c;if(void 0!==o)for(var l=document.getElementsByTagName("script"),d=0;d<l.length;d++){var u=l[d];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==f+o){a=u;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+o),a.src=r.tu(t)),e[t]=[i];var s=(g,p)=>{a.onerror=a.onload=null,clearTimeout(b);var _=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),_&&_.forEach(h=>h(p)),g)return g(p)},b=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tu=f=>(void 0===e&&(e={createScriptURL:t=>t},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(f))})(),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(666!=i){var a=new Promise((u,s)=>n=e[i]=[u,s]);o.push(n[2]=a);var c=r.p+r.u(i),l=new Error;r.l(c,u=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var s=u&&("load"===u.type?"missing":u.type),b=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+s+": "+b+")",l.name="ChunkLoadError",l.type=s,l.request=b,n[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var l,d,[n,a,c]=o,u=0;if(n.some(b=>0!==e[b])){for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(c)var s=c(r)}for(i&&i(o);u<n.length;u++)r.o(e,d=n[u])&&e[d]&&e[d][0](),e[n[u]]=0;return r.O(s)},t=self.webpackChunkblrec=self.webpackChunkblrec||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();

View File

@ -1,19 +1,18 @@
import os
import logging
from logging import LogRecord, Handler
from logging.handlers import RotatingFileHandler
from datetime import datetime
import asyncio import asyncio
import threading
import atexit import atexit
import logging
import os
import threading
from datetime import datetime
from logging import Handler, LogRecord
from logging.handlers import TimedRotatingFileHandler
from typing import Any, List, Optional from typing import Any, List, Optional
from colorama import init, deinit, Fore, Back, Style from colorama import Back, Fore, Style, deinit, init
from tqdm import tqdm from tqdm import tqdm
from .typing import LOG_LEVEL from .typing import LOG_LEVEL
__all__ = 'configure_logger', 'ConsoleHandler', 'TqdmOutputStream' __all__ = 'configure_logger', 'ConsoleHandler', 'TqdmOutputStream'
@ -57,7 +56,7 @@ def obtain_room_id() -> str:
name = task.get_name() name = task.get_name()
if '::' in name: if '::' in name:
if (room_id := name.split('::')[-1]): if room_id := name.split('::')[-1]:
return room_id return room_id
return '' return ''
@ -66,7 +65,7 @@ def obtain_room_id() -> str:
def record_factory(*args: Any, **kwargs: Any) -> LogRecord: def record_factory(*args: Any, **kwargs: Any) -> LogRecord:
record = _old_factory(*args, **kwargs) record = _old_factory(*args, **kwargs)
if (room_id := obtain_room_id()): if room_id := obtain_room_id():
record.roomid = '[' + room_id + '] ' # type: ignore record.roomid = '[' + room_id + '] ' # type: ignore
else: else:
record.roomid = '' # type: ignore record.roomid = '' # type: ignore
@ -84,7 +83,6 @@ def configure_logger(
log_dir: str, log_dir: str,
*, *,
console_log_level: LOG_LEVEL = 'INFO', console_log_level: LOG_LEVEL = 'INFO',
max_bytes: Optional[int] = None,
backup_count: Optional[int] = None, backup_count: Optional[int] = None,
) -> None: ) -> None:
# config root logger # config root logger
@ -104,10 +102,10 @@ def configure_logger(
# logging to file # logging to file
log_file_path = make_log_file_path(log_dir) log_file_path = make_log_file_path(log_dir)
file_handler = RotatingFileHandler( file_handler = TimedRotatingFileHandler(
log_file_path, filename=log_file_path,
maxBytes=max_bytes or 1024 ** 2 * 10, when='MIDNIGHT',
backupCount=backup_count or 1, backupCount=backup_count or 0,
encoding='utf-8', encoding='utf-8',
) )
file_handler.setLevel(logging.DEBUG) file_handler.setLevel(logging.DEBUG)

View File

@ -326,12 +326,7 @@ def log_dir_factory() -> str:
class LoggingSettings(BaseModel): class LoggingSettings(BaseModel):
log_dir: Annotated[str, Field(default_factory=log_dir_factory)] log_dir: Annotated[str, Field(default_factory=log_dir_factory)]
console_log_level: LOG_LEVEL = 'INFO' console_log_level: LOG_LEVEL = 'INFO'
max_bytes: Annotated[ backup_count: Annotated[int, Field(ge=0, le=90)] = 30
int, Field(ge=1024**2, le=1024**2 * 10, multiple_of=1024**2)
] = (
1024**2 * 10
) # allowed 1 ~ 10 MB
backup_count: Annotated[int, Field(ge=1, le=30)] = 30
@validator('log_dir') @validator('log_dir')
def _validate_dir(cls, path: str) -> str: def _validate_dir(cls, path: str) -> str:

View File

@ -265,7 +265,6 @@ class SettingsManager:
configure_logger( configure_logger(
log_dir=self._settings.logging.log_dir, log_dir=self._settings.logging.log_dir,
console_log_level=self._settings.logging.console_log_level, console_log_level=self._settings.logging.console_log_level,
max_bytes=self._settings.logging.max_bytes,
backup_count=self._settings.logging.backup_count, backup_count=self._settings.logging.backup_count,
) )

View File

@ -36,19 +36,6 @@
</nz-select> </nz-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item class="setting-item">
<nz-form-label class="setting-label" nzNoColon
>日志文件分割大小</nz-form-label
>
<nz-form-control
class="setting-control select"
[nzWarningTip]="syncFailedWarningTip"
[nzValidateStatus]="syncStatus.maxBytes ? maxBytesControl : 'warning'"
>
<nz-select formControlName="maxBytes" [nzOptions]="maxBytesOptions">
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item class="setting-item"> <nz-form-item class="setting-item">
<nz-form-label class="setting-label" nzNoColon <nz-form-label class="setting-label" nzNoColon
>日志文件备份数量</nz-form-label >日志文件备份数量</nz-form-label

View File

@ -42,12 +42,7 @@ export class LoggingSettingsComponent implements OnInit, OnChanges {
{ label: 'CRITICAL', value: 'CRITICAL' }, { label: 'CRITICAL', value: 'CRITICAL' },
]; ];
readonly maxBytesOptions = range(1, 11).map((i) => ({ readonly backupOptions = range(0, 91).map((i) => ({
label: `${i} MB`,
value: 1024 ** 2 * i,
}));
readonly backupOptions = range(1, 31).map((i) => ({
label: i.toString(), label: i.toString(),
value: i, value: i,
})); }));
@ -60,7 +55,6 @@ export class LoggingSettingsComponent implements OnInit, OnChanges {
this.settingsForm = formBuilder.group({ this.settingsForm = formBuilder.group({
logDir: [''], logDir: [''],
consoleLogLevel: [''], consoleLogLevel: [''],
maxBytes: [''],
backupCount: [''], backupCount: [''],
}); });
} }
@ -73,10 +67,6 @@ export class LoggingSettingsComponent implements OnInit, OnChanges {
return this.settingsForm.get('consoleLogLevel') as FormControl; return this.settingsForm.get('consoleLogLevel') as FormControl;
} }
get maxBytesControl() {
return this.settingsForm.get('maxBytes') as FormControl;
}
get backupCountControl() { get backupCountControl() {
return this.settingsForm.get('backupCount') as FormControl; return this.settingsForm.get('backupCount') as FormControl;
} }

View File

@ -113,7 +113,6 @@ export type LogLevel =
export interface LoggingSettings { export interface LoggingSettings {
logDir: string; logDir: string;
consoleLogLevel: LogLevel; consoleLogLevel: LogLevel;
maxBytes: number;
backupCount: number; backupCount: number;
} }