UNPKG

@htdangkhoa/google-ads

Version:
165 lines (164 loc) 8.17 kB
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')); } } } }