Skip to content

Commit

Permalink
feat: replacing electron-log with custom logger
Browse files Browse the repository at this point in the history
  • Loading branch information
KatoakDR committed Jan 6, 2025
1 parent 81a6395 commit a31d8c3
Show file tree
Hide file tree
Showing 25 changed files with 955 additions and 116 deletions.
4 changes: 2 additions & 2 deletions electron/common/logger/create-logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
Logger as ElectronLogger,
} from 'electron-log';
import { initializeLogging } from './initialize-logging.js';
import type { LogFunction, Logger } from './types.js';
import type { LogLevelFunction, Logger } from './types.js';

// Cache loggers for the same scope.
const scopedLoggers: Record<string, ElectronLogFunctions> = {};
Expand All @@ -15,7 +15,7 @@ interface ElectronLogFunctionsExtended extends ElectronLogFunctions {
/**
* Alternative to electron logger's 'silly' level.
*/
trace: LogFunction;
trace: LogLevelFunction;
}

export const createLogger = (options: {
Expand Down
55 changes: 0 additions & 55 deletions electron/common/logger/format-log-data.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,4 @@ describe('format-log-data', () => {
},
});
});

it('masks sensitive values', () => {
const data = {
password: 'secret',
apiKey: 'secret',
};

const result = formatLogData(data);

expect(result).toEqual({
password: '***REDACTED***',
apiKey: '***REDACTED***',
});
});
});
157 changes: 157 additions & 0 deletions electron/common/logger/format/__tests__/json-log-formatter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { beforeEach, describe, expect, it } from 'vitest';
import type { LogFormatter, LogMessage } from '../../types.js';
import { LogLevel } from '../../types.js';
import { jsonLogFormatter } from '../json-log-formatter.js';

