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

OpenTelemetry for launcher #1215

Merged
merged 31 commits into from
Jun 12, 2023
Merged

Conversation

RebeccaMahany
Copy link
Contributor

@RebeccaMahany RebeccaMahany commented May 31, 2023

Adds traces to a couple locations in launcher, as well as an optional exporter using OTLP over HTTP. These changes work out-of-the-box with the Jaeger all-in-one container documented here. Adds a command-line flag to disable exporting traces.

Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

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

I love it, but I want to noodle on the function signatures

pkg/osquery/tables/tablehelpers/exec.go Outdated Show resolved Hide resolved
pkg/traces/traces.go Outdated Show resolved Hide resolved
Comment on lines 52 to 54
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, span := traces.New(r.Context())
defer span.End()
Copy link
Contributor

Choose a reason for hiding this comment

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

This is an interesting question... I don't know if we should add spans to kryptoEcMiddleware.Wrap vs wrapping with a span middleware. Thoughts?

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 thought it was helpful this way because it gives us more specific timing info for the kryptoEcMiddleware, which would've been helpful in the past. We do already effectively wrap the entire localhost handler with the span middleware -- we use otelhttp.NewHandler to wrap all our other handlers. So we have an outer span for the initial request, a child span for the kryptoEcMiddleware, and then a final child span for the request handling (e.g. control server acceleration or whatever we're doing).

Copy link
Contributor

Choose a reason for hiding this comment

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

That's a good point -- maybe we don't usually want to instrument a span, but this one might be special.

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'm not sure I get the original point -- with the exception of the otelhttp wrapper, I'm mostly manually instrumenting spans here. Is that something we don't want?

Copy link
Contributor

Choose a reason for hiding this comment

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

There were a couple aspects to the original comment, but I'm not sure they're germane.

Foremost, my point is about how if we want to instrument the entire span, we'd be better off doing it in middleware. Though you're correct that otelhttp.NewHandler is already that middleware.

The secondary point is that if we're instrumenting the span with otelhttp.NewHandler, then immediately starting a subspan isn't going to be meaningful. It should be the same timing period. If there are smaller parts we want to trace it makes sense, but this looks like:

trace1{
  trace2{
    stuff
  }
}

So I don't see it adding much

Copy link
Contributor

Choose a reason for hiding this comment

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

Though I see that you need the span to add in the error. But I wonder if SpanFromContext is a better fit.

Basically, why add the span? Does it help any?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In general I like more child spans because they help us narrow down causes of performance issues. E.g. here, if we have a localserver request that we see take a long time, we can use the multiple child spans to identify if it's the krypto middleware that's taking a while, or the inner request to e.g. accelerate the control server interval. Without the child spans, all we have is one span that tells us it takes a certain amount of time for the request to be processed and a response to be returned, which isn't really more info than what we've got in the browser dev console.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right. But only if there are those inner spans. So why wrap the whole function, vs just the blocks you want? There's an extra span here

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 suppose I find it a little easier to view? All the spans I care about for troubleshooting one particular code path, grouped into one trace. And I appreciate when tracing/logging is done in a consistent way.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we're talking past each other. But we can point at a screen with real data and iterate later

ee/localserver/krypto-ec-middleware.go Show resolved Hide resolved
ee/localserver/request-controlservice.go Outdated Show resolved Hide resolved
ee/localserver/request-id.go Outdated Show resolved Hide resolved
ee/localserver/server.go Show resolved Hide resolved
Comment on lines 84 to 85
func (t *execTableV2) generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
ctx, span := traces.New(ctx, trace.WithAttributes(attribute.String(traces.AttributeName("dataflattentable", "table_name"), t.tableName)))
Copy link
Contributor

Choose a reason for hiding this comment

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

I want to add spans to the generate, but I think we should be doing it at a different level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Where do you have in mind?

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably the osquery-go SDK, or even thrift.

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 imagine we'll come back to that idea a little later?

pkg/traces/exporter/exporter.go Show resolved Hide resolved
@RebeccaMahany RebeccaMahany marked this pull request as ready for review June 5, 2023 20:26
Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

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

I'm not sure I can follow the exporter, but this seems about right.

I think we can add some sugar around adding errors. trace.AddErrorToCtx(ctx, err) and trace.AddErrorToSpan(span, err)`maybe? But we could kick that forward.

ee/localserver/request-id.go Outdated Show resolved Hide resolved
go.mod Show resolved Hide resolved
pkg/agent/knapsack/knapsack.go Show resolved Hide resolved
pkg/traces/traces.go Outdated Show resolved Hide resolved
func buildAttributes(callerFile string, keyVals ...interface{}) []attribute.KeyValue {
callerDir := defaultAttributeNamespace
if callerFile != "" {
callerDir = filepath.Base(filepath.Dir(callerFile))
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know what this value is -- is the path separator going to vary by platform?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's the closest I got to getting the package name -- e.g. when the caller is ee/localserver/request-controlservice.go, this will be localserver. I can document this better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment to make this clearer

Copy link
Contributor

Choose a reason for hiding this comment

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

On windows, are the paths / or \? (I'm never sure, since it's oddly inconsistent. windows paths are, of course \, but sometimes the internal go paths are /)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh sorry, I didn't realize I'd missed that part of the question -- let me confirm.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Forward slash also -- so no, path separator will not vary by platform.

Screenshot 2023-06-09 122315

Copy link
Contributor

Choose a reason for hiding this comment

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

Then it'll need path not filepath and a comment.

pkg/traces/traces.go Outdated Show resolved Hide resolved
pkg/traces/traces.go Show resolved Hide resolved
directionless
directionless previously approved these changes Jun 8, 2023
Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

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

I'd say fix the typecasts, and it's a solid base to iterate with

pkg/traces/traces.go Outdated Show resolved Hide resolved
pkg/traces/traces.go Outdated Show resolved Hide resolved
seejdev
seejdev previously approved these changes Jun 12, 2023
Copy link
Contributor

@seejdev seejdev left a comment

Choose a reason for hiding this comment

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

Seems like a solid starting point! Great job!

James-Pickett
James-Pickett previously approved these changes Jun 12, 2023
Copy link
Contributor

@James-Pickett James-Pickett left a comment

Choose a reason for hiding this comment

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

awesome work!

pkg/traces/exporter/exporter.go Outdated Show resolved Hide resolved
pkg/traces/traces.go Outdated Show resolved Hide resolved
@RebeccaMahany RebeccaMahany dismissed stale reviews from James-Pickett and seejdev via 24288af June 12, 2023 16:07
@RebeccaMahany RebeccaMahany merged commit f5ef9b6 into kolide:main Jun 12, 2023
@RebeccaMahany RebeccaMahany deleted the becca/opentelemetry branch June 12, 2023 16:33
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.

4 participants