From 370f06cb469be2cd6e4f57d9420fc0f7f7847341 Mon Sep 17 00:00:00 2001 From: bodymindarts Date: Sat, 30 Oct 2021 23:01:03 +0200 Subject: [PATCH] fix: adding nested input variables in graphql plugin GraphQL inputs are frequently nested like: { "input": { "value1": 1, "value2": 2 } } Currently this would result the following call: span.setAttribute("input", Object({ value1: 1, value2: 2})) But since SpanAttribute doesn't accept an Object type it silently fails and doesn't add the attribute at all. This commit goes depth-first into the nested structure and adds each variable with the appropriate path. --- .../src/instrumentation.ts | 5 ++--- .../src/utils.ts | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts index c4f0bc69df..e33c7cebee 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts @@ -43,6 +43,7 @@ import { Maybe, } from './types'; import { + addInputVariableAttributes, addSpanSource, endSpan, getOperation, @@ -419,9 +420,7 @@ export class GraphQLInstrumentation extends InstrumentationBase { } if (processedArgs.variableValues && config.allowValues) { - Object.entries(processedArgs.variableValues).forEach(([key, value]) => { - span.setAttribute(`${AttributeNames.VARIABLES}${String(key)}`, value); - }); + addInputVariableAttributes(span, processedArgs.variableValues); } return span; diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts index 930dd11dbb..cdafc018fb 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts @@ -32,6 +32,28 @@ import { const OPERATION_VALUES = Object.values(AllowedOperationTypes); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function addInputVariableAttribute(span: api.Span, key: string, variable: any) { + if (Array.isArray(variable)) { + variable.forEach((value, idx) => { + addInputVariableAttribute(span, `${key}.${idx}`, value); + }); + } else if (variable instanceof Object) { + Object.entries(variable).forEach(([nestedKey, value]) => { + addInputVariableAttribute(span, `${key}.${nestedKey}`, value); + }); + } else { + span.setAttribute(`${AttributeNames.VARIABLES}${String(key)}`, variable); + } +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function addInputVariableAttributes(span: api.Span, variableValues: { [key: string]: any }) { + Object.entries(variableValues).forEach(([key, value]) => { + addInputVariableAttribute(span, key, value); + }); +} + export function addSpanSource( span: api.Span, loc?: graphqlTypes.Location,