Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: pg span names #1306

Merged
merged 4 commits into from
Nov 30, 2022
Merged

fix: pg span names #1306

merged 4 commits into from
Nov 30, 2022

Conversation

ethanresnick
Copy link
Contributor

Which problem is this PR solving?

The primary functional change in this PR is to address a number of issues with how the pg instrumentation was generating span names.

  1. Before this PR, when the query being executed was a prepared statement with a name, the name was transformed first before it was put into the span's name. E.g., client.query({ name: 'find user', text: 'SELECT * from user where id = ?', values: [1] }) would generate a span name of pg.query:find, because the string 'find user' would be split on spaces and only the first word would be used. However, it's the full prepared statement name that constitutes the low cardinality identifier, so this commit now makes the span name: pg.query:find user.

  2. Similarly, before this PR, the parsed out operation name wasn't normalized before using it in the span name. Accordingly, a select * from x would get a span name of pg.query:select, while a SELECT * from x query would generate pg.query:SELECT. Now, they'll both have the latter span name.

  3. Previously, the generated span names did not include the DB name, although the examples in the otel spec recommend this. Now, the db name is included, as it's specified in the connection info.

There are also two commits prior to the commit that adjusts the span naming strategy. Those commits do not make any functional changes, but just refactor/DRY up the existing code, which allows the new span names to be constructed in only one place. They also make the logic a bit more defensive, so that various edge cases with invalid arguments (e.g., client.query(null) or client.query(queryText, valuesThatArentAnArray)) can no longer cause the instrumentation itself to fail with an uncaught exception (though errors raised synchronously or asynchronously from client.query are still propagated as before).

Short description of the changes

See each commit message and the overview above.

@ethanresnick ethanresnick requested a review from a team November 26, 2022 02:56
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Nov 26, 2022

CLA Signed

The committers listed above are authorized under a signed CLA.

@github-actions github-actions bot requested a review from rauno56 November 26, 2022 02:57
@ethanresnick ethanresnick changed the title Improve pg span names fix,refactor: pg span names Nov 26, 2022
@ethanresnick ethanresnick changed the title fix,refactor: pg span names fix: pg span names Nov 26, 2022
@ethanresnick ethanresnick force-pushed the main branch 3 times, most recently from 5e6f995 to 6d2dc50 Compare November 26, 2022 03:49
@codecov
Copy link

codecov bot commented Nov 28, 2022

Codecov Report

Merging #1306 (e3d7e5e) into main (092a250) will decrease coverage by 0.30%.
The diff coverage is 96.49%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1306      +/-   ##
==========================================
- Coverage   96.08%   95.77%   -0.31%     
==========================================
  Files          14       18       +4     
  Lines         893     1206     +313     
  Branches      191      255      +64     
==========================================
+ Hits          858     1155     +297     
- Misses         35       51      +16     
Impacted Files Coverage Δ
...elemetry-instrumentation-pg/src/instrumentation.ts 90.15% <95.83%> (ø)
...node/opentelemetry-instrumentation-pg/src/utils.ts 98.33% <96.96%> (ø)
...try-instrumentation-pg/src/enums/AttributeNames.ts 100.00% <0.00%> (ø)
...tapackages/auto-instrumentations-node/src/utils.ts 98.21% <0.00%> (ø)

@ethanresnick
Copy link
Contributor Author

@rauno56 Re the CI fail: I'm happy to add more tests first before this can be merged, but, before I take the time to do that, please let me know if the PR looks like it's on the right track and is something you think will be accepted. Thanks!

Copy link
Member

@blumamir blumamir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big like on these refactors and the work for improving the span name and error handling.
Added a few minor comments but overall I support these changes.

Your PR makes some changes with no update to existing tests, so I guess the current test coverage is not great. I Would be happy to see some tests to assert the new logic :)

@ethanresnick ethanresnick force-pushed the main branch 2 times, most recently from 1f619b9 to b491e1e Compare November 29, 2022 03:36
@ethanresnick
Copy link
Contributor Author

@blumamir Ok, I think I've addressed all your comments and have added some tests as well!

The prior code had three different utility functions for constructing
the span to use to trace the query: handleTextQuery, handleConfigQuery,
and handleParameterizedQuery. These functions contained a lot of
duplicated logic, and that duplication was gonna make it harder to
introduce new features (see next commit) and was already leading to
bugs/inconsistencies. For example, `handleConfigQuery` would verify that
the parameter `values` provided with the query were provided as an array
before attaching them to the span, whereas `handleParameterizedQuery`
would do so without this validation.

This commit instead normalizes the arguments to `client.query` first,
so that only function is needed to create the span. In the process of
normalizing the arguments, the new code also performs a bit more
validation on them, to make sure that the instrumentation will not throw
at runtime. For example, the prior code would've thrown on
`client.query(null)`, as it was checking `typeof args[0] === 'object'`
without excluding null. The prior code also assumed, if an object was
passed, that the `text` and `name` keys held a string; this is now
verified before attaching that data to the span.

Finally, the prior code had two different code paths for invoking the
original `client.query` method; one that went through
`handleInvalidQuery` and one directly in `_getClientQueryPatch`. The
former wrapped the call in a try-catch, while the latter did not. Now,
there's only one call to the original client.query, and it's always in
a try-catch, which ensures that other cases of invalid args passed to
client.query (which might lead it to throw synchronously) won't be an
issue.
BREAKING CHANGE. This improves the way that OTEL span names are
generated in two different ways.

First, if the query is a prepared statement with a `name`, the `name` is
put into the span name as-is. Before, the `name` was transformed first,
as though it were a full SQL query string (i.e., it was split on spaces
and only the first 'word' was used).

Second, when we do only have a full query string, and we take the first
word to form the span name, the code now calls `toUpperCase()` on that
string, so that a `select * from x` and a `SELECT * from x` query both
end up with a span name like `pg.query:SELECT`.
Copy link
Member

@blumamir blumamir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM

added 2 optional comments

@ethanresnick
Copy link
Contributor Author

@blumamir Thanks for the quick + detailed feedback! I added a couple more test cases per your comments. Is this good to merge now, or does it need a second reviewer?

@blumamir
Copy link
Member

@blumamir Thanks for the quick + detailed feedback! I added a couple more test cases per your comments. Is this good to merge now, or does it need a second reviewer?

Thanks again for the contribution and great improvements 🥇
This is good to merge as far as I am concerned. @rauno56 is the component owner - are you interested in adding a review?

@rauno56
Copy link
Member

rauno56 commented Nov 30, 2022

I don't want to be the blocker and don't have cycles to review it this week. Can merge if we have one pair of maintainer eyes seen and approved it.

@blumamir blumamir merged commit 8a375f5 into open-telemetry:main Nov 30, 2022
@dyladan dyladan mentioned this pull request Nov 30, 2022
@ethanresnick
Copy link
Contributor Author

Thanks @rauno56!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants