Skip to content

adding traceId and a more standardized format #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ instance.interceptors.request.use((request) => {
| `prefixText` | string \| `false` | `'Axios'` | `false` => no prefix, otherwise, customize the prefix wanted. |
| `dateFormat` | [dateformat](https://github.com/felixge/node-dateformat) \| `false` | `false` | `false` => no timestamp, otherwise, customize its format |
| `logger` | function<string, any> | `console.log` | Allows users to customize the logger function to be used. e.g. Winston's `logger.info` could be leveraged, like this: `logger.info.bind(this)` |
| `traceId` | string \| `false` | `false` | Allows users to add a string to be used as a traceable id between request/response (or a sequence of them). |

## CONTRIBUTE

Expand Down
3 changes: 3 additions & 0 deletions src/common/__test__/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ test('Default globalConfig properties should be equal to default values', () =>
dateFormat: false,
prefixText: DEFAULT_PREFIX,
headers: false,
traceId: false,
});
});

Expand All @@ -37,6 +38,7 @@ test('setGlobalConfig should set config. getGlobalConfig should return globalCon
dateFormat: false,
prefixText: DEFAULT_PREFIX,
headers: false,
traceId: false,
});
});

Expand Down Expand Up @@ -64,5 +66,6 @@ test('assembleBuildConfig should return merged with globalConfig object.', () =>
dateFormat: 'hh:mm:ss',
prefixText: DEFAULT_PREFIX,
headers: false,
traceId: false,
});
});
14 changes: 14 additions & 0 deletions src/common/__test__/string-builder.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import StringBuilder from '../string-builder';
import { getGlobalConfig } from '../config';
import chalk from 'chalk';

