-
Notifications
You must be signed in to change notification settings - Fork 327
Conversation
@rakyll @Ramonza, would you give me some hints? I'm getting the following AppVeyor build error which claims gcc compiler missing: runtime/cgo |
trace/tracestate.go
Outdated
// TraceState is a tracing-system specific context in a list of key-value pairs. | ||
// TraceState allows different vendors propagate additional information and | ||
// inter-operate with their legacy Id formats. | ||
type Tracestate struct { |
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 is this not just a map?
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 order of key-value pairs is important, see:
https://w3c.github.io/distributed-tracing/trace_context/HTTP_HEADER_FORMAT_RATIONALE.html#ordering-of-keys-in-tracestate
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.
@Ramonza - @basvanbeek is right, the W3C spec requires tracestate to following a special ordering rule - last modified key-value-pair should appear at the very beginning.
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.
trace/tracestate.go
Outdated
VALUE_FORMAT = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]` | ||
) | ||
|
||
var KEY_VALIDATION_RE = regexp.MustCompile(`^(` + KEY_FORMAT + `)$`) |
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.
Go convention for variables is camelCase
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.
Got it, I'm fixing it.
trace/tracestate.go
Outdated
) | ||
|
||
const ( | ||
KEY_WITHOUT_VENDOR_FORMAT = `[a-z][_0-9a-z\-\*\/]{0,255}` |
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.
Go convention for consts is camelCase - I think golint will pick this up
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.
Sure, I'd be glad to change to camelCase.
I did searched the entire repo to see if there is a convention I could follow, and I'm seeing inconsistent conventions. And golint is not part of CI validation (all I see is gofmt). e.g.
In stats/validation.go, we have
const (
MaxNameLength = 255
)
in vendor\git.apache.org\thrift.git\lib\go\thrift\application_exception.go (although this is 3rd party dependency), we have
const (
UNKNOWN_APPLICATION_EXCEPTION = 0
UNKNOWN_METHOD = 1
INVALID_MESSAGE_TYPE_EXCEPTION = 2
WRONG_METHOD_NAME = 3
BAD_SEQUENCE_ID = 4
MISSING_RESULT = 5
INTERNAL_ERROR = 6
PROTOCOL_ERROR = 7
)
trace/trace.go
Outdated
@@ -289,6 +295,14 @@ func (s *Span) SpanContext() SpanContext { | |||
return s.spanContext | |||
} | |||
|
|||
// Tracestate returns the Tracestate of the span context. | |||
func (s *Span) Tracestate() *Tracestate { |
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 isn't this a method on SpanContext?
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.
@Ramonza, I'll move this to SpanContext.
return ts.Set(key, "") | ||
} | ||
|
||
func (ts *Tracestate) Set(key string, value string) string { |
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.
I don't think we should make any part of SpanContext mutable. Can we make Tracestate immutable for now? I think we can figure out how to make it possible to change the Tracestate in a subsequent PR - I think the focus of this initial work should just be on correct propagation.
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.
Sure, we can take the step-by-step approach.
To provide more context, census-instrumentation/opencensus-specs#70 (comment) and census-instrumentation/opencensus-specs#131.
Also adding @wu-sheng for awareness.
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.
@Ramonza, I've commented out the Tracestate.Remove and Tracestate.Set for now.
Regarding SpanContext, I'm putting a pointer to Tracestate rather than a hardy copy for Tracestate as we would want to have COW (copy-on-write) Tracestate in the future for performance, taking a hard copy is too expensive.
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.
Would you mind removing them entirely for now? We in general never keep around commented code.
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.
Sure, I'll remove it.
trace/tracestate.go
Outdated
VALUE_VALIDATION_RE.MatchString(ts.value) | ||
} | ||
|
||
// TraceState is a tracing-system specific context in a list of key-value pairs. |
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.
Inconsistent capitalization
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.
Will fix.
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.
Some further comments. I think we need more test coverage. I would also ideally like to see somewhere where we actually propagate Tracestate. It's most important that we correctly propagate it for now I think so that we don't break the chain of propagation.
return ts.Set(key, "") | ||
} | ||
|
||
func (ts *Tracestate) Set(key string, value string) string { |
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.
Would you mind removing them entirely for now? We in general never keep around commented code.
return true | ||
} | ||
|
||
func (ts *Tracestate) Fork() *Tracestate { |
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.
I think we should remove this method as well. It only makes sense if Tracestate is mutable.
*/ | ||
|
||
func (ts *Tracestate) String() string { | ||
return fmt.Sprintf("tracestate%s", ts.entries) |
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.
I don't think this will be a useful output for String() - I would recommend just removing the method
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.
Alternatively, I think it would be reasonable for String()
to produce a Tracestate header value in the format from the spec.
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.
Please refer to census-instrumentation/opencensus-python#238 (comment) where we agreed to separate the in-process representation and the actual HTTP header format.
@@ -510,6 +520,7 @@ func TestSetSpanStatus(t *testing.T) { | |||
TraceID: tid, | |||
SpanID: SpanID{}, | |||
TraceOptions: 0x1, | |||
Tracestate: &Tracestate{}, |
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 zero value of *Tracestate
(nil
) should be a valid empty Tracestate in the spirit of making the zero value useful. So it should not be necessary to set it here.
} | ||
|
||
func (ts *Tracestate) Get(key string) string { | ||
for _, entry := range ts.entries { |
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.
To make the zero value of *Tracestate
useful, let's add
if ts == nil {
return ""
}
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.
Should this method distinguish between an empty string value and the absence of a key? If so, perhaps it should return (string, bool)
?
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.
Empty string means the key doesn't exist, as the W3C spec wouldn't allow empty string as the value.
} | ||
|
||
func (ts *TracestateEntry) IsValid() bool { | ||
return keyValidationRegExp.MatchString(ts.key) && |
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 an empty key valid? Is an empty value? It seems from the pattern that it is. Should it be? Ideally we would have a test for this.
@Ramonza, agree, that's what I've mentioned in the PR description "My next pull request will implement the ochttp integration, which will propagate tracestate in HTTP headers.", I will add the actual propagation and the test cases in the next PR. |
I would prefer to have it in one PR because I don't think just this alone makes sense on its own -- it doesn't add any functionality and I'm worried that if users see it they will be confused as to why its there. |
I am going to look into the AppVeyor failure, it is unrelated. |
This is the initial implementation of W3C tracestate in Go.
This is my first time writing program in Go, couple notes/questions: