From a5ed9140bb4b4a882b498b23524e2ebd46b9d57b Mon Sep 17 00:00:00 2001 From: Adrien FIGARD Date: Mon, 16 Sep 2024 16:11:11 +0200 Subject: [PATCH 1/2] :art: Format code --- package.json | 4 +- .../custom-plugins/monitor-envelop.ts | 232 ++-- .../custom-plugins/monitor-fetch.ts | 110 +- .../custom-plugins/monitor-yoga.ts | 226 ++-- .../local-pkg/directive-spl-1.0.0.tgz | Bin 52652 -> 52907 bytes .../inject-additional-transforms-1.0.0.tgz | Bin 2356 -> 2377 bytes packages/graphql-mesh/package.json | 18 +- .../@omnigraph+json-schema+0.97.4.patch | 2 +- packages/graphql-mesh/serve.ts | 19 +- packages/graphql-mesh/utils/logger.ts | 1106 +++++++++-------- .../graphql-mesh/utils/parseYamlConfig.ts | 119 +- 11 files changed, 1008 insertions(+), 828 deletions(-) diff --git a/package.json b/package.json index 775aba0..94444c1 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "preinstall": "npm run build:local:packages", "start": "npm start -w graphql-mesh", "startmesh": "npm run startmesh -w graphql-mesh", - "serve": "npm run serve -w graphql-mesh" - }, + "serve": "npm run serve -w graphql-mesh" + }, "devDependencies": { "concurrently": "^8.2.2", "patch-package": "^8.0.0" diff --git a/packages/graphql-mesh/custom-plugins/monitor-envelop.ts b/packages/graphql-mesh/custom-plugins/monitor-envelop.ts index 1506f4a..b56c1fe 100644 --- a/packages/graphql-mesh/custom-plugins/monitor-envelop.ts +++ b/packages/graphql-mesh/custom-plugins/monitor-envelop.ts @@ -1,110 +1,146 @@ import { type Plugin } from '@envelop/core' import { Logger } from '../utils/logger' -import { NoSchemaIntrospectionCustomRule } from 'graphql'; -import { GraphQLError } from 'graphql'; +import { NoSchemaIntrospectionCustomRule } from 'graphql' +import { GraphQLError } from 'graphql' /** - * monitor plugin in order to get event contextual log and add some security rules - * useful to - * - log the graphql Query event - * - add desabled introspection validation rule - * - remove suggestion message - * - log the execute result summary with executes duration - * - remove not allowed introspection in result + * Monitor plugin to get event contextual logs and add some security rules. + * Used to: + * - log the GraphQL Query event + * - add a disabled introspection validation rule + * - remove suggestion messages + * - log the execute result summary with execution duration + * - remove not allowed introspection in the result */ const formatter = (error: GraphQLError, mask: string): GraphQLError => { - if (error instanceof GraphQLError) { - error.message = error.message.replace(/Did you mean ".+"/g, mask); - } - return error as GraphQLError; -}; + if (error instanceof GraphQLError) { + error.message = error.message.replace(/Did you mean ".+"/g, mask) + } + return error as GraphQLError +} + export default ({ options }): Plugin => { - // not allow by default - const allowIntrospection = options?.introspection?.allow || process.env['ENABLED_INTROSPECTION'] || false - // low info in log by default - const resultLogInfoLevel = options?.resultLogInfoLevel ? options.resultLogInfoLevel : "low" - const denyIntrospectionHeaderName = options?.introspection?.denyHeaderName || null - const denyIntrospectionHeaderValue = options?.introspection?.denyHeaderValue || null - const allowIntrospectionHeaderName = options?.introspection?.allowHeaderName || null - const allowIntrospectionHeaderValue = options?.introspection?.allowHeaderValue || null - const isMaskSuggestion = options?.maskSuggestion?.enabled || false - const maskSuggestionMessage = options?.maskSuggestion?.message || "" - return { - onParse({ context }) { - if (options.logOnParse) { - Logger.graphqlQuery(context['request']['headers'], context['params']) - } - }, + // Not allowed by default + const allowIntrospection = + options?.introspection?.allow || process.env['ENABLED_INTROSPECTION'] || false + // Low info in log by default + const resultLogInfoLevel = options?.resultLogInfoLevel ? options.resultLogInfoLevel : 'low' + const denyIntrospectionHeaderName = options?.introspection?.denyHeaderName || null + const denyIntrospectionHeaderValue = options?.introspection?.denyHeaderValue || null + const allowIntrospectionHeaderName = options?.introspection?.allowHeaderName || null + const allowIntrospectionHeaderValue = options?.introspection?.allowHeaderValue || null + const isMaskSuggestion = options?.maskSuggestion?.enabled || false + const maskSuggestionMessage = options?.maskSuggestion?.message || '' - onValidate: ({ addValidationRule, context }) => { - const headers = context['request'].headers - let deny = true - /* - allowIntrospection=false : intropection deny for all - denyIntrospectionHeaderName : name of the header to check to deny introspection is deny ex plublic proxy header - allowIntrospectionHeaderName : name of the header allow if this header and value is presents - */ - // if introspection not allow - if (allowIntrospection) { - // intropection may be allow - deny = false - // is existed a header to deny introspection - if (denyIntrospectionHeaderName) { - if (headers.get(denyIntrospectionHeaderName)) { - if (headers.get(denyIntrospectionHeaderName).includes(denyIntrospectionHeaderValue)) { - Logger.denyIntrospection("onValidate", "deny by headers " + denyIntrospectionHeaderName + ": " + headers.get(denyIntrospectionHeaderName), headers) - deny = true - } - } - } - // is existed a header mandatory to allow introspection - if (allowIntrospectionHeaderName) { - deny = true - if (headers.get(allowIntrospectionHeaderName)) { - if (headers.get(allowIntrospectionHeaderName).includes(allowIntrospectionHeaderValue)) { - Logger.allowIntrospection("onValidate", "allow by headers " + allowIntrospectionHeaderName + ": " + headers.get(allowIntrospectionHeaderName).substring(0, 4) + "...", headers) - deny = false - } else { - Logger.denyIntrospection("onValidate", "deny by bad header value " + allowIntrospectionHeaderName + ": " + headers.get(allowIntrospectionHeaderName).substring(0, 4) + "...", headers) - } - } else { - Logger.denyIntrospection("onValidate", "deny by no header " + allowIntrospectionHeaderName, headers) - } - } - } - if (deny) { - addValidationRule(NoSchemaIntrospectionCustomRule) - } + return { + onParse({ context }) { + if (options.logOnParse) { + Logger.graphqlQuery(context['request']['headers'], context['params']) + } + }, - return function onValidateEnd({ valid, result, setResult }) { - if (isMaskSuggestion && !valid) { - setResult(result.map((error: GraphQLError) => formatter(error, maskSuggestionMessage))); - } - }; - }, + onValidate: ({ addValidationRule, context }) => { + const headers = context['request'].headers + let deny = true + /* + allowIntrospection = false: introspection denied for all + denyIntrospectionHeaderName: name of the header to check to deny introspection, e.g., public proxy header + allowIntrospectionHeaderName: name of the header to allow if this header and value are present + */ + if (allowIntrospection) { + // Introspection may be allowed + deny = false + // If there exists a header to deny introspection + if (denyIntrospectionHeaderName) { + if (headers.get(denyIntrospectionHeaderName)) { + if (headers.get(denyIntrospectionHeaderName).includes(denyIntrospectionHeaderValue)) { + Logger.denyIntrospection( + 'onValidate', + 'Denied by headers ' + + denyIntrospectionHeaderName + + ': ' + + headers.get(denyIntrospectionHeaderName), + headers + ) + deny = true + } + } + } + // If there exists a mandatory header to allow introspection + if (allowIntrospectionHeaderName) { + deny = true + if (headers.get(allowIntrospectionHeaderName)) { + if (headers.get(allowIntrospectionHeaderName).includes(allowIntrospectionHeaderValue)) { + Logger.allowIntrospection( + 'onValidate', + 'Allowed by headers ' + + allowIntrospectionHeaderName + + ': ' + + headers.get(allowIntrospectionHeaderName).substring(0, 4) + + '...', + headers + ) + deny = false + } else { + Logger.denyIntrospection( + 'onValidate', + 'Denied by bad header value ' + + allowIntrospectionHeaderName + + ': ' + + headers.get(allowIntrospectionHeaderName).substring(0, 4) + + '...', + headers + ) + } + } else { + Logger.denyIntrospection( + 'onValidate', + 'Denied by missing header ' + allowIntrospectionHeaderName, + headers + ) + } + } + } + if (deny) { + addValidationRule(NoSchemaIntrospectionCustomRule) + } - onExecute(/*{ args, extendContext }*/) { - let timestampDebut = new Date().getTime() - return { - before() { + return function onValidateEnd({ valid, result, setResult }) { + if (isMaskSuggestion && !valid) { + setResult(result.map((error: GraphQLError) => formatter(error, maskSuggestionMessage))) + } + } + }, - timestampDebut = new Date().getTime() - }, - onExecuteDone({ result, args }) { - const timestampDone = new Date().getTime(); - // short cut to desabled introspection response in case of bad configuration rule - if (!allowIntrospection && args.contextValue['params'].query.includes('__schema')) { - result['data'] = {} - result['errors'] = [{ message: "Fordidden" }] - Logger.error('SECU', 'onExecute', 'Introspection query deteted not allowed', args.contextValue['params']) - } - if (options.loOnExecuteDone) { - Logger.endExec(args.contextValue['request']['headers'], result, timestampDone - timestampDebut, resultLogInfoLevel) - } - } - } - } - } + onExecute(/* { args, extendContext } */) { + let timestampStart = new Date().getTime() + return { + before() { + timestampStart = new Date().getTime() + }, + onExecuteDone({ result, args }) { + const timestampEnd = new Date().getTime() + // Shortcut to disable introspection response in case of bad configuration rule + if (!allowIntrospection && args.contextValue['params'].query.includes('__schema')) { + result['data'] = {} + result['errors'] = [{ message: 'Forbidden' }] + Logger.error( + 'SECU', + 'onExecute', + 'Introspection query detected and not allowed', + args.contextValue['params'] + ) + } + if (options.logOnExecuteDone) { + Logger.endExec( + args.contextValue['request']['headers'], + result, + timestampEnd - timestampStart, + resultLogInfoLevel + ) + } + } + } + } + } } - - diff --git a/packages/graphql-mesh/custom-plugins/monitor-fetch.ts b/packages/graphql-mesh/custom-plugins/monitor-fetch.ts index 26d7437..d5ce872 100644 --- a/packages/graphql-mesh/custom-plugins/monitor-fetch.ts +++ b/packages/graphql-mesh/custom-plugins/monitor-fetch.ts @@ -1,65 +1,63 @@ -import { type Plugin } from '@envelop/core'; +import { type Plugin } from '@envelop/core' import { Logger } from '../utils/logger' /** - * monitor fetch source - * use to : - * - add log event for each fetch like, url, response status, duration + * Monitor fetch source + * Used to: + * - add log events for each fetch such as URL, response status, and duration */ export default ({ options }) => { - return { - onFetch({ context, info }) { - if (!info) { - Logger.warn("noFeychInfo", "onFetch", "no info in on fetch") - return; - } - const start = Date.now(); - let rawSource = context[info.sourceName] - let description = info.parentType._fields[info.path.key].description + return { + onFetch({ context, info }) { + if (!info) { + Logger.warn('noFetchInfo', 'onFetch', 'No info in on fetch') + return + } + const start = Date.now() + let rawSource = context[info.sourceName] + let description = info.parentType._fields[info.path.key].description - return (fetch: any) => { - if (options.logOnFetch) { - const duration = Date.now() - start; - let fetchInfo = {} - let httpStatus = null - let url = null - if (options.fullFetchInfo) { - fetchInfo = { - fieldName: info.fieldName, - sourceName: info.sourceName, - pathKey: info.path.key, - operation: info.operation.name, - variables: info.variables, - endpoint: rawSource.rawSource.handler.config.endpoint, - description: description - } - } else { - fetchInfo = { - fieldName: info.fieldName, - pathKey: info.path.key, - operation: info.operation.name, - variables: info.variableValues, - endpoint: rawSource.rawSource.handler.config.endpoint, - } - } - //const fetchResponseInfo = {} - if (fetch.response) { - - httpStatus = fetch.response.status - url = fetch.response.url - const options = fetch.response.options - if (options) { - fetchInfo['options'] = { - requestId: options.headers['x-request-id'], - server: options.headers['server'] - } - } - } - Logger.onFetch(context.request, url, httpStatus, duration, fetchInfo) - } - } - } - } + return (fetch: any) => { + if (options.logOnFetch) { + const duration = Date.now() - start + let fetchInfo = {} + let httpStatus = null + let url = null + if (options.fullFetchInfo) { + fetchInfo = { + fieldName: info.fieldName, + sourceName: info.sourceName, + pathKey: info.path.key, + operation: info.operation.name, + variables: info.variables, + endpoint: rawSource.rawSource.handler.config.endpoint, + description: description + } + } else { + fetchInfo = { + fieldName: info.fieldName, + pathKey: info.path.key, + operation: info.operation.name, + variables: info.variableValues, + endpoint: rawSource.rawSource.handler.config.endpoint + } + } + if (fetch.response) { + httpStatus = fetch.response.status + url = fetch.response.url + const options = fetch.response.options + if (options) { + fetchInfo['options'] = { + requestId: options.headers['x-request-id'], + server: options.headers['server'] + } + } + } + Logger.onFetch(context.request, url, httpStatus, duration, fetchInfo) + } + } + } + } } diff --git a/packages/graphql-mesh/custom-plugins/monitor-yoga.ts b/packages/graphql-mesh/custom-plugins/monitor-yoga.ts index 02ae05e..4506325 100644 --- a/packages/graphql-mesh/custom-plugins/monitor-yoga.ts +++ b/packages/graphql-mesh/custom-plugins/monitor-yoga.ts @@ -3,116 +3,138 @@ import { Logger } from '../utils/logger' import { GraphQLError } from 'graphql' import { v4 as uuidv4 } from 'uuid' /** - * monitor plugin in order to get event contextual log and add some security rules - * useful to : - * - log new request comming event - * - add request timestamp in headers to get duration time - * - monitor instropection request - * - mask error in result is required ( ex in production ) - * - log response sumary event - * - remove a eventualy not allowed instropection data in result + * Monitor plugin to get event contextual logs and add some security rules. + * Used to: + * - log new incoming request events + * - add request timestamps in headers to get duration time + * - monitor introspection requests + * - mask errors in the result if required (e.g., in production) + * - log response summary events + * - remove potentially not allowed introspection data in the result */ -export function useYagaMonitoring({ options }): Plugin { - const isMaskErrors = options?.maskError?.enabled || process.env['MASK_ERRORS'] || false - // filter error in production anyway - const isFilterError = options?.filterError?.enabled || process.env['FILTER_ERRORS'] == 'true' || process.env['IS_PROUCTION_ENV'] == 'true' || false - const errorMaskMessage = options?.maskError?.message ? options.maskError.message : "something goes wrong" - const responseLogInfoLevel = options?.responseLogInfoLevel ? options.responseLogInfoLevel : "medium" - const resultLogInfoLevel = options?.resultLogInfoLevel ? options.resultLogInfoLevel : "medium" +export function useYogaMonitoring({ options }): Plugin { + const isMaskErrors = options?.maskError?.enabled || process.env['MASK_ERRORS'] || false + // Filter errors in production anyway + const isFilterError = + options?.filterError?.enabled || + process.env['FILTER_ERRORS'] == 'true' || + process.env['IS_PRODUCTION_ENV'] == 'true' || + false + const errorMaskMessage = options?.maskError?.message + ? options.maskError.message + : 'Something went wrong' + const responseLogInfoLevel = options?.responseLogInfoLevel + ? options.responseLogInfoLevel + : 'medium' + const resultLogInfoLevel = options?.resultLogInfoLevel ? options.resultLogInfoLevel : 'medium' - return { - onRequest({ request/*, fetchAPI, endResponse */ }) { - if (options.LogOnRequest) { - // log only graphql request, avoid log other request like metric requests - if (request.url.includes("/graphql")) { - Logger.onRequest(request) - } - } + return { + onRequest({ request /*, fetchAPI, endResponse */ }) { + if (options.LogOnRequest) { + // Log only GraphQL requests, avoid logging other requests like metric requests + if (request.url.includes('/graphql')) { + Logger.onRequest(request) + } + } - // add resuestTimestamp in headers - const timestamp = new Date().getTime(); - request.headers.append("requestTimestamp", String(timestamp)) + // Add requestTimestamp in headers + const timestamp = new Date().getTime() + request.headers.append('requestTimestamp', String(timestamp)) - // add x-request-id in header if not present - if (!request.headers.get('x-request-id')) { - request.headers.append("x-request-id", uuidv4()) - } + // Add x-request-id in header if not present + if (!request.headers.get('x-request-id')) { + request.headers.append('x-request-id', uuidv4()) + } + }, + onRequestParse(args) { + const beforeTimestamp = new Date().getTime() + let requestHeaders = args.request.headers + return { + onRequestParseDone(nRequestParseDoneEventPayload) { + const timestamp = new Date().getTime() + if (options.logOnRequestParseDone) { + Logger.onRequestParseDone( + requestHeaders, + nRequestParseDoneEventPayload.requestParserResult['query'], + nRequestParseDoneEventPayload.requestParserResult['operationName'], + nRequestParseDoneEventPayload.requestParserResult['variables'], + timestamp - beforeTimestamp + ) + } + if (nRequestParseDoneEventPayload.requestParserResult['query'].includes('__schema')) { + Logger.introspection( + requestHeaders, + nRequestParseDoneEventPayload.requestParserResult['query'] + ) + } + } + } + }, + onResultProcess(args) { + if (options.logOnResultProcess) { + // Calculate duration from request timestamp + let requestTimestamp: number = 0 + if (args.request['headers']) { + const requestTimestampString = args.request['headers'].get('requesttimestamp') + if (requestTimestampString) { + requestTimestamp = parseInt(requestTimestampString) + } + } + const responseTimestamp = new Date().getTime() + Logger.onResultProcess( + args.request, + args.result, + requestTimestamp > 0 ? responseTimestamp - requestTimestamp : 0, + resultLogInfoLevel + ) + } + // If we want to replace all messages with a generic message + if (isMaskErrors) { + if (args.result['errors']) { + let errors = args.result['errors'] + for (let i = 0; i < errors.length; i++) { + errors[i] = errorMaskMessage + } + } + } else { + // If we want to filter errors to only return the message, don't return extended information like stack traces + if (args.result['errors']) { + if (isFilterError) { + let errors = args.result['errors'] + for (let i = 0; i < errors.length; i++) { + // Return only message and path + errors[i] = new GraphQLError(filterErrorMessage(errors[i]['message']), { + path: errors[i]['path'] + }) + } + } + } + } + }, - }, - onRequestParse(args) { - const beforeTimestamp = new Date().getTime(); - let requestHeaders = args.request.headers - return { - onRequestParseDone(nRequestParseDoneEventPayload) { - const timestamp = new Date().getTime(); - if (options.logOnRequestParseDone) { - Logger.onRequestParseDone(requestHeaders, nRequestParseDoneEventPayload.requestParserResult['query'], nRequestParseDoneEventPayload.requestParserResult['operationName'], nRequestParseDoneEventPayload.requestParserResult['variables'], timestamp - beforeTimestamp) - } - if (nRequestParseDoneEventPayload.requestParserResult['query'].includes('__schema')) { - Logger.introspection(requestHeaders, nRequestParseDoneEventPayload.requestParserResult['query']) - } - } - } - }, - onResultProcess(args) { - if (options.logOnResultProcess) { - // calculate duration from request timestamp - let requestTimestamp: number = 0 - if (args.request['headers']) { - const requestTimestampString = args.request['headers'].get('requesttimestamp') - if (requestTimestampString) { - requestTimestamp = parseInt(requestTimestampString) - } - } - const responseTimestamp = new Date().getTime(); - Logger.onResultProcess(args.request, args.result, requestTimestamp > 0 ? responseTimestamp - requestTimestamp : 0, resultLogInfoLevel) - } - // if we want to replace all message with a generic message - if (isMaskErrors) { - if (args.result['errors']) { - let errors = args.result['errors'] - for (let i = 0; i < errors.length; i++) { - errors[i] = errorMaskMessage - } - } - } else { - // if we want to filter error to only return the message, don't return extend information like stacktrace - - if (args.result['errors']) { - if (isFilterError) { - let errors = args.result['errors'] - for (let i = 0; i < errors.length; i++) { - // return only message and path - errors[i] = new GraphQLError(filterErrorMessage(errors[i]['message']), { path: errors[i]['path'] }) - } - } - } - } - }, - - onResponse({ request, response }) { - // dont log options http - if (request.method != 'OPTIONS') { - if (options.logOnResponse) { - // only log graphql request don't log metrics or other requests - if (request.url.includes("/graphql")) { - Logger.onResponse(request, response, responseLogInfoLevel) - } - } - } - } - } + onResponse({ request, response }) { + // Don't log OPTIONS HTTP method + if (request.method != 'OPTIONS') { + if (options.logOnResponse) { + // Only log GraphQL requests, don't log metrics or other requests + if (request.url.includes('/graphql')) { + Logger.onResponse(request, response, responseLogInfoLevel) + } + } + } + } + } } /** filterErrorMessage - * use to filter error message : - * - remove disabled introspection - * todo: add other filter rules to remove non expecting message -*/ + * Used to filter error messages: + * - Removes disabled introspection messages + * TODO: Add other filter rules to remove unexpected messages + */ function filterErrorMessage(message: string) { - if (message.includes("introspection has been disabled")) { - return "forbidden" - } - return message + if (message.includes('introspection has been disabled')) { + return 'forbidden' + } + return message } diff --git a/packages/graphql-mesh/local-pkg/directive-spl-1.0.0.tgz b/packages/graphql-mesh/local-pkg/directive-spl-1.0.0.tgz index aa64f1202904a17ea2faed2e669e82b616659c98..14325af334d070dbd0e7df8b5c4fa119cd7750e9 100644 GIT binary patch literal 52907 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 Hc$DXFW*36- literal 52652 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

*76ZXeC5$^(LlOeMj5J2saG>0aBfX}K{~ zt-z@P0Vgu;O|J*@Q+_6oq6@xhq6X_a<)j`{odhQ-GS0-al<+s=TC-~h z?Sx?nEXBp3qGl;Jhw5?<9eN^~z7p$Ya|SHEx2T;5O325$x^rOm{Kszlf*}f1TUplAv8Y*hd3Um*!z$!QFu@m=9vHR{qRZ=BC&L&yP zWS*H_3epC@NB4X9hB!Y<%lk`srX8rD*w=SGUh9!U z2J4;kxm8kc-`T||@yF*Pq^=XdEQ65i!A=3iL;S0^uZI&OEY?K0I^Y<3PFqH4g4BjO z*c5{d=(@JZ6fh;XsQQLqa(Si-R#t0mSPK9fIxPSQg>t%3DLW%1P-+Bar*I&=!i2M*DJnSHVU7S;u9qf~%5(cQ&% zQ;)pJlEC+rxruQH?>RT6uGCC}9=Lb&au-#sgs*@uZ#6myyPf>`~HBh3fQA zxt5qF9kFgB&tR4UH0g15N|RSr=|V9!EO%TqR=DB^vO%FY*kHvt^g|8AhaQLBe{L(9 z3z|KJOx7wtl$y_XoF^`@ud?nUN%+;(|;4d70rUuZAzcn z+SMcxMI=rN&}S%o5Sbjn*NTXhco0R9$_J#zX9t@ BlQ;kX diff --git a/packages/graphql-mesh/local-pkg/inject-additional-transforms-1.0.0.tgz b/packages/graphql-mesh/local-pkg/inject-additional-transforms-1.0.0.tgz index 1f45b741ccb4c008aa16f676126d2642b720df8c..93b007f4f93377ff8ef425a82dd7ec712eb84653 100644 GIT binary patch literal 2377 zcmV-P3AXkhiwFP!00002|Ls~^bK5o+_OpHkmb=qPE=5t2gnM1?m4U>dKh|K7ocBq&j?)419uAs!_1;NaYV1AYWg;(Bl01?pT}rhYK%cq`KJ zqZxW{tjNKAHPbYYkB&eU-89Xk{&5c+^asagw|jhS9)Sb1+k1HQ5FD5XduS=4EVux?omFOCQWlm!0eMHh?!MpvniQB&h2E$2w7ACNM~;{|q;_AywirqZQPj41vYy9t{>oFc2-M+@O2@cPY0Zzgk;Nw-QtpunxNas(j8 z?zQ0){@)Z9w(_B@ok+V&#Gxb_m10j$N(NT(81ooUTyNQI=6r&$85qaq?QRp^f>@WPt4OpTjezXu| z9gy^r@JmN#X+99m1dr+(o05Or%2CptF@O=M)?fIt-rV$>rk*_v3^z%FYcZlorPfFI zq;D>p>e#(NS1BSiS0wLsFhc=axNP2>IHKr1RdlH2*7jz;<(Cv%<=6-7yR%<}r9`2I z-QKrXOlGxHAEs@$PwR$+A6b%v(Jjv=tI_HF6OcH?9y${X=GBX*qYTm-p_?4kO=(FP z|05Fa9shTa`rG(_(5>mjqC;grCzx%Mi z_5R--40?6`?e*8vmsE1h3@Ul#>7X{07)UenO8_+SBEv)&on2};qkNAqah7b( zVcVLko%;bd?X^%UM;sn@4jJbg&ONI|nPAq*Y<9i3?HMA}k2tUdhS4b<60z5)pq;#3XnBlh=-n74D4LP%W zKaJyn$dA{R49drCwO@7%n&SSg#t3B+!HYO_O`ekt0nGm_{=0YVe*6C4@Atdg_^*3h z@BjP3fBBZ)*ZHod4Ygu>)Wns9BZ;;S}m$J8*hrTM#+}TfZJd_|~x?oCJ<#S=K3>p0cj*^_LL7)XyP2*BuBQ zeG1{ZHHFTSUrssEdd?W1LHJDkWQ?Mh{XjN^+Jbw^h@9~WgirJdgp*v%T#>+g`PEy8 zStmqtcK%cJXBw81OoKBPf-);0bLLX?LO2=gXAoZ5x@kjb+SU|4dFTiyx#Tkl&%_lM zGJ!B=*8Q-W=s&ZrQwUEL(a+)Jsg59g#X1&t?h)%b4b)I@aeQ>5gX~ib}J0;CG?3zO7hb-wPW0nO-cUYFB-0 z*;ed6ht4}YBlG!XBD1CP96AFhH>=2Ys2|%rwI|T&+S!l^&oOS?gheA)=B(`P`Er(a z?%el^a|@d%rURWBljU=dR>Jg{-z1KH#kLggUe{5q`gd+ff2Sc=x#jo+tSUn8LHIQv z-mxoevbjz6u1I+hdhBxckv2Kd`ObncnvC^h2Zj@;KE(L=@BjP4e@Fe^Hva1kYW(*Z z;Xe-kHU8UQ{pTq=R(}3eRsm&& zobs@_DBipQXNWBGl9C-2pZttm9W>r9GqXRH<0MLmB3ztIwv~MAM%TPk{#1+-zt$a!w}zWb@*`bvqwCg|%-rHf v)?L5%-1+_g|God$@Bj7wU+@3*{$KC^f9d{Tx4PBs%Wb~{Np+&y07d`+W8|sZ literal 2356 zcmV-43Cs2$iwFP!00002|Lq!UbK5pDpYbc89jNd)^4|Vwzo+c9NKnor%Rsn`aA7TXJ@AkbnQ-ecY7E9pKPEdQEY{v$|D#F zjb#6yNK=xCk|+)xJ649ZR~MJmjLG_-=*mD`-t zXx3r`IelQoGcFdU2=?0fxid$-PGSA(86PB78Zfi9wN)cqZ0h^3XZ@cb6pkh>az7KgW@hmA|iJi!Qu47*@g+luWOsnam@!-g~uUE{k{V~F}M zrsX}2h0IiQ*N4e;Ostsv>kb(&eo+Z$Bufw)pb5j;qGr2R6y0Yn*MTifnAkB$zr)eQ znX2T%is*q8LO4jO#xp0sE6j_Fv~3HnOSM_J!UB;6MPiQnvg11qI7!G`Nl|dseS!b~VV}Gsz*j>Swqts*v~& zlolySJqSn|NgVdIv$iC7HIUNgOh_TzmYeX|MdZgxOn=1i-;+{IyYwBeE<0W&Qc#w2 zo2S`X2zpt@n(3%4pS(`pk|5E7B%0Md`m2zO8wP$p0)&0^j8TP^Q9&A^HDUpl8;bU8c zJj;#xFlp;;TGT}OktR9B+4_4E-1l4mB$1zlHa+G6^XBB`URu&>b1QgKHK_%~`kzMg zjo1I3?cQqr-|tlQ|0bF!81G2=Hl>o%L>J)Y-I^?Th5fXontwX130YgjisX`>PeH)b zs%-!BWjo&{NxDl`ReV*&S572Kau{g3be z1qfEp_cl=fx7*$A<@&$Z?^o~tH`4ADER&T1QEY!c_r1$VSyWl^<>mjQC;fx-zq8w0 zdH(P8``s%4H& zw;V=R@?lvJaN?Xqe)p8~jY=uTS}bV9+d-h>HISlZT^R5O8Dycg)`?++;yJ!RSae=W)S-5a{?n)4mSbIl2E87 z=77@o%mM7`9HbBDq!~^K*N%Mk74d>O2@{WGTvvgh00a7CO0<@+p%sKQutM4t`$SU~ zhcJ{@;FB^&B%T{@-S6N3d%a#~wf^huRQvyC z>c4DD@2PB8QwB=DJu3Xk?!@;YXOwIV@pz^{2E#83Z4oiB)4fyKy#&$Fo%82G7%9Wy zP}h%i^=nf<+BTqX_6_y+K-b@!Fc`Te5DX9XqeDb}ub%4qsrpve->N2z)g$N)k92d! zx2B$tkAR~OC>o3$12+i0`Bn}MAdhbotjsN-_Hgvsh0R4+ylN-r61M-;n7!&CEsND~jBlTxQ z9qRg_#QL>9dZ|)fe}jmrky(V8LsxbMW5;HvW+DxGhKck+9p4aKa`SSRFe+xmTix6} z$gJlW1fDFxcuz3S9hgcEGu)CSc42FuIUL#lPv)Al%VEs8e3&z2yjU+=@az&9Tp_V~hcK%KETvIDl}F+2~UC3j-UH-XQqeNWpA>^hPGkyfjwV%bXdRao#o*+-F{X7eMa>kEB?gI(0p0kAq&}_57PQXK+<}u zZ%8*Bwj<>CP(kwrm6P%fon5NpvMMgC;_|a8F0;+=?^0K08vi{?%7T9$vzq);3dptZ z|L_g_hQ9xFR=)rAx~!C{>c7pM|2)Lk%CBFFQ$XoKPVuriKfHNIj%hT@j+Cr9@yXti z%aaaP51O17&jGD+D!$;Bxs7h9oglO9JdOmxlP&9*r6*B8^sFREcIljYakOMUe<{xo zMGnXX2%(n8&&C9ybB)Kw3a1@YU@V { - const config = getConfig() - const PORT = config.serve?.port ?? 4000 - const HOSTNAME = config.serve?.hostname ?? 'http://0.0.0.0' - const server = createServer(obj.createBuiltMeshHTTPHandler()) - Logger.info('STARTUP', 'main', `🚀 Server ready at ${HOSTNAME}:${PORT}/graphql`) - server.listen(PORT) - }) +const mesh = process.env['MESH_ARTIFACTS_DIRNAME'] || '.mesh' +import(mesh).then((obj) => { + const config = getConfig() + const PORT = config.serve?.port ?? 4000 + const HOSTNAME = config.serve?.hostname ?? 'http://0.0.0.0' + const server = createServer(obj.createBuiltMeshHTTPHandler()) + Logger.info('STARTUP', 'main', `🚀 Server ready at ${HOSTNAME}:${PORT}/graphql`) + server.listen(PORT) +}) diff --git a/packages/graphql-mesh/utils/logger.ts b/packages/graphql-mesh/utils/logger.ts index b30dadd..d9c29fb 100644 --- a/packages/graphql-mesh/utils/logger.ts +++ b/packages/graphql-mesh/utils/logger.ts @@ -1,521 +1,641 @@ /** - * Logger : Class static - * use to log event with much useful context information and some useful data + * Logger: Static Class + * Used to log events with contextual information and useful data * - * TODO : split into specifiques loggers and core logger + * TODO: Split into specific loggers and core logger */ -import { v4 as uuidv4 } from 'uuid'; - +import { v4 as uuidv4 } from 'uuid' export class Logger { - - private static level: string = process.env["LogLevel"] || "INFO" - private static format: string = process.env["LogFormat"] || "HUMAN" // set JSON_STRING to have one line json string by log - private static bodyMaxLogSize = process.env["LogBodyMaxSize"] ? parseInt(process.env["LogBodyMaxSize"]) : 200 - private static maxSkackLogSize = process.env["LogStackTraceMaxSize"] ? parseInt(process.env["LogStackTraceMaxSize"]) : 500 - private static envLog: string = process.env["LogEnvFieldToAdd"] // use to add env extra field in json log ex "app=graphql,env.name=production,env.site=Paris" - private static localDateCountry: string = process.env["LogLocalDateCountry"] || "fr-FR" - private static logHeaders = defineLogHeaders(process.env["LogHeaders"] || "headers.host=host,headers.origin,headers.user-agent=user-agent,headers.content-length=content-length,headers.authorization=authorization") - private static logContextHeaders = defineLogHeaders(process.env["LogContextHeaders"] || "ctx.requestId=x-request-id") - private static skipHealthCheck = process.env["skipHealthCheck"] ? process.env["skipHealthCheck"] == "true" : true - private static healthCheckHeaderName = process.env["healthCheckHeazder"] || "x-internal" - private static HealthCheckHeaderValue = process.env["healthCheckHeaderValue"] || "health-check" - private static MaxErrorStackSize = process.env["MaxErrorStackSize"] ? parseInt(process.env["MaxErrorStackSize"]) : 200 - constructor() { - - } - /** - * Core logger with Human format or machine in one line json string format - */ - private static log(level: string, typeEv: string, message: string, headers = null, onlyContextHeader: boolean, info: any = null, err = null) { - - const date = new Date(); - const timestamp = date.getTime(); - - // if machine friendly json string is required - if (Logger.format == 'JSON_STRING') { - const log = { - events: [{ - idEv: uuidv4(), - date: date.toLocaleString(this.localDateCountry), - level: level, - typeEv: typeEv, - timestamp: timestamp, - message: message - }] - } - try { - // add http headers - if (headers) { - this.addHeadersToContextLog(log, headers) - if (!onlyContextHeader) { - this.addHeadersToLog(log.events[0], headers) - } - } - // add extra information to log event - if (info) { - for (const key in info) { - log.events[0][key] = info[key] - } - } - // if exception error add message and an extract of stack trace - if (err) { - log.events[0]['exeception'] = {} - //console.log("Exception:", err) - - log.events[0]['exeception'] = { - message: err.message, - stack: err.stack?.substring(0, this.MaxErrorStackSize) + " ..." - } - - } - // if define add extra env field - if (this.envLog) { - addEnvFieldLog(this.envLog, log) - } - - } catch (e) { - log['error'] = "error whileg getting log event contextual info :" + e.message - } - console.log(JSON.stringify(log)) - } else { - if (info) { - if (err) { - console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message, info, err) - } else - console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message, info) - - } else { - if (err) { - console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message, err) - } else - console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message) - - } - } - } - - public static error(typeEv: string, source: string, message: string, headers = null, info = null, e = null) { - if (Logger.level == 'ERROR' || Logger.level == 'WARN' || Logger.level == 'INFO' || Logger.level == 'DEBUG') { - Logger.log('ERROR', typeEv, source + ":" + message, headers, false, info, e) - } - } - public static warn(typeEv: string, source: string, message: string, headers: any = null, info: any = null, e = null) { - if (Logger.level == 'WARN' || Logger.level == 'INFO' || Logger.level == 'DEBUG') { - Logger.log('INFO', typeEv, source + ":" + message, headers, false, info, e) - } - } - - public static info(typeEv: string, source: string, message: string, headers: any = null, info: any = null, e = null) { - if (Logger.level == 'INFO' || Logger.level == 'DEBUG') { - Logger.log('INFO', typeEv, source + ":" + message, headers, true, info, e) - } - } - public static debug(typeEv: string, source: string, message: string, headers: any = null, info: any = null, e = null) { - if (Logger.level == 'DEBUG') { - Logger.log('DEBUG', typeEv, source + ":" + message, headers, true, info, e) - } - } - - - /** - * log the on parse event - */ - public static onParse(headers: any) { - try { - if (this.isEventToLog(headers)) { - Logger.log('INFO', "ON-PARSE", "Request", headers, true) - } - } catch (e) { - Logger.error('LOGGER_ERROR', 'onParse logger', 'error during log generation', null, e) - - } - } - - /** - * log the on end exec done event - */ - public static endExec(headers: any, result: any, duration: number, resultLogInfo: any) { - try { - if (this.isEventToLog(headers)) { - const info = { - result: InfoResult(result, this.maxSkackLogSize, resultLogInfo), - duration: duration, - } - Logger.log('INFO', "endExecDone", "Request", headers, true, info) - } - } catch (e) { - Logger.error('LOGGER_ERROR', 'endExec logger', 'error during log generation', headers, null, e) - } - } - - /** - * log the on result process event - */ - public static onResultProcess(request: any, result: any, duration: number, resultLogInfo: any) { - const headers = request['headers'] - try { - - if (this.isEventToLog(headers)) { - - const info = { - result: InfoResult(result, this.maxSkackLogSize, resultLogInfo), - duration: duration - } - Logger.log('INFO', "onResultProcess", "Result", headers, true, info) - } - } catch (e) { - Logger.error('LOGGER_ERROR', 'onResponse logger', 'error during log generation', headers, null, e) - } - } - - /** - * log the on request parse done event - */ - public static onRequestParseDone(headers: any, query: any, operation: string, variables: any, duration: number) { - if (this.isEventToLog(headers)) { - - const info = { - operation: operation, - query: query, - variables: variables, - parsingDuration: duration - } - Logger.log('INFO', "requestParseDone", "requestParse", headers, true, info) - } - } - /** - * log the on reponse event http respnse return - */ - public static onResponse(request: any, response: any, logResponseLevel: string) { - const headers = request['headers'] - try { - if (this.isEventToLog(headers)) { - // calculate duration from request timestamp - const requestTimestampString: string = headers.get('requesttimestamp') - let requestTimestamp: number; - if (requestTimestampString) { - requestTimestamp = parseInt(requestTimestampString) - } - const responseTimestamp = new Date().getTime(); - const info = { - request: { - url: request.url, - method: request.method - }, - response: { - status: response.status, - contentLength: response.contentLength, - }, - httpStatus: response.status, - duration: responseTimestamp - requestTimestamp - } - if (logResponseLevel != 'low') { - info.response['bodyExtract'] = extractBody(response.bodyInit, this.bodyMaxLogSize) - } - - Logger.log('INFO', "onResponse", responseSummary(response.bodyInit), headers, true, info) - } - } - catch (e) { - Logger.error('LOGGER_ERROR', 'onResponse logger', 'error during log generation', headers, null, e) - } - } - - public static introspection(headers, query) { - try { - const info = { - query: query - } - Logger.warn('WARN_INTROSPECTION', "introspection", "introspection query", headers, info) - } - catch (e) { - Logger.error('LOGGER_ERROR', 'introspection logger', 'error during log generation', null, null, e) - } - } - - public static denyIntrospection(headers, info, message,) { - try { - Logger.warn('DENY_INTROSPECTION', info, message, headers) - } - catch (e) { - Logger.error('LOGGER_ERROR', 'denyIntrospection logger', 'error during log generation', headers, null, e) - } - } - - public static allowIntrospection(headers, info, message,) { - try { - Logger.warn('ALLOW_INTROSPECTION', info, message, headers) - } - catch (e) { - Logger.error('LOGGER_ERROR', 'denyIntrospection logger', 'error during log generation', headers, null, e) - } - } - public static onRequest(request: any) { - const headersInit = request['headers']['headersInit'] - const headers = new Map - - for (const header in headersInit) { - headers.set(header, headersInit[header]) - } - try { - if (this.isEventToLog(headers)) { - const info = { - url: request.url, - method: request.method, - //body: request.body - } - Logger.log('INFO', "onRequest", "request incomming", headers, false, info) - } - } - catch (e) { - Logger.error('LOGGER_ERROR', 'onRequest logger', 'error during log generation', headers, null, e) - } - } - - public static onFetch(request: any, url: string, httpStatus: string, duration: number, fetchInfo: any) { - try { - const headers = request['headers'] - const info = { - fetch: fetch, - duration: duration, - httpStatus: httpStatus, - url: url - } - Logger.log('INFO', "onFetch", "fetch", headers, true, info) - } catch (e) { - Logger.error('LOGGER_ERROR', 'onFetch logger', 'error during log generation', null, e) - } - } - - public static graphqlQuery(headers: any, params: any) { - try { - if (this.isEventToLog(headers)) { - const regex = / /gi; - const queryTolog = { - query: params['query'].replace(regex, ""), - operationName: params['operationName'], - variables: params['variables'] - } - Logger.log('INFO', "graphqlQuery", "GraphQL Query", headers, true, queryTolog) - } - } catch (e) { - Logger.error('LOGGER_ERROR', 'graphql query logger', 'error during log generation', headers, null, e) - } - } - private static isEventToLog(headers): boolean { - if (this.skipHealthCheck && headers) { - if (headers.get(this.healthCheckHeaderName) == this.HealthCheckHeaderValue) { - return false - } - } - return true - } - private static addHeadersToContextLog(log: any, headers: any) { - - try { - let headerMap = null - if (headers["_map"]) { - headerMap = headers["_map"] - } else { - headerMap = headers - } - - if (headerMap && headerMap.get) { - if (this.logContextHeaders) { - for (const contextKey in this.logContextHeaders) { - const contextHeader = this.logContextHeaders[contextKey] - if (headerMap.get(contextHeader.header)) { - - if (contextHeader.header.toLowerCase() == "authorization") { - addLog(log, contextHeader.name, mask(headerMap.get('authorization'))) - } else { - addLog(log, contextHeader.name, headerMap.get(contextHeader.header)) - } - } - } - } - } - } catch (e) { - Logger.error('LOGGER_ERROR', 'onheadersToLog', 'error during headers log generation', headers, null, e) - } - return log - } - - private static addHeadersToLog(log: any, headers: any) { - let headerMap = null - if (headers["_map"]) { - headerMap = headers["_map"] - } else { - headerMap = headers - } - try { - if (headerMap) { - if (this.logHeaders) { - - for (const logHeaderKey in this.logHeaders) { - const logHeader = this.logHeaders[logHeaderKey] - if (headerMap.get(logHeader.header)) { - if (logHeader.header.toLowerCase() == "authorization") { - addLog(log, logHeader.name, mask(headerMap.get('authorization'))) - } else { - addLog(log, logHeader.name, headerMap.get(logHeader.header)) - } - } - } - } - } - } catch (e) { - Logger.error('LOGGER_ERROR', 'onheadersToLog', 'error during headers log generation', headers, null, e) - } - return log - } + private static level: string = process.env['LogLevel'] || 'INFO' + private static format: string = process.env['LogFormat'] || 'HUMAN' // Set to JSON_STRING for one-line JSON string logs + private static bodyMaxLogSize = process.env['LogBodyMaxSize'] + ? parseInt(process.env['LogBodyMaxSize']) + : 200 + private static maxStackLogSize = process.env['LogStackTraceMaxSize'] + ? parseInt(process.env['LogStackTraceMaxSize']) + : 500 + private static envLog: string = process.env['LogEnvFieldToAdd'] // Add extra env fields in JSON log e.g., "app=graphql,env.name=production,env.site=Paris" + private static localDateCountry: string = process.env['LogLocalDateCountry'] || 'fr-FR' + private static logHeaders = defineLogHeaders( + process.env['LogHeaders'] || + 'headers.host=host,headers.origin,headers.user-agent=user-agent,headers.content-length=content-length,headers.authorization=authorization' + ) + private static logContextHeaders = defineLogHeaders( + process.env['LogContextHeaders'] || 'ctx.requestId=x-request-id' + ) + private static skipHealthCheck = process.env['skipHealthCheck'] + ? process.env['skipHealthCheck'] == 'true' + : true + private static healthCheckHeaderName = process.env['healthCheckHeader'] || 'x-internal' + private static healthCheckHeaderValue = process.env['healthCheckHeaderValue'] || 'health-check' + private static maxErrorStackSize = process.env['MaxErrorStackSize'] + ? parseInt(process.env['MaxErrorStackSize']) + : 200 + + constructor() {} + + /** + * Core logger with human-readable format or machine-friendly one-line JSON string format + */ + private static log( + level: string, + typeEv: string, + message: string, + headers = null, + onlyContextHeader: boolean, + info: any = null, + err = null + ) { + const date = new Date() + const timestamp = date.getTime() + + // If machine-friendly JSON string is required + if (Logger.format == 'JSON_STRING') { + const log = { + events: [ + { + idEv: uuidv4(), + date: date.toLocaleString(this.localDateCountry), + level: level, + typeEv: typeEv, + timestamp: timestamp, + message: message + } + ] + } + try { + // Add HTTP headers + if (headers) { + this.addHeadersToContextLog(log, headers) + if (!onlyContextHeader) { + this.addHeadersToLog(log.events[0], headers) + } + } + // Add extra information to log event + if (info) { + for (const key in info) { + log.events[0][key] = info[key] + } + } + // If exception error, add message and a portion of the stack trace + if (err) { + log.events[0]['exception'] = { + message: err.message, + stack: err.stack?.substring(0, this.maxErrorStackSize) + ' ...' + } + } + // If defined, add extra env fields + if (this.envLog) { + addEnvFieldLog(this.envLog, log) + } + } catch (e) { + log['error'] = 'Error while getting log event contextual info: ' + e.message + } + console.log(JSON.stringify(log)) + } else { + if (info) { + if (err) { + console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message, info, err) + } else { + console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message, info) + } + } else { + if (err) { + console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message, err) + } else { + console.log(date.toLocaleString(this.localDateCountry), level, typeEv, message) + } + } + } + } + + public static error( + typeEv: string, + source: string, + message: string, + headers = null, + info = null, + e = null + ) { + if ( + Logger.level == 'ERROR' || + Logger.level == 'WARN' || + Logger.level == 'INFO' || + Logger.level == 'DEBUG' + ) { + Logger.log('ERROR', typeEv, source + ': ' + message, headers, false, info, e) + } + } + + public static warn( + typeEv: string, + source: string, + message: string, + headers: any = null, + info: any = null, + e = null + ) { + if (Logger.level == 'WARN' || Logger.level == 'INFO' || Logger.level == 'DEBUG') { + Logger.log('WARN', typeEv, source + ': ' + message, headers, false, info, e) + } + } + + public static info( + typeEv: string, + source: string, + message: string, + headers: any = null, + info: any = null, + e = null + ) { + if (Logger.level == 'INFO' || Logger.level == 'DEBUG') { + Logger.log('INFO', typeEv, source + ': ' + message, headers, true, info, e) + } + } + + public static debug( + typeEv: string, + source: string, + message: string, + headers: any = null, + info: any = null, + e = null + ) { + if (Logger.level == 'DEBUG') { + Logger.log('DEBUG', typeEv, source + ': ' + message, headers, true, info, e) + } + } + + /** + * Log the onParse event + */ + public static onParse(headers: any) { + try { + if (this.isEventToLog(headers)) { + Logger.log('INFO', 'ON-PARSE', 'Request', headers, true) + } + } catch (e) { + Logger.error('LOGGER_ERROR', 'onParse logger', 'Error during log generation', null, e) + } + } + + /** + * Log the on end exec done event + */ + public static endExec(headers: any, result: any, duration: number, resultLogInfo: any) { + try { + if (this.isEventToLog(headers)) { + const info = { + result: InfoResult(result, this.maxStackLogSize, resultLogInfo), + duration: duration + } + Logger.log('INFO', 'endExecDone', 'Request', headers, true, info) + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'endExec logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + /** + * Log the on result process event + */ + public static onResultProcess(request: any, result: any, duration: number, resultLogInfo: any) { + const headers = request['headers'] + try { + if (this.isEventToLog(headers)) { + const info = { + result: InfoResult(result, this.maxStackLogSize, resultLogInfo), + duration: duration + } + Logger.log('INFO', 'onResultProcess', 'Result', headers, true, info) + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'onResponse logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + /** + * Log the onRequestParseDone event + */ + public static onRequestParseDone( + headers: any, + query: any, + operation: string, + variables: any, + duration: number + ) { + if (this.isEventToLog(headers)) { + const info = { + operation: operation, + query: query, + variables: variables, + parsingDuration: duration + } + Logger.log('INFO', 'requestParseDone', 'Request Parse', headers, true, info) + } + } + + /** + * Log the onResponse event when HTTP response returns + */ + public static onResponse(request: any, response: any, logResponseLevel: string) { + const headers = request['headers'] + try { + if (this.isEventToLog(headers)) { + // Calculate duration from request timestamp + const requestTimestampString: string = headers.get('requesttimestamp') + let requestTimestamp: number + if (requestTimestampString) { + requestTimestamp = parseInt(requestTimestampString) + } + const responseTimestamp = new Date().getTime() + const info = { + request: { + url: request.url, + method: request.method + }, + response: { + status: response.status, + contentLength: response.contentLength + }, + httpStatus: response.status, + duration: responseTimestamp - requestTimestamp + } + if (logResponseLevel != 'low') { + info.response['bodyExtract'] = extractBody(response.bodyInit, this.bodyMaxLogSize) + } + + Logger.log('INFO', 'onResponse', responseSummary(response.bodyInit), headers, true, info) + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'onResponse logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + public static introspection(headers, query) { + try { + const info = { + query: query + } + Logger.warn('WARN_INTROSPECTION', 'Introspection', 'Introspection query', headers, info) + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'introspection logger', + 'Error during log generation', + null, + null, + e + ) + } + } + + public static denyIntrospection(headers, info, message) { + try { + Logger.warn('DENY_INTROSPECTION', info, message, headers) + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'denyIntrospection logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + public static allowIntrospection(headers, info, message) { + try { + Logger.warn('ALLOW_INTROSPECTION', info, message, headers) + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'allowIntrospection logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + public static onRequest(request: any) { + const headersInit = request['headers']['headersInit'] + const headers = new Map() + + for (const header in headersInit) { + headers.set(header, headersInit[header]) + } + try { + if (this.isEventToLog(headers)) { + const info = { + url: request.url, + method: request.method + // body: request.body + } + Logger.log('INFO', 'onRequest', 'Request incoming', headers, false, info) + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'onRequest logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + public static onFetch( + request: any, + url: string, + httpStatus: string, + duration: number, + fetchInfo: any + ) { + try { + const headers = request['headers'] + const info = { + fetch: fetch, + duration: duration, + httpStatus: httpStatus, + url: url + } + Logger.log('INFO', 'onFetch', 'Fetch', headers, true, info) + } catch (e) { + Logger.error('LOGGER_ERROR', 'onFetch logger', 'Error during log generation', null, e) + } + } + + public static graphqlQuery(headers: any, params: any) { + try { + if (this.isEventToLog(headers)) { + const regex = / /gi + const queryToLog = { + query: params['query'].replace(regex, ''), + operationName: params['operationName'], + variables: params['variables'] + } + Logger.log('INFO', 'graphqlQuery', 'GraphQL Query', headers, true, queryToLog) + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'graphqlQuery logger', + 'Error during log generation', + headers, + null, + e + ) + } + } + + private static isEventToLog(headers): boolean { + if (this.skipHealthCheck && headers) { + if (headers.get(this.healthCheckHeaderName) == this.healthCheckHeaderValue) { + return false + } + } + return true + } + + private static addHeadersToContextLog(log: any, headers: any) { + try { + let headerMap = null + if (headers['_map']) { + headerMap = headers['_map'] + } else { + headerMap = headers + } + + if (headerMap && headerMap.get) { + if (this.logContextHeaders) { + for (const contextKey in this.logContextHeaders) { + const contextHeader = this.logContextHeaders[contextKey] + if (headerMap.get(contextHeader.header)) { + if (contextHeader.header.toLowerCase() == 'authorization') { + addLog(log, contextHeader.name, mask(headerMap.get('authorization'))) + } else { + addLog(log, contextHeader.name, headerMap.get(contextHeader.header)) + } + } + } + } + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'onHeadersToLog', + 'Error during headers log generation', + headers, + null, + e + ) + } + return log + } + + private static addHeadersToLog(log: any, headers: any) { + let headerMap = null + if (headers['_map']) { + headerMap = headers['_map'] + } else { + headerMap = headers + } + try { + if (headerMap) { + if (this.logHeaders) { + for (const logHeaderKey in this.logHeaders) { + const logHeader = this.logHeaders[logHeaderKey] + if (headerMap.get(logHeader.header)) { + if (logHeader.header.toLowerCase() == 'authorization') { + addLog(log, logHeader.name, mask(headerMap.get('authorization'))) + } else { + addLog(log, logHeader.name, headerMap.get(logHeader.header)) + } + } + } + } + } + } catch (e) { + Logger.error( + 'LOGGER_ERROR', + 'onHeadersToLog', + 'Error during headers log generation', + headers, + null, + e + ) + } + return log + } } function mask(stringToMask: string) { - if (stringToMask) { - return "*******************" + stringToMask.substring(22) - } - return null; + if (stringToMask) { + return '*******************' + stringToMask.substring(22) + } + return null } function InfoResult(result: any, maxStackLogSize: number, resultLogInfoLevel: string) { - let resultInfo = {} - let nbKeys = 0 - const maxKeys = 1 - const nbErrorsMaxToLog = 3 - if (result['errors']) { - resultInfo['nbErrors'] = result['errors'].length - if (resultLogInfoLevel != 'low') { - let nbErrors = 0 - resultInfo['errors'] = [] - for (const errorKey in result['errors']) { - const error = result['errors'][errorKey] - let logError = {} - if (error['message']) { - if (nbErrorsMaxToLog > nbErrors) { - logError['message'] = error['message'] - } - } - if (error['path']) { - logError['path'] = error['path'] - } - if (resultLogInfoLevel == 'high') { - // no stack trace and extension in low trace level - if (error['stack']) { - logError['stack'] = error['stack'].substring(0, maxStackLogSize) - } - if (error['extensions']) { - logError['extensions'] = error['extensions'] - } - } - resultInfo['errors'].push(logError) - } - } - } else { - resultInfo['nbErrors'] = 0 - } - if (result['data']) { - let keys = null - for (const key in result['data']) { - if (result['data'].hasOwnProperty(key)) { - if (keys == null) { - keys = key - } else { - if (nbKeys < maxKeys) { - keys = keys + ',' + key - } - } - nbKeys = nbKeys + 1 - } - } - resultInfo['dataFields'] = keys - } - return resultInfo + let resultInfo = {} + let nbKeys = 0 + const maxKeys = 1 + const nbErrorsMaxToLog = 3 + if (result['errors']) { + resultInfo['nbErrors'] = result['errors'].length + if (resultLogInfoLevel != 'low') { + let nbErrors = 0 + resultInfo['errors'] = [] + for (const errorKey in result['errors']) { + const error = result['errors'][errorKey] + let logError = {} + if (error['message']) { + if (nbErrorsMaxToLog > nbErrors) { + logError['message'] = error['message'] + } + } + if (error['path']) { + logError['path'] = error['path'] + } + if (resultLogInfoLevel == 'high') { + // No stack trace and extension in low trace level + if (error['stack']) { + logError['stack'] = error['stack'].substring(0, maxStackLogSize) + } + if (error['extensions']) { + logError['extensions'] = error['extensions'] + } + } + resultInfo['errors'].push(logError) + } + } + } else { + resultInfo['nbErrors'] = 0 + } + if (result['data']) { + let keys = null + for (const key in result['data']) { + if (result['data'].hasOwnProperty(key)) { + if (keys == null) { + keys = key + } else { + if (nbKeys < maxKeys) { + keys = keys + ',' + key + } + } + nbKeys = nbKeys + 1 + } + } + resultInfo['dataFields'] = keys + } + return resultInfo } + function extractBody(body: String, bodyMaxLogSize: number) { - if (body != null) { - return body.substring(0, bodyMaxLogSize) + " ... " - } else { - return "" - } + if (body != null) { + return body.substring(0, bodyMaxLogSize) + ' ... ' + } else { + return '' + } } + function responseSummary(body: String) { - if (body != null) { - return "response :" + body.substring(0, 100) + " ... " - } else { - return "response : empty" - } + if (body != null) { + return 'response: ' + body.substring(0, 100) + ' ... ' + } else { + return 'response: empty' + } } - /** - * Use to add some environment fields to log, like env.name, app.name ... - * ex : logEnvInfoField : string = "app=graphql,env.name=production,env.site=Paris" + * Used to add some environment fields to the log, like env.name, app.name, etc. + * Example: logEnvInfoField: string = "app=graphql,env.name=production,env.site=Paris" * -> log={ * app: "graphql", - * env: + * env: { * name: "production", - * site: "Paris", - * ... // logs field + * site: "Paris" + * }, + * ... // logs field */ function addEnvFieldLog(logEnvInfoField: string, log: any) { - - // split fields list witth dot serator - const fields: string[] = logEnvInfoField.split(",") - for (let idxField = 0; idxField < fields.length; idxField++) { - // split key, value - const kvField: string[] = fields[idxField].trim().split("=") - // split key in objects tree hierarchy - const levelField = kvField[0].trim().split(".") - let current = log - // create new object if does not exist for each level and set value for leaf level - for (let idxLevel = 0; idxLevel < levelField.length; idxLevel++) { - if (current[levelField[idxLevel]]) { - current = current[levelField[idxLevel]] - } else { - if (idxLevel < levelField.length - 1) { - current = current[levelField[idxLevel]] = {} - } else { - current[levelField[idxLevel]] = kvField[1] - } - } - } - } + // Split fields list with dot separator + const fields: string[] = logEnvInfoField.split(',') + for (let idxField = 0; idxField < fields.length; idxField++) { + // Split key, value + const kvField: string[] = fields[idxField].trim().split('=') + // Split key in objects tree hierarchy + const levelField = kvField[0].trim().split('.') + let current = log + // Create new object if it does not exist for each level and set value for leaf level + for (let idxLevel = 0; idxLevel < levelField.length; idxLevel++) { + if (current[levelField[idxLevel]]) { + current = current[levelField[idxLevel]] + } else { + if (idxLevel < levelField.length - 1) { + current = current[levelField[idxLevel]] = {} + } else { + current[levelField[idxLevel]] = kvField[1] + } + } + } + } } function addLog(log: any, key: string, value: any) { - - const levelField = key.split(".") - let current = log - // create new object if does not exist for each level and set value for leaf level - for (let idxLevel = 0; idxLevel < levelField.length; idxLevel++) { - if (current[levelField[idxLevel]]) { - current = current[levelField[idxLevel]] - } else { - if (idxLevel < levelField.length - 1) { - current = current[levelField[idxLevel]] = {} - } else { - current[levelField[idxLevel]] = value - } - } - } + const levelField = key.split('.') + let current = log + // Create new object if it does not exist for each level and set value for leaf level + for (let idxLevel = 0; idxLevel < levelField.length; idxLevel++) { + if (current[levelField[idxLevel]]) { + current = current[levelField[idxLevel]] + } else { + if (idxLevel < levelField.length - 1) { + current = current[levelField[idxLevel]] = {} + } else { + current[levelField[idxLevel]] = value + } + } + } } function defineLogHeaders(logHeaders: string) { - const headersList = [] - if (logHeaders) { - const headers = logHeaders.split(',') - - for (const headerKey in headers) { - const header = headers[headerKey] - const headerInfo = header.split('=') - headersList.push({ name: headerInfo[0], header: headerInfo[1] ? headerInfo[1] : headerInfo[0] }) - } - } - return headersList + const headersList = [] + if (logHeaders) { + const headers = logHeaders.split(',') + + for (const headerKey in headers) { + const header = headers[headerKey] + const headerInfo = header.split('=') + headersList.push({ + name: headerInfo[0], + header: headerInfo[1] ? headerInfo[1] : headerInfo[0] + }) + } + } + return headersList } - - - - - - diff --git a/packages/graphql-mesh/utils/parseYamlConfig.ts b/packages/graphql-mesh/utils/parseYamlConfig.ts index f4e606f..c0ac989 100644 --- a/packages/graphql-mesh/utils/parseYamlConfig.ts +++ b/packages/graphql-mesh/utils/parseYamlConfig.ts @@ -1,81 +1,86 @@ import { YamlConfig } from '@graphql-mesh/types' -//import { DefaultLogger } from '@graphql-mesh/utils' import { load } from 'js-yaml' import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { Logger } from '../utils/logger' - -//const logger = new DefaultLogger() - // Load the config.yaml file export const getConfig = (): YamlConfig.Config => { - const configFile = process.env['ConfigFile'] || 'config.yaml' - Logger.info('CONFIG', 'getConfig', 'Loading config file ' + configFile) - let config: YamlConfig.Config - - try { - const configPath = resolve(configFile) - config = load(readFileSync(configPath, { encoding: 'utf-8' })) - } catch (e) { - Logger.error('CONFIG', 'getConfig', "Failed loading config " + configFile, e) - throw new Error('FAiles laoding config file ' + configFile, e) - } + const configFile = process.env['ConfigFile'] || 'config.yaml' + Logger.info('CONFIG', 'getConfig', 'Loading config file ' + configFile) + let config: YamlConfig.Config - if (!config) { - Logger.error('CONFIG', 'getConfig', "No config loaded from " + configFile) - throw new Error('No configuration loaded from ' + configFile) - } + try { + const configPath = resolve(configFile) + config = load(readFileSync(configPath, { encoding: 'utf-8' })) + } catch (e) { + Logger.error('CONFIG', 'getConfig', 'Failed loading config ' + configFile, e) + throw new Error('Failed loading config file ' + configFile, e) + } - // if sources config is on a separate file define by SourcesConfigFile env var - const sourcesConfigFile = process.env['SourcesConfigFile'] - if (sourcesConfigFile) { - let sourcesConfig: YamlConfig.Config - Logger.info('CONFIG', 'getConfig', 'Loading sources config file ' + sourcesConfigFile) + if (!config) { + Logger.error('CONFIG', 'getConfig', 'No config loaded from ' + configFile) + throw new Error('No configuration loaded from ' + configFile) + } - try { - const sourcesConfigPath = resolve(sourcesConfigFile) - let file = readFileSync(sourcesConfigPath, { encoding: 'utf-8' }) - sourcesConfig = load(readFileSync(sourcesConfigPath, { encoding: 'utf-8' })) - Logger.debug('CONFIG', 'getConfig', 'sources loading from ' + sourcesConfigPath , null, file) - } catch (e) { - Logger.error('CONFIG', 'getConfig', "Failed loading sources Config " + sourcesConfigFile, null, null, e) - throw new Error('FAiles laoding sources config file ' + sourcesConfigFile, e) - } - if (sourcesConfig.sources) { - config['sources'] = sourcesConfig.sources - Logger.info('CONFIG', 'getConfig', 'sources Config file loaded successfully with ' + sourcesConfig.sources.length + " sources") - } else { - Logger.error('CONFIG', 'getConfig', 'sources Config file loaded successfully but without sources') - } - + // If sources config is in a separate file defined by SourcesConfigFile env var + const sourcesConfigFile = process.env['SourcesConfigFile'] + if (sourcesConfigFile) { + let sourcesConfig: YamlConfig.Config + Logger.info('CONFIG', 'getConfig', 'Loading sources config file ' + sourcesConfigFile) - } else { - if (!config.sources) { - Logger.error('CONFIG', 'getConfig', "No source defined in configuration file " + configFile) - throw new Error('No source defioned in configuration file ' + configFile) - } - } - return config + try { + const sourcesConfigPath = resolve(sourcesConfigFile) + let file = readFileSync(sourcesConfigPath, { encoding: 'utf-8' }) + sourcesConfig = load(file) + Logger.debug('CONFIG', 'getConfig', 'Sources loading from ' + sourcesConfigPath, null, file) + } catch (e) { + Logger.error( + 'CONFIG', + 'getConfig', + 'Failed loading sources config ' + sourcesConfigFile, + null, + null, + e + ) + throw new Error('Failed loading sources config file ' + sourcesConfigFile, e) + } + if (sourcesConfig.sources) { + config['sources'] = sourcesConfig.sources + Logger.info( + 'CONFIG', + 'getConfig', + 'Sources config file loaded successfully with ' + sourcesConfig.sources.length + ' sources' + ) + } else { + Logger.error('CONFIG', 'getConfig', 'Sources config file loaded successfully but without sources') + } + } else { + if (!config.sources) { + Logger.error('CONFIG', 'getConfig', 'No source defined in configuration file ' + configFile) + throw new Error('No source defined in configuration file ' + configFile) + } + } + return config } -// Get the endpoint of a specific openapi source -export const getSourceOpenapiEnpoint = ( - source: string, - config: YamlConfig.Config +// Get the endpoint of a specific OpenAPI source +export const getSourceOpenapiEndpoint = ( + source: string, + config: YamlConfig.Config ): string | undefined => { - const data = config.sources?.find((item) => source.includes(item.name)) - return data?.handler.openapi?.endpoint + const data = config.sources?.find((item) => source.includes(item.name)) + return data?.handler?.openapi?.endpoint } // Get the name of a specific source export const getSourceName = (source: string, config: YamlConfig.Config): string => { - const data = config.sources?.find((item) => source.includes(item.name)) - return data?.name + const data = config.sources?.find((item) => source.includes(item.name)) + return data?.name } // Get the list of transforms of a specific source export const getSourceTransforms = (source: string, config: YamlConfig.Config) => { - const data = config.sources?.find((item) => source.includes(item.name)) - return data?.transforms + const data = config.sources?.find((item) => source.includes(item.name)) + return data?.transforms } From 3303f98a14ee1a50c0846bafc516d5e6afa275d9 Mon Sep 17 00:00:00 2001 From: Adrien FIGARD Date: Mon, 16 Sep 2024 16:39:44 +0200 Subject: [PATCH 2/2] :pencil2: Fix typos --- packages/graphql-mesh/utils/configFromSwaggers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/graphql-mesh/utils/configFromSwaggers.ts b/packages/graphql-mesh/utils/configFromSwaggers.ts index a37110d..7ff1357 100755 --- a/packages/graphql-mesh/utils/configFromSwaggers.ts +++ b/packages/graphql-mesh/utils/configFromSwaggers.ts @@ -4,7 +4,7 @@ import { Catalog, Spec, ConfigExtension } from '../types' import { getConfig, getSourceName, - getSourceOpenapiEnpoint, + getSourceOpenapiEndpoint, getSourceTransforms } from './parseYamlConfig' import { mergeObjects } from './helpers' @@ -224,7 +224,7 @@ export default class ConfigFromSwaggers { handler: { openapi: { source, - endpoint: getSourceOpenapiEnpoint(source, this.config) || '{env.ENDPOINT}', + endpoint: getSourceOpenapiEndpoint(source, this.config) || '{env.ENDPOINT}', ignoreErrorResponses: true, operationHeaders: { Authorization: `{context.headers["authorization"]}`,