log.ts 3.31 KB
Newer Older
liuzhe-lz's avatar
liuzhe-lz committed
1
2
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
Deshui Yu's avatar
Deshui Yu committed
3
4
5
6
7

'use strict';

import * as fs from 'fs';
import { Writable } from 'stream';
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

/* log level constants */

export const DEBUG = 10;
export const INFO = 20;
export const WARNING = 30;
export const ERROR = 40;
export const CRITICAL = 50;

export const TRACE = 1;
export const FATAL = 50;

const levelNames = new Map<number, string>([
    [CRITICAL, 'CRITICAL'],
    [ERROR, 'ERROR'],
    [WARNING, 'WARNING'],
    [INFO, 'INFO'],
    [DEBUG, 'DEBUG'],
    [TRACE, 'TRACE'],
27
]);
Deshui Yu's avatar
Deshui Yu committed
28

29
/* global_ states */
Deshui Yu's avatar
Deshui Yu committed
30

31
32
33
let logFile: Writable | null = null;
let logLevel: number = 0;
const loggers = new Map<string, Logger>();
Deshui Yu's avatar
Deshui Yu committed
34

35
/* major api */
Deshui Yu's avatar
Deshui Yu committed
36

37
38
39
40
41
export class Logger {
    private name: string;

    constructor(name: string = 'root') {
        this.name = name;
Deshui Yu's avatar
Deshui Yu committed
42
43
    }

44
45
46
    public trace(...args: any[]): void {
        this.log(TRACE, args);
    }
47

48
49
50
    public debug(...args: any[]): void {
        this.log(DEBUG, args);
    }
SparkSnail's avatar
SparkSnail committed
51

52
53
    public info(...args: any[]): void {
        this.log(INFO, args);
54
55
    }

56
57
    public warning(...args: any[]): void {
        this.log(WARNING, args);
Deshui Yu's avatar
Deshui Yu committed
58
59
    }

60
61
    public error(...args: any[]): void {
        this.log(ERROR, args);
62
63
    }

64
65
    public critical(...args: any[]): void {
        this.log(CRITICAL, args);
Deshui Yu's avatar
Deshui Yu committed
66
67
    }

68
69
    public fatal(...args: any[]): void {
        this.log(FATAL, args);
Deshui Yu's avatar
Deshui Yu committed
70
71
    }

72
73
74
    private log(level: number, args: any[]): void {
        if (level < logLevel || logFile === null) {
            return;
Deshui Yu's avatar
Deshui Yu committed
75
76
        }

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
        // `time.toLocaleString('sv')` trick does not work for Windows
        const isoTime = new Date(new Date().toLocaleString() + ' UTC').toISOString();
        const time = isoTime.slice(0, 10) + ' ' + isoTime.slice(11, 19);

        const levelName = levelNames.has(level) ? levelNames.get(level) : level.toString();

        const words = [];
        for (const arg of args) {
            if (arg === undefined) {
                words.push('undefined');
            } else if (arg === null) {
                words.push('null');
            } else if (typeof arg === 'object') {
                const json = JSON.stringify(arg);
                words.push(json === undefined ? arg : json);
            } else {
                words.push(arg);
            }
Deshui Yu's avatar
Deshui Yu committed
95
        }
96
97
98
99
        const message = words.join(' ');
        
        const record = `[${time}] ${levelName} (${this.name}) ${message}\n`;
        logFile.write(record);
Deshui Yu's avatar
Deshui Yu committed
100
    }
101
}
Deshui Yu's avatar
Deshui Yu committed
102

103
104
105
106
107
export function getLogger(name: string = 'root'): Logger {
    let logger = loggers.get(name);
    if (logger === undefined) {
        logger = new Logger(name);
        loggers.set(name, logger);
Deshui Yu's avatar
Deshui Yu committed
108
    }
109
110
111
112
113
114
115
116
117
118
119
120
121
    return logger;
}

/* management functions */

export function setLogLevel(levelName: string): void {
    if (levelName) {
        const level = module.exports[levelName.toUpperCase()];
        if (typeof level === 'number') {
            logLevel = level;
        } else {
            console.log('[ERROR] Bad log level:', levelName);
            getLogger('logging').error('Bad log level:', levelName);
SparkSnail's avatar
SparkSnail committed
122
        }
Deshui Yu's avatar
Deshui Yu committed
123
124
125
    }
}

126
127
128
129
130
131
export function startLogging(logPath: string): void {
    logFile = fs.createWriteStream(logPath, {
        flags: 'a+',
        encoding: 'utf8',
        autoClose: true
    });
Deshui Yu's avatar
Deshui Yu committed
132
133
}

134
135
136
137
138
139
export function stopLogging(): void {
    if (logFile !== null) {
        logFile.end();
        logFile = null;
    }
}