Skip to content

Commit bfd79d6

Browse files
Provide log line and stack trace on runtime worker errors. (#17)
1 parent dcf33de commit bfd79d6

File tree

11 files changed

+79
-42
lines changed

11 files changed

+79
-42
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Release Notes
44

5+
### v1.1.4
6+
7+
- Provide log line and stack trace on runtime worker errors.
8+
59
### v1.1.3
610

711
- Exported `axios` and `axiosClient` with exponential backoff retry mechanism for HTTP requests and omitting Authorization headers from Axios errors.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devrev/ts-adaas",
3-
"version": "1.1.3",
3+
"version": "1.1.4",
44
"description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
55
"type": "commonjs",
66
"main": "./dist/index.js",

src/common/control-protocol.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
LoaderEvent,
88
} from '../types/extraction';
99
import { LoaderEventType } from '../types/loading';
10-
import { formatAxiosError } from '../logger/logger';
10+
import { serializeAxiosError } from '../logger/logger';
1111

1212
export interface EmitInterface {
1313
event: AirdropEvent;
@@ -49,7 +49,7 @@ export const emit = async ({
4949
if (axios.isAxiosError(error)) {
5050
console.error(
5151
`Failed to emit event with event type ${eventType}.`,
52-
formatAxiosError(error)
52+
serializeAxiosError(error)
5353
);
5454
} else {
5555
// TODO: Stop it through UI or think about retrying this request. Implement exponential retry mechanism.

src/common/install-initial-domain-mapping.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { axios, axiosClient } from '../http/axios-client';
22
import { FunctionInput } from '@devrev/typescript-sdk/dist/snap-ins';
33

44
import { InitialDomainMapping } from '../types/common';
5-
import { formatAxiosError } from '../logger/logger';
5+
import { serializeAxiosError } from '../logger/logger';
66

77
export async function installInitialDomainMapping(
88
event: FunctionInput,
@@ -71,7 +71,7 @@ export async function installInitialDomainMapping(
7171
if (axios.isAxiosError(error)) {
7272
console.error(
7373
'Error while creating recipe blueprint',
74-
formatAxiosError(error)
74+
serializeAxiosError(error)
7575
);
7676
} else {
7777
console.error('Error while creating recipe blueprint', error);
@@ -109,7 +109,7 @@ export async function installInitialDomainMapping(
109109
if (axios.isAxiosError(error)) {
110110
console.error(
111111
'Error while installing initial domain mapping',
112-
formatAxiosError(error)
112+
serializeAxiosError(error)
113113
);
114114
} else {
115115
console.error('Error while installing initial domain mapping', error);
@@ -118,7 +118,7 @@ export async function installInitialDomainMapping(
118118
}
119119
} catch (error) {
120120
if (axios.isAxiosError(error)) {
121-
console.error('Error while fetching snap in', formatAxiosError(error));
121+
console.error('Error while fetching snap in', serializeAxiosError(error));
122122
} else {
123123
console.error('Error while fetching snap in', error);
124124
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export { spawn } from './workers/spawn';
1414
export * from './types/workers';
1515

1616
export { formatAxiosError } from './logger/logger';
17+
export { serializeAxiosError } from './logger/logger';

src/logger/logger.test.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AxiosError } from 'axios';
2-
import { getPrintableState, formatAxiosError } from './logger';
2+
import { getPrintableState, serializeAxiosError } from './logger';
33

44
it('getPrintableState should return printable state', () => {
55
const state = {
@@ -33,7 +33,7 @@ it('getPrintableState should return printable state', () => {
3333
});
3434
});
3535

36-
it('formatAxiosError should return formatted error', () => {
36+
it('serializeAxiosError should return formatted error', () => {
3737
const error = {
3838
response: {
3939
status: 500,
@@ -44,14 +44,21 @@ it('formatAxiosError should return formatted error', () => {
4444
},
4545
} as AxiosError;
4646

47-
const formattedError = formatAxiosError(error);
47+
const formattedError = serializeAxiosError(error);
4848

4949
expect(formattedError).toEqual({
50-
status: 500,
51-
data: 'Internal server error',
52-
method: 'GET',
53-
baseURL: undefined,
54-
url: undefined,
55-
payload: undefined,
50+
config: {
51+
method: 'GET',
52+
params: undefined,
53+
url: undefined,
54+
},
55+
isAxiosError: true,
56+
isCorsOrNoNetworkError: false,
57+
response: {
58+
data: 'Internal server error',
59+
headers: undefined,
60+
status: 500,
61+
statusText: undefined,
62+
},
5663
});
5764
});

src/logger/logger.ts

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from './logger.interfaces';
1010
import { isMainThread, parentPort } from 'node:worker_threads';
1111
import { WorkerAdapterOptions, WorkerMessageSubject } from '../types/workers';
12-
import { AxiosError } from 'axios';
12+
import { AxiosError, RawAxiosResponseHeaders } from 'axios';
1313
import { getCircularReplacer } from '../common/helpers';
1414

1515
export class Logger extends Console {
@@ -93,18 +93,43 @@ export function getPrintableState(state: Record<string, any>): PrintableState {
9393
// Process the state object directly since it's guaranteed to be an object
9494
return processValue(state) as PrintableState;
9595
}
96-
96+
/**
97+
* @deprecated
98+
*/
9799
export function formatAxiosError(error: AxiosError): object {
98-
if (error.response) {
99-
return {
100-
status: error.response.status,
101-
data: error.response.data,
102-
method: error.config?.method,
103-
baseURL: error.config?.baseURL,
104-
url: error.config?.url,
105-
payload: error.config?.data,
106-
};
100+
return serializeAxiosError(error);
101+
}
102+
103+
export const serializeError = (error: unknown): Error => {
104+
let serializedError = error;
105+
try {
106+
serializedError = JSON.parse(
107+
JSON.stringify(error, Object.getOwnPropertyNames(error))
108+
);
109+
} catch (err) {
110+
console.error('Failed to serialize error object for logger', err);
107111
}
112+
return serializedError as Error;
113+
};
108114

109-
return error;
115+
export function serializeAxiosError(error: AxiosError) {
116+
const response = error.response
117+
? {
118+
data: error.response.data,
119+
headers: error.response.headers as RawAxiosResponseHeaders,
120+
status: error.response.status,
121+
statusText: error.response.statusText,
122+
}
123+
: null;
124+
const config = {
125+
method: error.config?.method,
126+
params: error.config?.params,
127+
url: error.config?.url,
128+
};
129+
return {
130+
config,
131+
isAxiosError: true,
132+
isCorsOrNoNetworkError: !error.response,
133+
response,
134+
};
110135
}

src/state/state.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { axios, axiosClient } from '../http/axios-client';
22

33
import { AirdropEvent, SyncMode } from '../types/extraction';
44
import { STATELESS_EVENT_TYPES } from '../common/constants';
5-
import { formatAxiosError, getPrintableState } from '../logger/logger';
5+
import { serializeAxiosError, getPrintableState } from '../logger/logger';
66
import { ErrorRecord } from '../types/common';
77

88
import { AdapterState, SdkState, StateInterface } from './state.interfaces';
@@ -101,7 +101,7 @@ export class State<ConnectorState> {
101101
);
102102
} catch (error) {
103103
if (axios.isAxiosError(error)) {
104-
console.error('Failed to update state.', formatAxiosError(error));
104+
console.error('Failed to update state.', serializeAxiosError(error));
105105
} else {
106106
console.error('Failed to update state.', error);
107107
}

src/uploader/uploader.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
StreamAttachmentsResponse,
1919
UploaderFactoryInterface,
2020
} from './uploader.interfaces';
21-
import { formatAxiosError } from '../logger/logger';
21+
import { serializeAxiosError } from '../logger/logger';
2222

2323
export class Uploader {
2424
private event: AirdropEvent;
@@ -106,7 +106,7 @@ export class Uploader {
106106
if (axios.isAxiosError(error)) {
107107
console.error(
108108
'Error while preparing artifact.',
109-
formatAxiosError(error)
109+
serializeAxiosError(error)
110110
);
111111
} else {
112112
console.error('Error while preparing artifact.', error);
@@ -137,7 +137,7 @@ export class Uploader {
137137
if (axios.isAxiosError(error)) {
138138
console.error(
139139
'Error while uploading artifact.',
140-
formatAxiosError(error)
140+
serializeAxiosError(error)
141141
);
142142
} else {
143143
console.error('Error while uploading artifact.', error);
@@ -171,7 +171,7 @@ export class Uploader {
171171
if (axios.isAxiosError(error)) {
172172
console.error(
173173
'Error while streaming artifact.',
174-
formatAxiosError(error)
174+
serializeAxiosError(error)
175175
);
176176
} else {
177177
console.error('Error while streaming artifact.', error);
@@ -278,7 +278,7 @@ export class Uploader {
278278
if (axios.isAxiosError(error)) {
279279
console.error(
280280
'Error while downloading artifact from URL.',
281-
formatAxiosError(error)
281+
serializeAxiosError(error)
282282
);
283283
} else {
284284
console.error('Error while downloading artifact from URL.', error);
@@ -386,7 +386,7 @@ export class Uploader {
386386
if (axios.isAxiosError(error)) {
387387
console.error(
388388
'Error while fetching attachment from URL.',
389-
formatAxiosError(error)
389+
serializeAxiosError(error)
390390
);
391391
} else {
392392
console.error('Error while fetching attachment from URL.', error);

src/workers/create-worker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isMainThread, Worker } from 'node:worker_threads';
22

33
import { WorkerData, WorkerEvent } from '../types/workers';
4-
import { Logger } from '../logger/logger';
4+
import { Logger, serializeError } from '../logger/logger';
55

66
async function createWorker<ConnectorState>(
77
workerData: WorkerData<ConnectorState>
@@ -19,7 +19,7 @@ async function createWorker<ConnectorState>(
1919
} as WorkerOptions);
2020

2121
worker.on(WorkerEvent.WorkerError, (error) => {
22-
logger.error('Worker error', error);
22+
logger.error('Worker error', serializeError(error));
2323
reject();
2424
});
2525
worker.on(WorkerEvent.WorkerOnline, () => {

0 commit comments

Comments
 (0)