trace.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // Copyright The OpenTelemetry Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package trace // import "go.opentelemetry.io/otel/trace"
  15. import (
  16. "bytes"
  17. "context"
  18. "encoding/hex"
  19. "encoding/json"
  20. "go.opentelemetry.io/otel/attribute"
  21. "go.opentelemetry.io/otel/codes"
  22. )
  23. const (
  24. // FlagsSampled is a bitmask with the sampled bit set. A SpanContext
  25. // with the sampling bit set means the span is sampled.
  26. FlagsSampled = TraceFlags(0x01)
  27. errInvalidHexID errorConst = "trace-id and span-id can only contain [0-9a-f] characters, all lowercase"
  28. errInvalidTraceIDLength errorConst = "hex encoded trace-id must have length equals to 32"
  29. errNilTraceID errorConst = "trace-id can't be all zero"
  30. errInvalidSpanIDLength errorConst = "hex encoded span-id must have length equals to 16"
  31. errNilSpanID errorConst = "span-id can't be all zero"
  32. )
  33. type errorConst string
  34. func (e errorConst) Error() string {
  35. return string(e)
  36. }
  37. // TraceID is a unique identity of a trace.
  38. // nolint:revive // revive complains about stutter of `trace.TraceID`.
  39. type TraceID [16]byte
  40. var nilTraceID TraceID
  41. var _ json.Marshaler = nilTraceID
  42. // IsValid checks whether the trace TraceID is valid. A valid trace ID does
  43. // not consist of zeros only.
  44. func (t TraceID) IsValid() bool {
  45. return !bytes.Equal(t[:], nilTraceID[:])
  46. }
  47. // MarshalJSON implements a custom marshal function to encode TraceID
  48. // as a hex string.
  49. func (t TraceID) MarshalJSON() ([]byte, error) {
  50. return json.Marshal(t.String())
  51. }
  52. // String returns the hex string representation form of a TraceID
  53. func (t TraceID) String() string {
  54. return hex.EncodeToString(t[:])
  55. }
  56. // SpanID is a unique identity of a span in a trace.
  57. type SpanID [8]byte
  58. var nilSpanID SpanID
  59. var _ json.Marshaler = nilSpanID
  60. // IsValid checks whether the SpanID is valid. A valid SpanID does not consist
  61. // of zeros only.
  62. func (s SpanID) IsValid() bool {
  63. return !bytes.Equal(s[:], nilSpanID[:])
  64. }
  65. // MarshalJSON implements a custom marshal function to encode SpanID
  66. // as a hex string.
  67. func (s SpanID) MarshalJSON() ([]byte, error) {
  68. return json.Marshal(s.String())
  69. }
  70. // String returns the hex string representation form of a SpanID
  71. func (s SpanID) String() string {
  72. return hex.EncodeToString(s[:])
  73. }
  74. // TraceIDFromHex returns a TraceID from a hex string if it is compliant with
  75. // the W3C trace-context specification. See more at
  76. // https://www.w3.org/TR/trace-context/#trace-id
  77. // nolint:revive // revive complains about stutter of `trace.TraceIDFromHex`.
  78. func TraceIDFromHex(h string) (TraceID, error) {
  79. t := TraceID{}
  80. if len(h) != 32 {
  81. return t, errInvalidTraceIDLength
  82. }
  83. if err := decodeHex(h, t[:]); err != nil {
  84. return t, err
  85. }
  86. if !t.IsValid() {
  87. return t, errNilTraceID
  88. }
  89. return t, nil
  90. }
  91. // SpanIDFromHex returns a SpanID from a hex string if it is compliant
  92. // with the w3c trace-context specification.
  93. // See more at https://www.w3.org/TR/trace-context/#parent-id
  94. func SpanIDFromHex(h string) (SpanID, error) {
  95. s := SpanID{}
  96. if len(h) != 16 {
  97. return s, errInvalidSpanIDLength
  98. }
  99. if err := decodeHex(h, s[:]); err != nil {
  100. return s, err
  101. }
  102. if !s.IsValid() {
  103. return s, errNilSpanID
  104. }
  105. return s, nil
  106. }
  107. func decodeHex(h string, b []byte) error {
  108. for _, r := range h {
  109. switch {
  110. case 'a' <= r && r <= 'f':
  111. continue
  112. case '0' <= r && r <= '9':
  113. continue
  114. default:
  115. return errInvalidHexID
  116. }
  117. }
  118. decoded, err := hex.DecodeString(h)
  119. if err != nil {
  120. return err
  121. }
  122. copy(b, decoded)
  123. return nil
  124. }
  125. // TraceFlags contains flags that can be set on a SpanContext
  126. type TraceFlags byte //nolint:revive // revive complains about stutter of `trace.TraceFlags`.
  127. // IsSampled returns if the sampling bit is set in the TraceFlags.
  128. func (tf TraceFlags) IsSampled() bool {
  129. return tf&FlagsSampled == FlagsSampled
  130. }
  131. // WithSampled sets the sampling bit in a new copy of the TraceFlags.
  132. func (tf TraceFlags) WithSampled(sampled bool) TraceFlags {
  133. if sampled {
  134. return tf | FlagsSampled
  135. }
  136. return tf &^ FlagsSampled
  137. }
  138. // MarshalJSON implements a custom marshal function to encode TraceFlags
  139. // as a hex string.
  140. func (tf TraceFlags) MarshalJSON() ([]byte, error) {
  141. return json.Marshal(tf.String())
  142. }
  143. // String returns the hex string representation form of TraceFlags
  144. func (tf TraceFlags) String() string {
  145. return hex.EncodeToString([]byte{byte(tf)}[:])
  146. }
  147. // SpanContextConfig contains mutable fields usable for constructing
  148. // an immutable SpanContext.
  149. type SpanContextConfig struct {
  150. TraceID TraceID
  151. SpanID SpanID
  152. TraceFlags TraceFlags
  153. TraceState TraceState
  154. Remote bool
  155. }
  156. // NewSpanContext constructs a SpanContext using values from the provided
  157. // SpanContextConfig.
  158. func NewSpanContext(config SpanContextConfig) SpanContext {
  159. return SpanContext{
  160. traceID: config.TraceID,
  161. spanID: config.SpanID,
  162. traceFlags: config.TraceFlags,
  163. traceState: config.TraceState,
  164. remote: config.Remote,
  165. }
  166. }
  167. // SpanContext contains identifying trace information about a Span.
  168. type SpanContext struct {
  169. traceID TraceID
  170. spanID SpanID
  171. traceFlags TraceFlags
  172. traceState TraceState
  173. remote bool
  174. }
  175. var _ json.Marshaler = SpanContext{}
  176. // IsValid returns if the SpanContext is valid. A valid span context has a
  177. // valid TraceID and SpanID.
  178. func (sc SpanContext) IsValid() bool {
  179. return sc.HasTraceID() && sc.HasSpanID()
  180. }
  181. // IsRemote indicates whether the SpanContext represents a remotely-created Span.
  182. func (sc SpanContext) IsRemote() bool {
  183. return sc.remote
  184. }
  185. // WithRemote returns a copy of sc with the Remote property set to remote.
  186. func (sc SpanContext) WithRemote(remote bool) SpanContext {
  187. return SpanContext{
  188. traceID: sc.traceID,
  189. spanID: sc.spanID,
  190. traceFlags: sc.traceFlags,
  191. traceState: sc.traceState,
  192. remote: remote,
  193. }
  194. }
  195. // TraceID returns the TraceID from the SpanContext.
  196. func (sc SpanContext) TraceID() TraceID {
  197. return sc.traceID
  198. }
  199. // HasTraceID checks if the SpanContext has a valid TraceID.
  200. func (sc SpanContext) HasTraceID() bool {
  201. return sc.traceID.IsValid()
  202. }
  203. // WithTraceID returns a new SpanContext with the TraceID replaced.
  204. func (sc SpanContext) WithTraceID(traceID TraceID) SpanContext {
  205. return SpanContext{
  206. traceID: traceID,
  207. spanID: sc.spanID,
  208. traceFlags: sc.traceFlags,
  209. traceState: sc.traceState,
  210. remote: sc.remote,
  211. }
  212. }
  213. // SpanID returns the SpanID from the SpanContext.
  214. func (sc SpanContext) SpanID() SpanID {
  215. return sc.spanID
  216. }
  217. // HasSpanID checks if the SpanContext has a valid SpanID.
  218. func (sc SpanContext) HasSpanID() bool {
  219. return sc.spanID.IsValid()
  220. }
  221. // WithSpanID returns a new SpanContext with the SpanID replaced.
  222. func (sc SpanContext) WithSpanID(spanID SpanID) SpanContext {
  223. return SpanContext{
  224. traceID: sc.traceID,
  225. spanID: spanID,
  226. traceFlags: sc.traceFlags,
  227. traceState: sc.traceState,
  228. remote: sc.remote,
  229. }
  230. }
  231. // TraceFlags returns the flags from the SpanContext.
  232. func (sc SpanContext) TraceFlags() TraceFlags {
  233. return sc.traceFlags
  234. }
  235. // IsSampled returns if the sampling bit is set in the SpanContext's TraceFlags.
  236. func (sc SpanContext) IsSampled() bool {
  237. return sc.traceFlags.IsSampled()
  238. }
  239. // WithTraceFlags returns a new SpanContext with the TraceFlags replaced.
  240. func (sc SpanContext) WithTraceFlags(flags TraceFlags) SpanContext {
  241. return SpanContext{
  242. traceID: sc.traceID,
  243. spanID: sc.spanID,
  244. traceFlags: flags,
  245. traceState: sc.traceState,
  246. remote: sc.remote,
  247. }
  248. }
  249. // TraceState returns the TraceState from the SpanContext.
  250. func (sc SpanContext) TraceState() TraceState {
  251. return sc.traceState
  252. }
  253. // WithTraceState returns a new SpanContext with the TraceState replaced.
  254. func (sc SpanContext) WithTraceState(state TraceState) SpanContext {
  255. return SpanContext{
  256. traceID: sc.traceID,
  257. spanID: sc.spanID,
  258. traceFlags: sc.traceFlags,
  259. traceState: state,
  260. remote: sc.remote,
  261. }
  262. }
  263. // Equal is a predicate that determines whether two SpanContext values are equal.
  264. func (sc SpanContext) Equal(other SpanContext) bool {
  265. return sc.traceID == other.traceID &&
  266. sc.spanID == other.spanID &&
  267. sc.traceFlags == other.traceFlags &&
  268. sc.traceState.String() == other.traceState.String() &&
  269. sc.remote == other.remote
  270. }
  271. // MarshalJSON implements a custom marshal function to encode a SpanContext.
  272. func (sc SpanContext) MarshalJSON() ([]byte, error) {
  273. return json.Marshal(SpanContextConfig{
  274. TraceID: sc.traceID,
  275. SpanID: sc.spanID,
  276. TraceFlags: sc.traceFlags,
  277. TraceState: sc.traceState,
  278. Remote: sc.remote,
  279. })
  280. }
  281. // Span is the individual component of a trace. It represents a single named
  282. // and timed operation of a workflow that is traced. A Tracer is used to
  283. // create a Span and it is then up to the operation the Span represents to
  284. // properly end the Span when the operation itself ends.
  285. //
  286. // Warning: methods may be added to this interface in minor releases.
  287. type Span interface {
  288. // End completes the Span. The Span is considered complete and ready to be
  289. // delivered through the rest of the telemetry pipeline after this method
  290. // is called. Therefore, updates to the Span are not allowed after this
  291. // method has been called.
  292. End(options ...SpanEndOption)
  293. // AddEvent adds an event with the provided name and options.
  294. AddEvent(name string, options ...EventOption)
  295. // IsRecording returns the recording state of the Span. It will return
  296. // true if the Span is active and events can be recorded.
  297. IsRecording() bool
  298. // RecordError will record err as an exception span event for this span. An
  299. // additional call to SetStatus is required if the Status of the Span should
  300. // be set to Error, as this method does not change the Span status. If this
  301. // span is not being recorded or err is nil then this method does nothing.
  302. RecordError(err error, options ...EventOption)
  303. // SpanContext returns the SpanContext of the Span. The returned SpanContext
  304. // is usable even after the End method has been called for the Span.
  305. SpanContext() SpanContext
  306. // SetStatus sets the status of the Span in the form of a code and a
  307. // description, overriding previous values set. The description is only
  308. // included in a status when the code is for an error.
  309. SetStatus(code codes.Code, description string)
  310. // SetName sets the Span name.
  311. SetName(name string)
  312. // SetAttributes sets kv as attributes of the Span. If a key from kv
  313. // already exists for an attribute of the Span it will be overwritten with
  314. // the value contained in kv.
  315. SetAttributes(kv ...attribute.KeyValue)
  316. // TracerProvider returns a TracerProvider that can be used to generate
  317. // additional Spans on the same telemetry pipeline as the current Span.
  318. TracerProvider() TracerProvider
  319. }
  320. // Link is the relationship between two Spans. The relationship can be within
  321. // the same Trace or across different Traces.
  322. //
  323. // For example, a Link is used in the following situations:
  324. //
  325. // 1. Batch Processing: A batch of operations may contain operations
  326. // associated with one or more traces/spans. Since there can only be one
  327. // parent SpanContext, a Link is used to keep reference to the
  328. // SpanContext of all operations in the batch.
  329. // 2. Public Endpoint: A SpanContext for an in incoming client request on a
  330. // public endpoint should be considered untrusted. In such a case, a new
  331. // trace with its own identity and sampling decision needs to be created,
  332. // but this new trace needs to be related to the original trace in some
  333. // form. A Link is used to keep reference to the original SpanContext and
  334. // track the relationship.
  335. type Link struct {
  336. // SpanContext of the linked Span.
  337. SpanContext SpanContext
  338. // Attributes describe the aspects of the link.
  339. Attributes []attribute.KeyValue
  340. }
  341. // LinkFromContext returns a link encapsulating the SpanContext in the provided ctx.
  342. func LinkFromContext(ctx context.Context, attrs ...attribute.KeyValue) Link {
  343. return Link{
  344. SpanContext: SpanContextFromContext(ctx),
  345. Attributes: attrs,
  346. }
  347. }
  348. // SpanKind is the role a Span plays in a Trace.
  349. type SpanKind int
  350. // As a convenience, these match the proto definition, see
  351. // https://github.com/open-telemetry/opentelemetry-proto/blob/30d237e1ff3ab7aa50e0922b5bebdd93505090af/opentelemetry/proto/trace/v1/trace.proto#L101-L129
  352. //
  353. // The unspecified value is not a valid `SpanKind`. Use `ValidateSpanKind()`
  354. // to coerce a span kind to a valid value.
  355. const (
  356. // SpanKindUnspecified is an unspecified SpanKind and is not a valid
  357. // SpanKind. SpanKindUnspecified should be replaced with SpanKindInternal
  358. // if it is received.
  359. SpanKindUnspecified SpanKind = 0
  360. // SpanKindInternal is a SpanKind for a Span that represents an internal
  361. // operation within an application.
  362. SpanKindInternal SpanKind = 1
  363. // SpanKindServer is a SpanKind for a Span that represents the operation
  364. // of handling a request from a client.
  365. SpanKindServer SpanKind = 2
  366. // SpanKindClient is a SpanKind for a Span that represents the operation
  367. // of client making a request to a server.
  368. SpanKindClient SpanKind = 3
  369. // SpanKindProducer is a SpanKind for a Span that represents the operation
  370. // of a producer sending a message to a message broker. Unlike
  371. // SpanKindClient and SpanKindServer, there is often no direct
  372. // relationship between this kind of Span and a SpanKindConsumer kind. A
  373. // SpanKindProducer Span will end once the message is accepted by the
  374. // message broker which might not overlap with the processing of that
  375. // message.
  376. SpanKindProducer SpanKind = 4
  377. // SpanKindConsumer is a SpanKind for a Span that represents the operation
  378. // of a consumer receiving a message from a message broker. Like
  379. // SpanKindProducer Spans, there is often no direct relationship between
  380. // this Span and the Span that produced the message.
  381. SpanKindConsumer SpanKind = 5
  382. )
  383. // ValidateSpanKind returns a valid span kind value. This will coerce
  384. // invalid values into the default value, SpanKindInternal.
  385. func ValidateSpanKind(spanKind SpanKind) SpanKind {
  386. switch spanKind {
  387. case SpanKindInternal,
  388. SpanKindServer,
  389. SpanKindClient,
  390. SpanKindProducer,
  391. SpanKindConsumer:
  392. // valid
  393. return spanKind
  394. default:
  395. return SpanKindInternal
  396. }
  397. }
  398. // String returns the specified name of the SpanKind in lower-case.
  399. func (sk SpanKind) String() string {
  400. switch sk {
  401. case SpanKindInternal:
  402. return "internal"
  403. case SpanKindServer:
  404. return "server"
  405. case SpanKindClient:
  406. return "client"
  407. case SpanKindProducer:
  408. return "producer"
  409. case SpanKindConsumer:
  410. return "consumer"
  411. default:
  412. return "unspecified"
  413. }
  414. }
  415. // Tracer is the creator of Spans.
  416. //
  417. // Warning: methods may be added to this interface in minor releases.
  418. type Tracer interface {
  419. // Start creates a span and a context.Context containing the newly-created span.
  420. //
  421. // If the context.Context provided in `ctx` contains a Span then the newly-created
  422. // Span will be a child of that span, otherwise it will be a root span. This behavior
  423. // can be overridden by providing `WithNewRoot()` as a SpanOption, causing the
  424. // newly-created Span to be a root span even if `ctx` contains a Span.
  425. //
  426. // When creating a Span it is recommended to provide all known span attributes using
  427. // the `WithAttributes()` SpanOption as samplers will only have access to the
  428. // attributes provided when a Span is created.
  429. //
  430. // Any Span that is created MUST also be ended. This is the responsibility of the user.
  431. // Implementations of this API may leak memory or other resources if Spans are not ended.
  432. Start(ctx context.Context, spanName string, opts ...SpanStartOption) (context.Context, Span)
  433. }
  434. // TracerProvider provides access to instrumentation Tracers.
  435. //
  436. // Warning: methods may be added to this interface in minor releases.
  437. type TracerProvider interface {
  438. // Tracer creates an implementation of the Tracer interface.
  439. // The instrumentationName must be the name of the library providing
  440. // instrumentation. This name may be the same as the instrumented code
  441. // only if that code provides built-in instrumentation. If the
  442. // instrumentationName is empty, then a implementation defined default
  443. // name will be used instead.
  444. //
  445. // This method must be concurrency safe.
  446. Tracer(instrumentationName string, opts ...TracerOption) Tracer
  447. }