test('makeLogTypeWithPrefix should add prefix text', () => {
const sb = new StringBuilder(getGlobalConfig());
Expand Down Expand Up @@ -85,3 +86,16 @@ test('makeData should not stringify data if configured not to', () => {
const result = sb.makeData(a).build();
expect(result).toEqual('');
});

test('makeTraceId should add a string if configured', () => {
const testId = '1324567890987654321';
const config = {
...getGlobalConfig(),
traceId: testId,
};

const sb = new StringBuilder(config);
const result = sb.makeTraceId().build();

expect(result).toContain(`[${chalk.blue(testId)}]`);
});
1 change: 1 addition & 0 deletions src/common/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ let globalConfig: Required<GlobalLogConfig> = {
prefixText: 'Axios',
dateFormat: false,
headers: false,
traceId: false,
};

function getGlobalConfig() {
Expand Down
19 changes: 16 additions & 3 deletions src/common/string-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import chalk from 'chalk';

class StringBuilder {
private config: GlobalLogConfig;
private lineHeader: Array<string>;
private printQueue: Array<string>;
private filteredHeaderList: Array<String>;

constructor(config: GlobalLogConfig) {
this.config = config;
this.lineHeader = [];
this.printQueue = [];
this.filteredHeaderList = ['common', 'delete', 'get', 'head', 'post', 'put', 'patch', 'content-type', 'content-length', 'vary', 'date', 'connection', 'content-security-policy'];
}

makeLogTypeWithPrefix(logType: string) {
const prefix = this.config.prefixText === false ? `[${logType}]` : `[${this.config.prefixText || 'Axios'}][${logType}]`;
this.printQueue.push(chalk.green(prefix));
this.lineHeader.push(chalk.green(prefix));
return this;
}

Expand All @@ -24,7 +26,14 @@ class StringBuilder {
if (this.config.dateFormat !== false) {
// @ts-ignore
const dateFormat = dateformat(date, this.config.dateFormat || 'isoDateTime');
this.printQueue.push(dateFormat);
this.lineHeader.push(`[${dateFormat}]`);
}
return this;
}

makeTraceId() {
if (this.config.traceId !== false) {
this.lineHeader.push(`[${chalk.blue(this.config.traceId)}]`);
}
return this;
}
Expand Down Expand Up @@ -76,8 +85,12 @@ class StringBuilder {
return this;
}

buildLineHeader() {
return this.lineHeader.join('');
}

build() {
return this.printQueue.join(' ');
return this.buildLineHeader() ? `${this.buildLineHeader()} ` + this.printQueue.join(' ') : this.printQueue.join(' ');
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ export interface GlobalLogConfig extends CommonConfig {
url?: boolean,
status?: boolean,
statusText?: boolean,
traceId?: string | boolean,
}

export interface RequestLogConfig extends CommonConfig {
data?: boolean,
method?: boolean,
url?: boolean,
traceId?: string | boolean,
}

export interface ResponseLogConfig extends CommonConfig {
data?: boolean,
status?: boolean,
statusText?: boolean,
traceId?: string | boolean,
}

export interface ErrorLogConfig extends CommonConfig {
Expand Down
30 changes: 30 additions & 0 deletions src/logger/__test__/request.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { requestLogger, setGlobalConfig } from '../../index';
import chalk from 'chalk';

const printLog = jest.fn(() => {});

Expand Down Expand Up @@ -91,3 +92,32 @@ test('if baseUrl is taken into consideration', () => {
expect(printLog).toHaveBeenCalled();
expect(printLog).toBeCalledWith(expect.stringContaining(axiosRequestConfig.url));
});

test('test a full request', () => {
const globalConfig = {
prefixText: 'TEST',
dateFormat: 'dd-mm-yyyy HH:MM:ss.l',
status: true,
method: true,
headers: true,
data: true,
traceId: '1324567890987654321',
};

setGlobalConfig(globalConfig);
requestLogger({ ...axiosRequestConfig, baseURL: 'https://github.com/', url: '/hg-pyun' });
expect(printLog).toHaveBeenCalled();
expect(printLog).toBeCalledWith(expect.stringContaining('[TEST]'));
expect(printLog).toBeCalledWith(expect.stringContaining('[Request]'));
expect(printLog).toBeCalledWith(expect.stringContaining(`[${chalk.blue('1324567890987654321')}]`));
expect(printLog).toBeCalledWith(
expect.stringMatching(
new RegExp(
/\[[01]?\d-(([0-2]?\d)|([3][01]))-((199\d)|([2-9]\d{3})) ([0-1]\d|[2][0-3]):([0-5]\d):([0-5]\d).(\d{0,3})\]/
)
)
);
expect(printLog).toBeCalledWith(expect.stringContaining(axiosRequestConfig.method));
expect(printLog).toBeCalledWith(expect.stringContaining(axiosRequestConfig.url));
expect(printLog).toBeCalledWith(expect.stringContaining(JSON.stringify(axiosRequestConfig.data)));
});
38 changes: 38 additions & 0 deletions src/logger/__test__/response.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { responseLogger, setGlobalConfig } from '../../index';
import chalk from 'chalk';

const printLog = jest.fn(() => {});

Expand Down Expand Up @@ -104,3 +105,40 @@ test('if baseUrl is taken into consideration', () => {
expect(printLog).toHaveBeenCalled();
expect(printLog).toBeCalledWith(expect.stringContaining(axiosResponse.config.url));
});

test('test a full response', () => {
const globalConfig = {
prefixText: 'TEST',
dateFormat: 'dd-mm-yyyy HH:MM:ss.l',
status: true,
method: true,
headers: true,
data: true,
traceId: '1324567890987654321',
};

const {
status,
statusText,
data,
config: { url, method },
} = axiosResponse;

setGlobalConfig(globalConfig);
responseLogger(axiosResponse);
expect(printLog).toHaveBeenCalled();
expect(printLog).toBeCalledWith(expect.stringContaining('[TEST]'));
expect(printLog).toBeCalledWith(expect.stringContaining('[Response]'));
expect(printLog).toBeCalledWith(expect.stringContaining(`[${chalk.blue('1324567890987654321')}]`));
expect(printLog).toBeCalledWith(
expect.stringMatching(
new RegExp(
/\[[01]?\d-(([0-2]?\d)|([3][01]))-((199\d)|([2-9]\d{3})) ([0-1]\d|[2][0-3]):([0-5]\d):([0-5]\d).(\d{0,3})\]/
)
)
);
expect(printLog).toBeCalledWith(expect.stringContaining(method));
expect(printLog).toBeCalledWith(expect.stringContaining(url));
expect(printLog).toBeCalledWith(expect.stringContaining(`${status}:${statusText}`));
expect(printLog).toBeCalledWith(expect.stringContaining(data));
});
1 change: 1 addition & 0 deletions src/logger/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function errorLoggerWithoutPromise(error: AxiosError, config: ErrorLogConfig = {
const log = stringBuilder
.makeLogTypeWithPrefix('Error')
.makeDateFormat(new Date())
.makeTraceId()
.makeMethod(method)
.makeUrl(url, baseURL)
.makeParams(params)
Expand Down
1 change: 1 addition & 0 deletions src/logger/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function requestLogger(request: AxiosRequestConfig, config: RequestLogConfig = {
const log = stringBuilder
.makeLogTypeWithPrefix('Request')
.makeDateFormat(new Date())
.makeTraceId()
.makeMethod(method)
.makeUrl(url, baseURL)
.makeParams(params)
Expand Down
1 change: 1 addition & 0 deletions src/logger/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function responseLogger(response: AxiosResponse, config: ResponseLogConfig = {})
const log = stringBuilder
.makeLogTypeWithPrefix('Response')
.makeDateFormat(new Date())
.makeTraceId()
.makeMethod(method)
.makeUrl(url, baseURL)
.makeParams(params)
Expand Down