describe('json-log-formatter', () => {
const logDate = new Date('2022-01-02T00:00:00Z');

let formatter: LogFormatter;

beforeEach(() => {
formatter = jsonLogFormatter({ colors: false });
});

it('formats log message', () => {
const message: LogMessage = {
level: LogLevel.INFO,
scope: 'test',
message: 'hello world',
timestamp: logDate,
};

const result = formatter([message]);

expect(result).toEqual(
`{ level: 'info', scope: 'test', message: 'hello world', timestamp: ${logDate.toISOString()} }\n`
);
});

it('formats log message with custom properties', () => {
const message: LogMessage = {
level: LogLevel.INFO,
scope: 'test',
message: 'hello world',
timestamp: logDate,
// Custom properties
foo: 'bar',
};

const result = formatter([message]);

expect(result).toEqual(
`{ level: 'info', scope: 'test', message: 'hello world', timestamp: ${logDate.toISOString()}, foo: 'bar' }\n`
);
});

it('formats log message with complex properties', () => {
const message: LogMessage = {
level: LogLevel.INFO,
scope: 'test',
message: 'hello world',
timestamp: logDate,
// Custom properties
boolean: false,
number: 42,
array: [1, 2, 3],
date: logDate,
set: new Set(['A', 'B', 'C']),
map: new Map<string, any>([
['A', 1],
['B', logDate],
['C', { foo: 'bar' }],
]),
};

const result = formatter([message]);

expect(result).toEqual(
`{ level: 'info', scope: 'test', message: 'hello world', timestamp: ${logDate.toISOString()}, boolean: false, number: 42, array: [ 1, 2, 3 ], date: ${logDate.toISOString()}, set: [ 'A', 'B', 'C' ], map: { A: 1, B: '${logDate.toISOString()}', C: { foo: 'bar' } } }\n`
);
});

it('formats log message with sensitive properties', () => {
const message: LogMessage = {
level: LogLevel.INFO,
scope: 'test',
message: 'hello world',
timestamp: logDate,
// Custom properties
password: 'secret',
accessToken: 'secret',
apiKey: 'secret',
};

const result = formatter([message]);

expect(result).toEqual(
`{ level: 'info', scope: 'test', message: 'hello world', timestamp: ${logDate.toISOString()}, password: '***REDACTED***', accessToken: '***REDACTED***', apiKey: '***REDACTED***' }\n`
);
});

it('formats log messages with colors', () => {
formatter = jsonLogFormatter({ colors: true });

const messages: Array<LogMessage> = [
{
level: LogLevel.ERROR,
scope: 'test',
message: 'hello world',
timestamp: logDate,
},
{
level: LogLevel.WARN,
scope: 'test',
message: 'hello world',
timestamp: logDate,
},
{
level: LogLevel.INFO,
scope: 'test',
message: 'hello world',
timestamp: logDate,
},
{
level: LogLevel.DEBUG,
scope: 'test',
message: 'hello world',
timestamp: logDate,
},
{
level: LogLevel.TRACE,
scope: 'test',
message: 'hello world',
timestamp: logDate,
},
];

const result = formatter(messages);
const lines = result.trim().split('\n');

expect(lines).toHaveLength(messages.length);

// Note, the json formatter colorizes the values based on data type.
// The log levels are strings and so all have the same color.
// This behavior differs from the pretty formatter.

expect(lines[0]).toEqual(
`{ level: \u001b[32m'error'\u001b[39m, scope: \u001b[32m'test'\u001b[39m, message: \u001b[32m'hello world'\u001b[39m, timestamp: \u001b[35m2022-01-02T00:00:00.000Z\u001b[39m }`
);

expect(lines[1]).toEqual(
`{ level: \u001b[32m'warn'\u001b[39m, scope: \u001b[32m'test'\u001b[39m, message: \u001b[32m'hello world'\u001b[39m, timestamp: \u001b[35m2022-01-02T00:00:00.000Z\u001b[39m }`
);

expect(lines[2]).toEqual(
`{ level: \u001b[32m'info'\u001b[39m, scope: \u001b[32m'test'\u001b[39m, message: \u001b[32m'hello world'\u001b[39m, timestamp: \u001b[35m2022-01-02T00:00:00.000Z\u001b[39m }`
);

expect(lines[3]).toEqual(
`{ level: \u001b[32m'debug'\u001b[39m, scope: \u001b[32m'test'\u001b[39m, message: \u001b[32m'hello world'\u001b[39m, timestamp: \u001b[35m2022-01-02T00:00:00.000Z\u001b[39m }`
);

expect(lines[4]).toEqual(
`{ level: \u001b[32m'trace'\u001b[39m, scope: \u001b[32m'test'\u001b[39m, message: \u001b[32m'hello world'\u001b[39m, timestamp: \u001b[35m2022-01-02T00:00:00.000Z\u001b[39m }`
);
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
import { describe, expect, it } from 'vitest';
import { isNotMaskable, maskSensitiveValues } from '../mask-log-data.js';
import {
isNotMaskable,
maskLogData,
maskSensitiveValues,
} from '../mask-log-data.js';

describe('mask-log-data', () => {
describe('#maskLogData', () => {
const data: Record<string, any> = {
accessToken: 'accessToken1',
password: 'password1',
apiKey: 'apiKey1',
credential: 'credential1',
nested: {
accessToken: 'accessToken2',
password: 'password2',
apiKey: 'apiKey2',
credential: 'credential2',
},
};

it('masks password, accessToken, and apiKey properties by default', () => {
const result = maskLogData(data);

expect(result).toEqual({
accessToken: '***REDACTED***',
password: '***REDACTED***',
apiKey: '***REDACTED***',
credential: 'credential1',
nested: {
accessToken: '***REDACTED***',
password: '***REDACTED***',
apiKey: '***REDACTED***',
credential: 'credential2',
},
});
});
});

describe('#maskSensitiveValues', () => {
const data: Record<string, any> = {
accessToken: 'accessToken1',
Expand All @@ -18,7 +54,7 @@ describe('mask-log-data', () => {

it('masks password, accessToken, and apiKey properties by default', () => {
const result = maskSensitiveValues({
json: data,
object: data,
});

expect(result).toEqual({
Expand All @@ -37,7 +73,7 @@ describe('mask-log-data', () => {

it('masks specified properties', () => {
const result = maskSensitiveValues({
json: data,
object: data,
keys: ['apiKey', 'credential'],
});

Expand All @@ -57,7 +93,7 @@ describe('mask-log-data', () => {

it('masks specified properties with custom mask', () => {
const result = maskSensitiveValues({
json: data,
object: data,
keys: ['apiKey', 'credential'],
mask: '***MASKED***',
});
Expand Down
Loading

0 comments on commit a31d8c3

Please sign in to comment.