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

Add support for "Start" utility methods #16

Merged
merged 8 commits into from
Apr 21, 2024

Conversation

trixnz
Copy link
Contributor

@trixnz trixnz commented Apr 19, 2024

Fixes #7.

Replaces the list of names and packages for the Start span functions with a list of regex patterns that may be extended using the -extra-start-span-signatures command line option.

The format is <regex>:<telemetry-type>. Ideally this would just be a list of regex patterns, but we need to know what telemetry library we're matching against so we don't run RecordError on opencensus.

I've tested this on our rather large code base, and was pleased to see many new lints that we had previously missed after moving to a utility method.

This is a great lint check, thank you!

trixnz added 2 commits April 20, 2024 00:20
Replaces the hardcoded list of function names and packages with a list
of regex patterns that may be extended using the
`-extra-start-span-signatures` command line option.

The format is `<regex>:<telemetry-type>`. Ideally this would just be a
list of regex patterns, but we need to know what telemetry library we're
matching so we don't run RecordError on opencensus.
The tests need to unconditionally include the
DefaultStartSpanSignatures, which was not possible with the old harness.

Instead of returning an object directly, they now return a function to
prepare a config, which ensures they all start out with the default
config as a base.
@jjti
Copy link
Owner

jjti commented Apr 19, 2024

Thank you a ton, @trixnz! I've been feeling guilty about not having found the time to implement this... I'll review and merge ASAP (tomorrow AM)

@coveralls
Copy link

coveralls commented Apr 21, 2024

Pull Request Test Coverage Report for Build 8774843807

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 62 of 82 (75.61%) changed or added relevant lines in 2 files are covered.
  • 3 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-3.3%) to 83.942%

Changes Missing Coverage Covered Lines Changed/Added Lines %
spancheck.go 33 34 97.06%
config.go 29 48 60.42%
Files with Coverage Reduction New Missed Lines %
spancheck.go 3 87.5%
Totals Coverage Status
Change from base Build 8105344262: -3.3%
Covered Lines: 345
Relevant Lines: 411

💛 - Coveralls

Copy link
Owner

@jjti jjti left a comment

Choose a reason for hiding this comment

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

@trixnz this looks dope. I added a couple tests and found a couple things that I had to change which I called out below. Let me know what you think of those changes.

Two other things I wanted to bring up:

  • are there any other tests you're aware of that we should throw into testdata/enableall/enable_all.go?
  • do you want to take a stab at documenting this new setting in the README? Up to you, I can in a follow up if you'd prefer

@@ -225,11 +235,16 @@ func getID(node ast.Node) *ast.Ident {
case *ast.ValueSpec:
if len(stmt.Names) > 1 {
return stmt.Names[1]
} else if len(stmt.Names) == 1 {
Copy link
Owner

@jjti jjti Apr 21, 2024

Choose a reason for hiding this comment

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

right now I'm hard-coding the index of the span to get its ID. For the existing libraries, it was as simple as grabbing the second var (since that's the case for all the funcs being tested from opencensus and otel). For these new/custom func signatures, we don't know which index the returned span is. What I did here is the quickest dirtiest fix, to grab the span's ID assuming it's the only return value (if only one var is being assigned). So this works with funcs like I use in the test:

func startTrace() trace.Span {
  ...
}

If would be better to walk thru the stmts and find whatever var is of a span type... (supporting more arbitrary custom span start functions)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, potential for future robustness work here!

"go.opentelemetry.io/otel/trace"
)

func TestStartTrace() trace.Span {
Copy link
Owner

Choose a reason for hiding this comment

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

this is another limitation I found with the existing implementation of spancheck's isSpanStartfunc. It will only work with SelectorExpr which means the span starting utility functions need to be in a package different from the one being linted. To test that in this function I just made a new /util package. But isSpanStart should probably be updated to also allow for utility funcs within the same package.

func isSpanStart(info *types.Info, n ast.Node, startSpanMatchers []spanStartMatcher) (spanType, bool) {
	sel, ok := n.(*ast.SelectorExpr)
	if !ok {
		return spanUnset, false
	}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did notice this, I agree - it might miss a few calls in places where the tracing packages themselves are misbehaving with spans.

spancheck.go Outdated
@@ -84,6 +88,11 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) {
funcScope = pass.TypesInfo.Scopes[v.Type]
case *ast.FuncDecl:
funcScope = pass.TypesInfo.Scopes[v.Type]

// Skip checking spans in this function if it's a custom starter/creator.
if config.startSpanMatchersCustomRegex != nil && config.startSpanMatchersCustomRegex.MatchString(v.Name.Name) {
Copy link
Owner

Choose a reason for hiding this comment

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

this is another hack/workaround I had to throw in. Without it, we'll get linting exceptions for the func that defines the spans. Like the function below (just a quick example from memory, not exact) would get a linting error because it itself is in violation of the other rules like calling .End() on spans

func startSpan() trace.Span { // 
  _, span := otel.StartTrace()
  return span
} // return reached without calling span.SetStatus

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice one! We can remove a few nolint from our codebase :). I updated your check to match the regex against the full function signature, rather than just the function name itself, as that might unintentionally hide lints from functions with the same name as utility methods.

trixnz added 2 commits April 21, 2024 19:22
Instead of checking if the function name matches, which might result in
overzealous exclusions, prefer to match against the function signature
itself
@trixnz
Copy link
Contributor Author

trixnz commented Apr 21, 2024

@trixnz this looks dope. I added a couple tests and found a couple things that I had to change which I called out below. Let me know what you think of those changes.

Two other things I wanted to bring up:

  • are there any other tests you're aware of that we should throw into testdata/enableall/enable_all.go?
  • do you want to take a stab at documenting this new setting in the README? Up to you, I can in a follow up if you'd prefer

Looks good to me! I took a pass at documentation, let me know what you think 😄

@jjti jjti merged commit 34d21b4 into jjti:main Apr 21, 2024
2 of 3 checks passed
@jjti
Copy link
Owner

jjti commented Apr 21, 2024

Just merged @trixnz! I'll need to make a follow-up to golangci-lint to get that YAML config thing in. I also added a shout out in the README for your help. Thank you again! Please lmk if this works for you (or not and we can patch it)

@trixnz
Copy link
Contributor Author

trixnz commented Apr 21, 2024

How gracious, thanks! 😄 Looks great on my end, I appreciate the suggestions and how quick you were to land this. Once again, great idea for a tool - love it!

@trixnz trixnz deleted the feat/add-start-span-matchers branch April 21, 2024 19:32
@Crocmagnon
Copy link

Thanks!

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.

Support "start" utility functions
4 participants