@htdangkhoa/google-ads
Version:
Google Ads API client for Node.js
165 lines (164 loc) • 8.17 kB
JavaScript
import { InterceptingCall, RequesterBuilder, Metadata, ListenerBuilder, status, } from '@grpc/grpc-js';
import log4js from 'log4js';
import { HOST } from './constants.js';
import { getGoogleAdsError } from './utils.js';
const cleanEmpty = function (obj, defaults = [undefined, null]) {
if (defaults.includes(obj))
return;
if (Array.isArray(obj))
return obj
.map((v) => (v && typeof v === 'object' ? cleanEmpty(v, defaults) : v))
.filter((v) => !defaults.includes(v));
return Object.entries(obj).length
? Object.entries(obj)
.map(([k, v]) => [
k,
v && typeof v === 'object' ? cleanEmpty(v, defaults) : v,
])
.reduce((a, [k, v]) => (defaults.includes(v) ? a : Object.assign(Object.assign({}, a), { [k]: v })), {})
: obj;
};
export class LoggingInterceptor {
constructor(requestLogging) {
this.requestLogging = requestLogging;
this.messages = [];
this.requestLogging = requestLogging;
log4js.configure({
appenders: {
out: { type: 'stdout', layout: { type: 'basic' } },
},
categories: {
default: { appenders: ['out'], level: 'trace' },
},
});
this.summaryLogger = log4js.getLogger('Google::Ads::GoogleAds::Summary');
this.detailLogger = log4js.getLogger('Google::Ads::GoogleAds::Detail');
this.requester = new RequesterBuilder()
.withSendMessage((message, next) => {
this.request = message;
return next(message);
})
.withStart((headers, _listener, next) => {
this.requestHeaders = headers;
const listener = new ListenerBuilder()
.withOnReceiveMetadata((metadata, next) => {
this.responseHeaders = metadata;
next(metadata);
})
.withOnReceiveStatus((status, next) => {
this.responseStatus = status;
next(status);
})
.build();
return next(headers, listener);
})
.build();
}
callInvocationTransformer(properties, originalCallInvocationTransformer) {
let props = properties;
if (typeof originalCallInvocationTransformer === 'function') {
props = originalCallInvocationTransformer === null || originalCallInvocationTransformer === void 0 ? void 0 : originalCallInvocationTransformer(props);
}
const originalCallback = props.callback;
// clear messages from previous call
this.messages.length = 0;
props.callback = (error, value) => {
this.callback(error, value);
if (typeof originalCallback === 'function') {
originalCallback(error, value);
}
};
return props;
}
interceptCall(options, nextCall) {
this.interceptorOptions = options;
return new InterceptingCall(nextCall(options), this.requester);
}
callback(err, value) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
const isSuccess = !err && ((_a = this.responseStatus) === null || _a === void 0 ? void 0 : _a.code) === status.OK.valueOf();
const methodName = (_c = (_b = this.interceptorOptions) === null || _b === void 0 ? void 0 : _b.method_definition.path) !== null && _c !== void 0 ? _c : '';
const requestHeaders = (_d = this.requestHeaders) !== null && _d !== void 0 ? _d : new Metadata();
const request = (_e = this.request) !== null && _e !== void 0 ? _e : {};
const responseHeaders = (_f = this.responseHeaders) !== null && _f !== void 0 ? _f : new Metadata();
const responseStatus = {
code: (_h = (!isSuccess ? err.code : (_g = this.responseStatus) === null || _g === void 0 ? void 0 : _g.code)) !== null && _h !== void 0 ? _h : status.UNKNOWN,
details: (_k = (!isSuccess ? err.details : (_j = this.responseStatus) === null || _j === void 0 ? void 0 : _j.details)) !== null && _k !== void 0 ? _k : '',
metadata: (_m = (!isSuccess ? err.metadata : (_l = this.responseStatus) === null || _l === void 0 ? void 0 : _l.metadata)) !== null && _m !== void 0 ? _m : new Metadata(),
};
this.logSummary({
isSuccess,
methodName,
responseStatus,
customerId: (_o = this.request) === null || _o === void 0 ? void 0 : _o['customer_id'],
requestId: (_p = requestHeaders === null || requestHeaders === void 0 ? void 0 : requestHeaders.get('request-id')) === null || _p === void 0 ? void 0 : _p.toString(),
});
this.logDetail({
isSuccess,
methodName,
responseStatus,
requestHeaders,
request,
responseHeaders,
response: err || value,
});
}
logSummary(event) {
if (this.requestLogging === true ||
this.requestLogging.summary === true) {
const { isSuccess, methodName, responseStatus, customerId, requestId } = event;
const messages = [
`${isSuccess ? 'SUCCESS' : 'FAILURE'} REQUEST SUMMARY.`,
`Host=${HOST},`,
`Method=${methodName},`,
`ClientCustomerId=${customerId},`,
`RequestId=${requestId},`,
`ResponseCode=${responseStatus.code}`,
];
if (isSuccess) {
const msg = messages.join(' ').concat('.');
this.summaryLogger.info(msg);
}
else {
let msg = messages
.join(' ')
.concat(`, Fault=${responseStatus.details}`);
if (!msg.endsWith('.'))
msg += '.';
this.summaryLogger.warn(msg);
}
}
}
logDetail(event) {
var _a, _b, _c, _d, _e;
if (this.requestLogging === true ||
this.requestLogging.detail === true) {
const { isSuccess, methodName, responseStatus, requestHeaders, request, responseHeaders, response, } = event;
const messages = [
`${isSuccess ? 'SUCCESS' : 'FAILURE'} REQUEST DETAIL.`,
'Request',
'-------',
`MethodName: ${methodName}`,
`Host: ${HOST}`,
`Headers: ${JSON.stringify((_a = requestHeaders === null || requestHeaders === void 0 ? void 0 : requestHeaders.getMap()) !== null && _a !== void 0 ? _a : {})}`,
`Body: ${JSON.stringify(request)}`,
`\nResponse`,
'--------',
`Headers: ${JSON.stringify((_b = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders.getMap()) !== null && _b !== void 0 ? _b : {})}`,
];
if (!isSuccess) {
const serviceError = response;
const { errors } = getGoogleAdsError(serviceError);
const [googleAdsError] = errors !== null && errors !== void 0 ? errors : [];
const [errorType, errorCode] = (_d = Object.entries((_c = googleAdsError === null || googleAdsError === void 0 ? void 0 : googleAdsError.error_code) !== null && _c !== void 0 ? _c : {}).find(([key, value]) => ![undefined, null].includes(value))) !== null && _d !== void 0 ? _d : [];
const errorMessage = (_e = googleAdsError === null || googleAdsError === void 0 ? void 0 : googleAdsError.message) !== null && _e !== void 0 ? _e : responseStatus.details;
messages.push(`Body: ${errorMessage}`, `ResponseCode: ${responseStatus.code}`, `ErrorCode: ${errorCode} (${errorType})`, `FailureMessage: ${responseStatus.details}`);
this.detailLogger.info(messages.join('\n'));
}
else {
messages.push(`Body: ${JSON.stringify(cleanEmpty(response))}`, `ResponseCode: ${responseStatus.code}`);
this.detailLogger.debug(messages.join('\n'));
}
}
}
}