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 WithStatus option to set Span status at the same time (#1677) #1817

Closed
wants to merge 13 commits into from

Conversation

lastchiliarch
Copy link
Contributor

Add WithStatus event option to set Span status at the same time, see #1677.
Signed-off-by: lastchiliarch [email protected]

@codecov
Copy link

codecov bot commented Apr 17, 2021

Codecov Report

Merging #1817 (68fc2eb) into main (d20e722) will increase coverage by 0.0%.
The diff coverage is 80.0%.

Impacted file tree graph

@@          Coverage Diff          @@
##            main   #1817   +/-   ##
=====================================
  Coverage   79.2%   79.2%           
=====================================
  Files        139     139           
  Lines       7459    7476   +17     
=====================================
+ Hits        5908    5926   +18     
  Misses      1304    1304           
+ Partials     247     246    -1     
Impacted Files Coverage Δ
bridge/opentracing/internal/mock.go 72.9% <0.0%> (-0.7%) ⬇️
trace/noop.go 57.1% <0.0%> (ø)
trace/trace.go 86.7% <ø> (ø)
oteltest/span.go 100.0% <100.0%> (ø)
sdk/trace/span.go 89.1% <100.0%> (+0.1%) ⬆️
trace/config.go 69.7% <100.0%> (+9.1%) ⬆️
sdk/trace/batch_span_processor.go 87.1% <0.0%> (+1.5%) ⬆️

@lastchiliarch lastchiliarch force-pushed the issue1677 branch 2 times, most recently from 5d238e8 to 5ae2893 Compare April 17, 2021 12:49
Copy link
Member

@XSAM XSAM left a comment

Choose a reason for hiding this comment

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

Looks good overall.

sdk/trace/trace_test.go Outdated Show resolved Hide resolved
sdk/trace/span.go Outdated Show resolved Hide resolved
trace/config_test.go Outdated Show resolved Hide resolved
CHANGELOG.md Outdated
@@ -141,6 +141,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Added

- Added `WithStatus` event option to set Span status at the same time when call RecordError. (#1677)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Added `WithStatus` event option to set Span status at the same time when call RecordError. (#1677)
- Added `WithStatus` event option to set Span status when passed to `RecordError`. (#1817)

Comment on lines 248 to 250
// This method does not change the Span status in default
// To change Span status, pass `WithStatus` as options.
// This method does nothing If this span is not being recorded or err is nil.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// This method does not change the Span status in default
// To change Span status, pass `WithStatus` as options.
// This method does nothing If this span is not being recorded or err is nil.
// This method does not change the Span status by default.
// To set the Span status, pass `WithStatus` as an option.
// This method does nothing if this span is not being recorded or err is nil.

trace/config.go Outdated
func (o withStatusSpanOption) apply(c *SpanConfig) { c.WithStatus = bool(o) }

// WithStatus set the status at the same time when RecordError
func WithStatus(o bool) LifeCycleOption {
Copy link
Contributor

Choose a reason for hiding this comment

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

Having this return a LifeCycleOption means that the life-cycle methods of the span will accept this. I'm not sure we do or don't want to do this. IIRC the specification might state that we cannot set the status in these methods, you'll need to double check that. If we do, the life-cycle methods will need to be updated to set the status when they receive this option.

Additionally, having this accept a boolean as an argument doesn't seem that useful. Why not accept a code and message for the status to set?

Copy link
Member

Choose a reason for hiding this comment

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

Additionally, having this accept a boolean as an argument doesn't seem that useful. Why not accept a code and message for the status to set?

I would second that, this at the minimum should accept a code and message as the span status concept has room to grow beyond the current tri-state values.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure about this either. WithStatusdoesn't seems to be an EventOption, it does not change or affect an Event. It is only applicable to the RecordError method.

For example, using span.AddEvent("some event", trace.WithStatus()) is syntactically correct but does nothing.

I would prefer if we create another method to record an error with status or create an ErrorOption that wraps an EventOptions, for example:

span.RecordErrorStatus(err, code, "description", EventOptions..)

or

span.RecordError(err, trace.WithErrorStatus(code, "description"), trace.WithEventOpts(EventOptions..))

Copy link
Contributor

Choose a reason for hiding this comment

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

I like the creation of the ErrorOption approach. I could see there being many more things we want to pass here (we talked about maybe an option that would signal the stacktrace needed to be recorded).

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

@lastchiliarch lastchiliarch Apr 21, 2021

Choose a reason for hiding this comment

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

ErrorOption sounds good. I will use ErrorOption to replace WithStatusOption.
Thanks very much.

…rrorOption (open-telemetry#1677)

* Change signature of the Span `RecordError, replace EventOption by ErrorOption
* Add WithEventOpts, WithErrorStatus
* Set status when WithErrorStatus is passed to RecordError

Signed-off-by: lastchiliarch <[email protected]>
Copy link
Member

@Aneurysm9 Aneurysm9 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 really like to avoid the extra WithEventOptions() wrapper.

@@ -255,11 +255,13 @@ func (s *MockSpan) RecordError(err error, opts ...trace.EventOption) {
}

s.SetStatus(codes.Error, "")
Copy link
Member

Choose a reason for hiding this comment

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

This probably shouldn't be setting the status here. Looks like maybe it was missed in the removal of that functionality.

CHANGELOG.md Outdated
@@ -212,6 +212,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Changed

- Changed signature of the Span `RecordError` , replace EventOption by ErrorOption
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
- Changed signature of the Span `RecordError` , replace EventOption by ErrorOption
- Changed signature of the Span `RecordError`, replace EventOption with ErrorOption. (#1817)

Comment on lines 248 to 250
// This method does not change the Span status in default
// To set the Span status, pass `WithErrorStatus` as an option.
// This method does nothing If this span is not being recorded or err is nil.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// This method does not change the Span status in default
// To set the Span status, pass `WithErrorStatus` as an option.
// This method does nothing If this span is not being recorded or err is nil.
// This method does not change the Span status by default
// To set the Span status pass a `WithErrorStatus(status)` option.
// This method does nothing if this span is not being recorded or if err is nil.

trace/config.go Outdated
Comment on lines 230 to 232
for _, option := range options {
option.ApplyError(c)
}
Copy link
Member

Choose a reason for hiding this comment

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

I'd like to avoid the need to use WithEventOpts() when calling RecordError(). My first thought was that maybe something like this would work:

   for _, option := range options {
   	if evopt, ok := option.(EventOption); ok {
   		c.EventOpts = append(c.EventOpts, option)
   	} else {
   		option.ApplyError(c)
   	}
   }

But I don't think it does since the method signature now requires ErrorOptions to be passed instead of EventOptions. So, my next thought is could the relevant EventOption implementations gain an ErrorOption implementation that looks something like this:

func (o someOptionType) ApplyError(c *ErrorConfig) {
	c.EventOpts = append(c.EventOpts, o)
}

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 don't like the wrap either, I had tried this way to make it work before the wrap.

But it can't work, beacuse the compile complains about the type mismatch.
Error message:
Cannot use 'trace.WithTimestamp(errTime)' (type LifeCycleOption) as the type ErrorOption Type does not implement
'ErrorOption' as some methods are missing: ApplyError(config *ErrorConfig)

Code looks like this:

config:
 type timestampSpanOption time.Time

func (o timestampSpanOption) ApplySpan(c *SpanConfig)  { o.apply(c) }
func (o timestampSpanOption) ApplyEvent(c *SpanConfig) { o.apply(c) }
func (o timestampSpanOption) ApplyError(c *ErrorConfig) {c.Timestamp = time.Time(o)}
func (timestampSpanOption) private()                   {}
func (o timestampSpanOption) apply(c *SpanConfig)      { c.Timestamp = time.Time(o) }



client code:
span.RecordError(s.err, trace.WithTimestamp(errTime))


RecordError:

func (s *span) RecordError(err error, options ...trace.ErrorOption) {
	if s == nil || err == nil || !s.IsRecording() {
		return
	}
	c := trace.NewErrorConfig(options...)
	if c.Code != codes.Unset {
		s.SetStatus(c.Code, c.Message)
	}

	var eventOpts []trace.EventOption
	for _, option := range options {
		if option, ok := option.(trace.EventOption); ok {
			eventOpts = append(eventOpts, option)
		}
	}
	eventOpts = append(eventOpts, trace.WithAttributes(
		semconv.ExceptionTypeKey.String(typeStr(err)),
		semconv.ExceptionMessageKey.String(err.Error()),
	))
	s.addEvent(semconv.ExceptionEventName, eventOpts...)
}

I don't think it's a good idea to make LifeCycleOption implements ErrorOption.

If you know any idea, that will be a great help, I'd like to remove the wrap.

Copy link
Contributor

Choose a reason for hiding this comment

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

trace/config.go Outdated
func (eventOptsErrorOption) private() {}

// WithEventOpts set event options, will be passed to addEvent
func WithEventOpts(option ...EventOption) ErrorOption {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
func WithEventOpts(option ...EventOption) ErrorOption {
func WithEventOptions(option ...EventOption) ErrorOption {

If we can't get rid of this I'd like it to not use an abbreviated name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks very much.

trace/trace.go Outdated
Comment on lines 519 to 521
// This method does not change the Span status by default.
// To set the Span status, pass `WithErrorStatus` as an option.
// This method does nothing if this span is not being recorded or err is nil.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// This method does not change the Span status by default.
// To set the Span status, pass `WithErrorStatus` as an option.
// This method does nothing if this span is not being recorded or err is nil.
// This method does not change the Span status by default
// To set the Span status pass a `WithErrorStatus(status)` option.
// This method does nothing if this span is not being recorded or if err is nil.

…rrorOption (open-telemetry#1677)

* Change signature of the Span `RecordError, replace EventOption by ErrorOption
* Add WithEventOpts, WithErrorStatus
* Set status when WithErrorStatus is passed to RecordError

Signed-off-by: lastchiliarch <[email protected]>
trace/config.go Outdated

// ErrorOption applies an option to a ErrorConfig.
type ErrorOption interface {
ApplyError(config *ErrorConfig)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ApplyError(config *ErrorConfig)
applyError(config *errorConfig)

We're working on normalizing configuration and options and part of that will involve making the config type and apply methods unexported. Can we get out ahead of that 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.

Sure. I had renamed ApplyError to applyError.
But golangci-lint will fail if I changed ErrorConfig to errorConfig.

exported func NewErrorConfig returns unexported type *go.opentelemetry.io/otel/trace.errorConfig, which can be annoying to us.

Copy link
Member

Choose a reason for hiding this comment

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

newErrorConfig shouldn't need to be exported, either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since newErrorConfig will be used in by bridge/opentracing/internal/mock.go , oteltest/span.go and sdk/trace/span.go, it will take a lot of work to make it unexported at this time.

I think it's better to move all the code which implements Span interface to the package trace, so we can easily make the config unexported.

But there is another problem, since sdk/trace/span.go needs some code in sdk/trace/internal, we must change it at the same time.

I'm not sure about this solution, it will cause a lot of files to be changed.

Maybe we can keep NewErrorConfig exported and make a new pr to make it unexported, I'd like to take it.

Comment on lines +220 to +224

// A private method to prevent users implementing the
// interface and so future additions to it will not
// violate compatibility.
private()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// A private method to prevent users implementing the
// interface and so future additions to it will not
// violate compatibility.
private()

This is no longer necessary since the applyError() method is unexported.

// than this method does nothing.
func (s *span) RecordError(err error, opts ...trace.EventOption) {
// RecordError will record err as a span event for this span.
// This method does not change the Span status by default
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// This method does not change the Span status by default
// This method does not change the Span status by default.

@@ -203,3 +205,56 @@ func (i instrumentationVersionOption) ApplyTracer(config *TracerConfig) {
}

func (instrumentationVersionOption) private() {}

// ErrorConfig is a group of options for error.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// ErrorConfig is a group of options for error.
// ErrorConfig is a group of options for error events.

}
func (statusErrorOption) private() {}

// WithErrorStatus set the error code and message when code is not codes.Unset
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// WithErrorStatus set the error code and message when code is not codes.Unset
// WithErrorStatus set the error code and message when code is not codes.Unset.

// span is not being recorded or err is nil than this method does nothing.
RecordError(err error, options ...EventOption)
// RecordError will record err as an exception span event for this span.
// This method does not change the Span status by default
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// This method does not change the Span status by default
// This method does not change the Span status by default.

trace/config.go Outdated
Comment on lines 230 to 232
for _, option := range options {
option.ApplyError(c)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

@MrAlias
Copy link
Contributor

MrAlias commented Jun 8, 2021

Closing as HEAD has progressed far enough this will likely need to be re-evaluated.

@MrAlias MrAlias closed this Jun 8, 2021
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.

5 participants