From 9f137c3b1456b66b092bc8122d3f44269d5eda95 Mon Sep 17 00:00:00 2001 From: danstarns Date: Mon, 29 Apr 2024 20:57:11 +0700 Subject: [PATCH 1/2] fix: json the operation vs query string in span attributes --- packages/opentelemetry/src/extract-spans.ts | 7 ++++--- packages/opentelemetry/src/info-to-attributes.ts | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/opentelemetry/src/extract-spans.ts b/packages/opentelemetry/src/extract-spans.ts index bfe31bd8..02fcd9d2 100644 --- a/packages/opentelemetry/src/extract-spans.ts +++ b/packages/opentelemetry/src/extract-spans.ts @@ -4,7 +4,7 @@ import { ResourceSpans, } from "@graphql-debugger/types"; -import { parse, print } from "graphql"; +import { print } from "graphql"; import { attributesToObject } from "./attributes-to-object"; import { debug } from "./debug"; @@ -46,8 +46,9 @@ export function extractSpans({ const document = attributes[AttributeNames.DOCUMENT]; if (document) { try { - const parsed = parse(document); - const printed = print(parsed); + const astString = document; + const ast = JSON.parse(astString); + const printed = print(ast); graphqlDocument = printed; } catch (error) { debug("Error parsing document", error); diff --git a/packages/opentelemetry/src/info-to-attributes.ts b/packages/opentelemetry/src/info-to-attributes.ts index f62019d7..0173bbbf 100644 --- a/packages/opentelemetry/src/info-to-attributes.ts +++ b/packages/opentelemetry/src/info-to-attributes.ts @@ -1,7 +1,7 @@ import { AttributeNames } from "@graphql-debugger/types"; import { isGraphQLInfoRoot } from "@graphql-debugger/utils"; -import { GraphQLResolveInfo, print } from "graphql"; +import { GraphQLResolveInfo } from "graphql"; export function infoToAttributes({ info, @@ -21,8 +21,7 @@ export function infoToAttributes({ ...(isRoot ? { [AttributeNames.OPERATION_ROOT]: true, - // Note - [AttributeNames.DOCUMENT]: print(info.operation), + [AttributeNames.DOCUMENT]: JSON.stringify(info.operation), [AttributeNames.OPERATION_TYPE]: info.operation.operation.toLowerCase(), ...(info.operation.name?.value From 8b468ade30a3f7859afbfdc284e42a49ecae3be6 Mon Sep 17 00:00:00 2001 From: danstarns Date: Mon, 29 Apr 2024 21:22:54 +0700 Subject: [PATCH 2/2] test: fix --- .../tests/foreign-traces.test.ts | 12 ++- .../tests/plugin-express.test.ts | 12 ++- .../collector-proxy/tests/post-traces.test.ts | 12 ++- .../opentelemetry/tests/extract-spans.test.ts | 46 ++++----- packages/trace-directive/tests/trace.test.ts | 93 ++++++++++++++----- 5 files changed, 121 insertions(+), 54 deletions(-) diff --git a/apps/collector-proxy/tests/foreign-traces.test.ts b/apps/collector-proxy/tests/foreign-traces.test.ts index d5b327c1..ad943e8a 100644 --- a/apps/collector-proxy/tests/foreign-traces.test.ts +++ b/apps/collector-proxy/tests/foreign-traces.test.ts @@ -27,13 +27,17 @@ describe("foreign traces", () => { const schemaHash = faker.string.alpha(6); - const document = /* GraphQL */ ` + const documentAst = parse(/* GraphQL */ ` query { users { name } } - `; + `); + + const printedDocument = print(documentAst); + + const jsonDocument = JSON.stringify(documentAst); const payload: PostTraces["body"] = { resourceSpans: [ @@ -64,7 +68,7 @@ describe("foreign traces", () => { { key: AttributeNames.DOCUMENT, value: { - stringValue: document, + stringValue: jsonDocument, }, }, { @@ -231,7 +235,7 @@ describe("foreign traces", () => { const rootSpan = traceGroup?.spans.find((span) => span.isGraphQLRootSpan); expect(rootSpan).toBeDefined(); expect(rootSpan?.name).toEqual("query users"); - expect(rootSpan?.graphqlDocument).toEqual(print(parse(document))); + expect(rootSpan?.graphqlDocument).toEqual(printedDocument); const foreignSpans = traceGroup?.spans.filter( (span) => span.isForeign === true, diff --git a/apps/collector-proxy/tests/plugin-express.test.ts b/apps/collector-proxy/tests/plugin-express.test.ts index d8682c2e..d1ba84f4 100644 --- a/apps/collector-proxy/tests/plugin-express.test.ts +++ b/apps/collector-proxy/tests/plugin-express.test.ts @@ -24,13 +24,17 @@ describe("plugin express", () => { const schemaHash = faker.string.alpha(6); - const document = /* GraphQL */ ` + const documentAst = parse(/* GraphQL */ ` query { users { name } } - `; + `); + + const printedDocument = print(documentAst); + + const jsonDocument = JSON.stringify(documentAst); const expressScopeSpan: ResourceSpans["scopeSpans"][0] = { scope: knownScope, @@ -105,7 +109,7 @@ describe("plugin express", () => { { key: AttributeNames.DOCUMENT, value: { - stringValue: document, + stringValue: jsonDocument, }, }, { @@ -202,7 +206,7 @@ describe("plugin express", () => { const rootSpan = traceGroup?.spans.find((span) => span.isGraphQLRootSpan); expect(rootSpan).toBeDefined(); expect(rootSpan?.name).toEqual("query users"); - expect(rootSpan?.graphqlDocument).toEqual(print(parse(document))); + expect(rootSpan?.graphqlDocument).toEqual(printedDocument); const nameSpan = traceGroup?.spans.find( (span) => span.name === "User name", diff --git a/apps/collector-proxy/tests/post-traces.test.ts b/apps/collector-proxy/tests/post-traces.test.ts index 637d529d..2e674c0e 100644 --- a/apps/collector-proxy/tests/post-traces.test.ts +++ b/apps/collector-proxy/tests/post-traces.test.ts @@ -66,7 +66,7 @@ describe("POST /v1/traces", () => { const schemaHash = faker.string.alpha(6); - const document = /* GraphQL */ ` + const documentAst = /* GraphQL */ parse(` query { users { name @@ -80,7 +80,11 @@ describe("POST /v1/traces", () => { } } } - `; + `); + + const printedDocument = print(documentAst); + + const jsonDocument = JSON.stringify(documentAst); const payload: PostTraces["body"] = { resourceSpans: [ @@ -111,7 +115,7 @@ describe("POST /v1/traces", () => { { key: AttributeNames.DOCUMENT, value: { - stringValue: document, + stringValue: jsonDocument, }, }, { @@ -367,6 +371,6 @@ describe("POST /v1/traces", () => { const rootSpan = traceGroup?.spans.find((span) => span.isGraphQLRootSpan); expect(rootSpan).toBeDefined(); expect(rootSpan?.name).toEqual("query users"); - expect(rootSpan?.graphqlDocument).toEqual(print(parse(document))); + expect(rootSpan?.graphqlDocument).toEqual(printedDocument); }); }); diff --git a/packages/opentelemetry/tests/extract-spans.test.ts b/packages/opentelemetry/tests/extract-spans.test.ts index 9df16718..7d99503f 100644 --- a/packages/opentelemetry/tests/extract-spans.test.ts +++ b/packages/opentelemetry/tests/extract-spans.test.ts @@ -11,16 +11,18 @@ describe("extractSpans", () => { test("should extract data from spans", () => { const schemaHash = faker.string.alpha(6); - const document = print( - parse(/* GraphQL */ ` - { - users(where: { name: "bob" }) { - name - errorField - } + const docAst = parse(/* GraphQL */ ` + { + users(where: { name: "bob" }) { + name + errorField } - `), - ); + } + `); + + const printedDocument = print(docAst); + + const jsonDocument = JSON.stringify(docAst); const error = new Error("something went wrong"); @@ -57,7 +59,7 @@ describe("extractSpans", () => { { key: AttributeNames.DOCUMENT, value: { - stringValue: document, + stringValue: jsonDocument, }, }, { @@ -197,7 +199,7 @@ describe("extractSpans", () => { resourceSpans[0].scopeSpans[0].spans[0].endTimeUnixNano, ).toString(), graphqlSchemaHash: schemaHash, - graphqlDocument: document, + graphqlDocument: printedDocument, errorMessage: undefined, errorStack: undefined, isForeign: false, @@ -258,15 +260,17 @@ describe("extractSpans", () => { test("should extract data from foreign spans", () => { const schemaHash = faker.string.alpha(6); - const document = print( - parse(/* GraphQL */ ` - { - users { - name - } + const docAst = parse(/* GraphQL */ ` + { + users { + name } - `), - ); + } + `); + + const printedDocument = print(docAst); + + const jsonDocument = JSON.stringify(docAst); const knownScope: ResourceSpans["scopeSpans"][0]["scope"] = { name: TRACER_NAME, @@ -305,7 +309,7 @@ describe("extractSpans", () => { { key: AttributeNames.DOCUMENT, value: { - stringValue: document, + stringValue: jsonDocument, }, }, { @@ -456,7 +460,7 @@ describe("extractSpans", () => { ).toString(), isForeign: false, graphqlSchemaHash: schemaHash, - graphqlDocument: "{\n users {\n name\n }\n}", + graphqlDocument: printedDocument, parentSpanId: undefined, errorMessage: undefined, errorStack: undefined, diff --git a/packages/trace-directive/tests/trace.test.ts b/packages/trace-directive/tests/trace.test.ts index 97dced4a..65a594f8 100644 --- a/packages/trace-directive/tests/trace.test.ts +++ b/packages/trace-directive/tests/trace.test.ts @@ -193,9 +193,17 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("query users"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); + expect(spanTree.span.attributes[AttributeNames.OPERATION_NAME]).toMatch( "users", ); @@ -305,9 +313,16 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("mutation createUser"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); const postsSpan = spanTree.children.find( (child) => child.span.name === "User posts", @@ -372,9 +387,16 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("query users"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); const events = spanTree.span.events; @@ -478,9 +500,17 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("query users"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); + expect( spanTree.span.attributes[AttributeNames.OPERATION_RETURN_TYPE], ).toMatch("[User]"); @@ -541,9 +571,16 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("query user"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); const nameSpan = spanTree.children.find( (child) => child.span.name === "User name", @@ -604,9 +641,16 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("query user"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); const result = spanTree.span.attributes[AttributeNames.SCHEMA_HASH]; @@ -665,8 +709,15 @@ describe("@trace directive", () => { const spanTree = buildSpanTree({ span: rootSpan, children: [] }, spans); expect(spanTree.span.name).toEqual("query hello"); - expect(spanTree.span.attributes[AttributeNames.DOCUMENT]).toMatch( - print(parse(query)), - ); + + const astString = spanTree.span.attributes[ + AttributeNames.DOCUMENT + ] as string; + if (!astString) { + throw new Error("astString is undefined"); + } + + const ast = JSON.parse(astString); + expect(print(ast)).toMatch(print(parse(query))); }); });