Skip to content

Commit b765cc9

Browse files
feat: simplify tables compare (#78)
1 parent 31073dd commit b765cc9

File tree

4 files changed

+58
-56
lines changed

4 files changed

+58
-56
lines changed

package-lock.json

Lines changed: 1 addition & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/expect-opentelemetry/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@
3838
"@opentelemetry/semantic-conventions": "^1.10.1",
3939
"@traceloop/otel-proto": "^0.7.0",
4040
"axios": "^1.3.4",
41-
"deep-equal": "^2.2.0",
42-
"node-sql-parser": "^4.7.0"
41+
"deep-equal": "^2.2.0"
4342
},
4443
"devDependencies": {
4544
"@types/deep-equal": "^1.0.1",

packages/expect-opentelemetry/src/matchers/utils/filters.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,30 @@ import { opentelemetry } from '@traceloop/otel-proto';
22
import { objectCompare, stringCompare } from './comparators';
33
import { CompareOptions } from './compare-types';
44

5+
export const extractAttributeStringValues = (
6+
spans: opentelemetry.proto.trace.v1.ISpan[],
7+
attribute: string,
8+
) => {
9+
return spans
10+
.map((span) => {
11+
return span.attributes?.find(
12+
(attribute: opentelemetry.proto.common.v1.IKeyValue) =>
13+
attribute.key === attribute,
14+
)?.value?.stringValue;
15+
})
16+
.filter((statement) => !!statement) as string[];
17+
};
18+
519
export const filterByAttributeKey = (
620
spans: opentelemetry.proto.trace.v1.ISpan[],
721
attName: string,
822
) =>
923
spans.filter((span) => {
10-
return span.attributes?.find((attribute) => {
11-
return attribute.key === attName;
12-
});
24+
return span.attributes?.find(
25+
(attribute: opentelemetry.proto.common.v1.IKeyValue) => {
26+
return attribute.key === attName;
27+
},
28+
);
1329
});
1430

1531
export const filterBySpanKind = (
@@ -38,7 +54,7 @@ export const filterByAttributeIntValue = (
3854
) =>
3955
spans.filter((span) => {
4056
return span.attributes?.find(
41-
(attribute) =>
57+
(attribute: opentelemetry.proto.common.v1.IKeyValue) =>
4258
attribute.key === attName &&
4359
attribute.value?.intValue.toNumber() === attValue,
4460
);

packages/expect-opentelemetry/src/resources/postgresql-query.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
22
import { opentelemetry } from '@traceloop/otel-proto';
3-
import { Parser } from 'node-sql-parser';
43
import {
54
CompareOptions,
5+
extractAttributeStringValues,
66
filterByAttributeStringValue,
77
} from '../matchers/utils';
88

9+
const tablesRegex = /(from|join|into|update|alter)\s+(?<table>\S+)/gi;
10+
911
export class PostgreSQLQuery {
1012
constructor(
1113
readonly spans: opentelemetry.proto.trace.v1.ISpan[],
1214
private readonly serviceName: string,
13-
private parser = new Parser(),
1415
) {}
1516

1617
withDatabaseName(name: string | RegExp, options?: CompareOptions) {
@@ -40,7 +41,12 @@ export class PostgreSQLQuery {
4041

4142
if (filteredSpans.length === 0) {
4243
throw new Error(
43-
`No query by ${this.serviceName} to postgresql with statement ${statement} was found`,
44+
`No query by ${
45+
this.serviceName
46+
} to postgresql with statement ${statement} was found. Found statements: ${extractAttributeStringValues(
47+
this.spans,
48+
SemanticAttributes.DB_STATEMENT,
49+
)}`,
4450
);
4551
}
4652

@@ -50,7 +56,8 @@ export class PostgreSQLQuery {
5056
withOperations(...operations: string[]) {
5157
const filteredSpans = this.spans.filter((span) => {
5258
const statement = span.attributes?.find(
53-
(attribute) => attribute.key === SemanticAttributes.DB_STATEMENT,
59+
(attribute: opentelemetry.proto.common.v1.IKeyValue) =>
60+
attribute.key === SemanticAttributes.DB_STATEMENT,
5461
)?.value?.stringValue;
5562

5663
if (!statement) {
@@ -66,7 +73,12 @@ export class PostgreSQLQuery {
6673

6774
if (filteredSpans.length === 0) {
6875
throw new Error(
69-
`No query by ${this.serviceName} to postgresql with operations ${operations} was found`,
76+
`No query by ${
77+
this.serviceName
78+
} to postgresql with operations ${operations} was found. Found statements: ${extractAttributeStringValues(
79+
this.spans,
80+
SemanticAttributes.DB_STATEMENT,
81+
)}`,
7082
);
7183
}
7284

@@ -76,32 +88,41 @@ export class PostgreSQLQuery {
7688
withTables(...tables: string[]) {
7789
const filteredSpans = this.spans.filter((span) => {
7890
const statement = span.attributes?.find(
79-
(attribute) => attribute.key === SemanticAttributes.DB_STATEMENT,
91+
(attribute: opentelemetry.proto.common.v1.IKeyValue) =>
92+
attribute.key === SemanticAttributes.DB_STATEMENT,
8093
)?.value?.stringValue;
8194

8295
if (!statement) {
8396
return false;
8497
}
8598

86-
const allTablesInStatement = this.parser
87-
.tableList(prepareQuery(statement), { database: 'PostgresQL' })
88-
.map((table) => table.split('::')[2].trim());
99+
const matches = statement.match(tablesRegex);
100+
const cleaned = matches?.map((elem: string) => {
101+
const [_, second] = elem.split(' ');
102+
return second
103+
.replace('"', '')
104+
.replace('(', '')
105+
.replace(')', '')
106+
.replace('\n', '')
107+
.toLocaleLowerCase();
108+
});
89109

90110
return tables.every((table) =>
91-
allTablesInStatement.includes(table.toLowerCase()),
111+
cleaned?.includes(table.toLocaleLowerCase()),
92112
);
93113
});
94114

95115
if (filteredSpans.length === 0) {
96116
throw new Error(
97-
`No query by ${this.serviceName} to postgresql with tables ${tables} was found`,
117+
`No query by ${
118+
this.serviceName
119+
} to postgresql with tables ${tables} was found. Found statements: ${extractAttributeStringValues(
120+
this.spans,
121+
SemanticAttributes.DB_STATEMENT,
122+
)}`,
98123
);
99124
}
100125

101126
return new PostgreSQLQuery(filteredSpans, this.serviceName);
102127
}
103128
}
104-
105-
const prepareQuery = (
106-
query: string, // remove double quotes and replace %s with 111
107-
) => query.replace(/"/g, '').replace(/%s/g, '111').toLocaleLowerCase();

0 commit comments

Comments
 (0)