-
Notifications
You must be signed in to change notification settings - Fork 116
Dummy flag to reduce operations on non sampled traces #194
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic looks good. I would recommend you also add a reviewer who is more versed in Go than I am. :)
xray/segment.go
Outdated
logger.Debugf("Beginning segment named %s", name) | ||
|
||
cfg := GetRecorder(ctx) | ||
dummySeg.assignConfiguration(cfg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to pass the recorder in configuration for a DummySegment? The assignConfiguration
method does a bunch of comparisons which should be avoided if we don't really need the configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right.
xray/segment.go
Outdated
defer dummySeg.Unlock() | ||
|
||
dummySeg.Name = name | ||
dummySeg.TraceID = "dummy segment" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be an empty string or something more meaningful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to here and for dummy subsegment, actually in Java we create a new trace ID. Probably best to not risk some weird validation errors and do the same here.
xray/segment.go
Outdated
return context.WithValue(ctx, ContextKey, seg), seg | ||
} | ||
|
||
return BeginDummySegment(ctx, "Dummy Seg") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use full name as "DummySegment"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
xray/segment.go
Outdated
|
||
dummySubSeg.ParentSegment = parent.ParentSegment | ||
dummySubSeg.Name = name | ||
dummySubSeg.TraceID = "dummy subsegment" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
xray/segment.go
Outdated
return context.WithValue(ctx, ContextKey, seg), seg | ||
} | ||
|
||
return BeginDummySegment(ctx, "Dummy SubSeg") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use full name as "DummySubsegment"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dummy segment here does not stub out methods that it should to achieve performance savings. This is because the dummies are still instances of real segments, and will thus invoke their real methods. Furthermore, since the dummy (sub)segments are not begun until the end of the conventional beginSegment
/beginSubsegment
functions, it actually takes longer to begin a dummy instance.
I think the design here could include making the segment struct in segment_model
an interface instead. This would allow us to more closely follow the implementation in the Java SDK, where such interfaces made implementing dummy (sub)segments much easier.
There will be differences between the two SDKs because the dummy subsegment is never actually used in the Java SDK, but I think that could be an area the Go SDK improves upon.
xray/segment.go
Outdated
defer dummySeg.Unlock() | ||
|
||
dummySeg.Name = name | ||
dummySeg.TraceID = "dummy segment" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to here and for dummy subsegment, actually in Java we create a new trace ID. Probably best to not risk some weird validation errors and do the same here.
xray/segment.go
Outdated
func BeginDummySegment(ctx context.Context, name string) (context.Context, *Segment) { | ||
dummySeg := &Segment{parent: nil} | ||
dummySeg.ParentSegment = dummySeg | ||
logger.Debugf("Beginning segment named %s", name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should read Beginning dummy segment named %s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good pick
xray/segment.go
Outdated
seg.Unlock() | ||
} | ||
|
||
// Begin DummySubSegment creates a in the case of no sampling to reduce memory footprint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Fix typo in comments
xray/segment.go
Outdated
} | ||
|
||
dummySubSeg := &Segment{parent: parent} | ||
logger.Debugf("Beginning subsegment named %s", name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: dummy subsegment
xray/segment.go
Outdated
return context.WithValue(ctx, ContextKey, seg), seg | ||
} | ||
|
||
return BeginDummySegment(ctx, "Dummy SubSeg") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
xray/segment.go
Outdated
return context.WithValue(ctx, ContextKey, seg), seg | ||
} | ||
|
||
return BeginDummySegment(ctx, "Dummy Seg") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
xray/segment.go
Outdated
return context.WithValue(ctx, ContextKey, seg), seg | ||
} | ||
|
||
return BeginDummySegment(ctx, "DummySegment") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the Segment is dummy, adding annotation and metadata should be no-op to save the memory footprint.
|
||
// AddAnnotation allows adding an annotation to the segment. | ||
func (seg *Segment) AddAnnotation(key string, value interface{}) error { | ||
seg.Lock() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we lock and unlock before checking dummy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because we don't want any data race on segment struct. so it's a good idea to lock the struct before accessing it.
xray/segment.go
Outdated
seg.InProgress = true | ||
|
||
// check whether segment is dummy or not based on sampling decision | ||
seg.isDummy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we fail faster by putting this immediately after seg.ParentSegment = parent.ParentSegment
? We don't bother keeping the footprint in the parent segment as we won't send it out anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. we can put this right after seg.ParentSegment = parent.ParentSegment.
xray/segment.go
Outdated
} | ||
|
||
// check the segment is dummy segment or not | ||
func (seg *Segment) isDummy() *Segment { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method seems not necessary. It is only called at 2 places when begin a segment or subsegment. Customer doesn't need to call it as well. I'd suggest replacing the caller code with
if !seg.ParentSegment.Sampled
seg.Dummy = true
BTW The method name is confusing. isXYZ()
should returns a boolean. Now the return type is never used (see the github warn below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good suggestion!
xray/segment.go
Outdated
defer seg.Unlock() | ||
|
||
// If segment is dummy we return | ||
if seg.Dummy { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At creating segment we dealt with the segment children membership no matter dummy or not. If we return early here, would skipping the following code cause mem leak? i.e. it will always be "in progress" and the parent always keep the reference of it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be semantic
Issue #, if available:
Description of changes:
Added support for creating DummySegment and DummySubSegments.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.