config.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package trace // import "go.opentelemetry.io/otel/trace"
  4. import (
  5. "slices"
  6. "time"
  7. "go.opentelemetry.io/otel/attribute"
  8. )
  9. // TracerConfig is a group of options for a Tracer.
  10. type TracerConfig struct {
  11. instrumentationVersion string
  12. // Schema URL of the telemetry emitted by the Tracer.
  13. schemaURL string
  14. attrs attribute.Set
  15. }
  16. // InstrumentationVersion returns the version of the library providing instrumentation.
  17. func (t *TracerConfig) InstrumentationVersion() string {
  18. return t.instrumentationVersion
  19. }
  20. // InstrumentationAttributes returns the attributes associated with the library
  21. // providing instrumentation.
  22. func (t *TracerConfig) InstrumentationAttributes() attribute.Set {
  23. return t.attrs
  24. }
  25. // SchemaURL returns the Schema URL of the telemetry emitted by the Tracer.
  26. func (t *TracerConfig) SchemaURL() string {
  27. return t.schemaURL
  28. }
  29. // NewTracerConfig applies all the options to a returned TracerConfig.
  30. func NewTracerConfig(options ...TracerOption) TracerConfig {
  31. var config TracerConfig
  32. for _, option := range options {
  33. config = option.apply(config)
  34. }
  35. return config
  36. }
  37. // TracerOption applies an option to a TracerConfig.
  38. type TracerOption interface {
  39. apply(TracerConfig) TracerConfig
  40. }
  41. type tracerOptionFunc func(TracerConfig) TracerConfig
  42. func (fn tracerOptionFunc) apply(cfg TracerConfig) TracerConfig {
  43. return fn(cfg)
  44. }
  45. // SpanConfig is a group of options for a Span.
  46. type SpanConfig struct {
  47. attributes []attribute.KeyValue
  48. timestamp time.Time
  49. links []Link
  50. newRoot bool
  51. spanKind SpanKind
  52. stackTrace bool
  53. }
  54. // Attributes describe the associated qualities of a Span.
  55. func (cfg *SpanConfig) Attributes() []attribute.KeyValue {
  56. return cfg.attributes
  57. }
  58. // Timestamp is a time in a Span life-cycle.
  59. func (cfg *SpanConfig) Timestamp() time.Time {
  60. return cfg.timestamp
  61. }
  62. // StackTrace reports whether stack trace capturing is enabled.
  63. func (cfg *SpanConfig) StackTrace() bool {
  64. return cfg.stackTrace
  65. }
  66. // Links are the associations a Span has with other Spans.
  67. func (cfg *SpanConfig) Links() []Link {
  68. return cfg.links
  69. }
  70. // NewRoot identifies a Span as the root Span for a new trace. This is
  71. // commonly used when an existing trace crosses trust boundaries and the
  72. // remote parent span context should be ignored for security.
  73. func (cfg *SpanConfig) NewRoot() bool {
  74. return cfg.newRoot
  75. }
  76. // SpanKind is the role a Span has in a trace.
  77. func (cfg *SpanConfig) SpanKind() SpanKind {
  78. return cfg.spanKind
  79. }
  80. // NewSpanStartConfig applies all the options to a returned SpanConfig.
  81. // No validation is performed on the returned SpanConfig (e.g. no uniqueness
  82. // checking or bounding of data), it is left to the SDK to perform this
  83. // action.
  84. func NewSpanStartConfig(options ...SpanStartOption) SpanConfig {
  85. var c SpanConfig
  86. for _, option := range options {
  87. c = option.applySpanStart(c)
  88. }
  89. return c
  90. }
  91. // NewSpanEndConfig applies all the options to a returned SpanConfig.
  92. // No validation is performed on the returned SpanConfig (e.g. no uniqueness
  93. // checking or bounding of data), it is left to the SDK to perform this
  94. // action.
  95. func NewSpanEndConfig(options ...SpanEndOption) SpanConfig {
  96. var c SpanConfig
  97. for _, option := range options {
  98. c = option.applySpanEnd(c)
  99. }
  100. return c
  101. }
  102. // SpanStartOption applies an option to a SpanConfig. These options are applicable
  103. // only when the span is created.
  104. type SpanStartOption interface {
  105. applySpanStart(SpanConfig) SpanConfig
  106. }
  107. type spanOptionFunc func(SpanConfig) SpanConfig
  108. func (fn spanOptionFunc) applySpanStart(cfg SpanConfig) SpanConfig {
  109. return fn(cfg)
  110. }
  111. // SpanEndOption applies an option to a SpanConfig. These options are
  112. // applicable only when the span is ended.
  113. type SpanEndOption interface {
  114. applySpanEnd(SpanConfig) SpanConfig
  115. }
  116. // EventConfig is a group of options for an Event.
  117. type EventConfig struct {
  118. attributes []attribute.KeyValue
  119. timestamp time.Time
  120. stackTrace bool
  121. }
  122. // Attributes describe the associated qualities of an Event.
  123. func (cfg *EventConfig) Attributes() []attribute.KeyValue {
  124. return cfg.attributes
  125. }
  126. // Timestamp is a time in an Event life-cycle.
  127. func (cfg *EventConfig) Timestamp() time.Time {
  128. return cfg.timestamp
  129. }
  130. // StackTrace reports whether stack trace capturing is enabled.
  131. func (cfg *EventConfig) StackTrace() bool {
  132. return cfg.stackTrace
  133. }
  134. // NewEventConfig applies all the EventOptions to a returned EventConfig. If no
  135. // timestamp option is passed, the returned EventConfig will have a Timestamp
  136. // set to the call time, otherwise no validation is performed on the returned
  137. // EventConfig.
  138. func NewEventConfig(options ...EventOption) EventConfig {
  139. var c EventConfig
  140. for _, option := range options {
  141. c = option.applyEvent(c)
  142. }
  143. if c.timestamp.IsZero() {
  144. c.timestamp = time.Now()
  145. }
  146. return c
  147. }
  148. // EventOption applies span event options to an EventConfig.
  149. type EventOption interface {
  150. applyEvent(EventConfig) EventConfig
  151. }
  152. // SpanOption are options that can be used at both the beginning and end of a span.
  153. type SpanOption interface {
  154. SpanStartOption
  155. SpanEndOption
  156. }
  157. // SpanStartEventOption are options that can be used at the start of a span, or with an event.
  158. type SpanStartEventOption interface {
  159. SpanStartOption
  160. EventOption
  161. }
  162. // SpanEndEventOption are options that can be used at the end of a span, or with an event.
  163. type SpanEndEventOption interface {
  164. SpanEndOption
  165. EventOption
  166. }
  167. type attributeOption []attribute.KeyValue
  168. func (o attributeOption) applySpan(c SpanConfig) SpanConfig {
  169. c.attributes = append(c.attributes, []attribute.KeyValue(o)...)
  170. return c
  171. }
  172. func (o attributeOption) applySpanStart(c SpanConfig) SpanConfig { return o.applySpan(c) }
  173. func (o attributeOption) applyEvent(c EventConfig) EventConfig {
  174. c.attributes = append(c.attributes, []attribute.KeyValue(o)...)
  175. return c
  176. }
  177. var _ SpanStartEventOption = attributeOption{}
  178. // WithAttributes adds the attributes related to a span life-cycle event.
  179. // These attributes are used to describe the work a Span represents when this
  180. // option is provided to a Span's start event. Otherwise, these
  181. // attributes provide additional information about the event being recorded
  182. // (e.g. error, state change, processing progress, system event).
  183. //
  184. // If multiple of these options are passed the attributes of each successive
  185. // option will extend the attributes instead of overwriting. There is no
  186. // guarantee of uniqueness in the resulting attributes.
  187. func WithAttributes(attributes ...attribute.KeyValue) SpanStartEventOption {
  188. return attributeOption(attributes)
  189. }
  190. // SpanEventOption are options that can be used with an event or a span.
  191. type SpanEventOption interface {
  192. SpanOption
  193. EventOption
  194. }
  195. type timestampOption time.Time
  196. func (o timestampOption) applySpan(c SpanConfig) SpanConfig {
  197. c.timestamp = time.Time(o)
  198. return c
  199. }
  200. func (o timestampOption) applySpanStart(c SpanConfig) SpanConfig { return o.applySpan(c) }
  201. func (o timestampOption) applySpanEnd(c SpanConfig) SpanConfig { return o.applySpan(c) }
  202. func (o timestampOption) applyEvent(c EventConfig) EventConfig {
  203. c.timestamp = time.Time(o)
  204. return c
  205. }
  206. var _ SpanEventOption = timestampOption{}
  207. // WithTimestamp sets the time of a Span or Event life-cycle moment (e.g.
  208. // started, stopped, errored).
  209. func WithTimestamp(t time.Time) SpanEventOption {
  210. return timestampOption(t)
  211. }
  212. type stackTraceOption bool
  213. func (o stackTraceOption) applyEvent(c EventConfig) EventConfig {
  214. c.stackTrace = bool(o)
  215. return c
  216. }
  217. func (o stackTraceOption) applySpan(c SpanConfig) SpanConfig {
  218. c.stackTrace = bool(o)
  219. return c
  220. }
  221. func (o stackTraceOption) applySpanEnd(c SpanConfig) SpanConfig { return o.applySpan(c) }
  222. // WithStackTrace sets the flag to capture the error with stack trace (e.g. true, false).
  223. func WithStackTrace(b bool) SpanEndEventOption {
  224. return stackTraceOption(b)
  225. }
  226. // WithLinks adds links to a Span. The links are added to the existing Span
  227. // links, i.e. this does not overwrite. Links with invalid span context are ignored.
  228. func WithLinks(links ...Link) SpanStartOption {
  229. return spanOptionFunc(func(cfg SpanConfig) SpanConfig {
  230. cfg.links = append(cfg.links, links...)
  231. return cfg
  232. })
  233. }
  234. // WithNewRoot specifies that the Span should be treated as a root Span. Any
  235. // existing parent span context will be ignored when defining the Span's trace
  236. // identifiers.
  237. func WithNewRoot() SpanStartOption {
  238. return spanOptionFunc(func(cfg SpanConfig) SpanConfig {
  239. cfg.newRoot = true
  240. return cfg
  241. })
  242. }
  243. // WithSpanKind sets the SpanKind of a Span.
  244. func WithSpanKind(kind SpanKind) SpanStartOption {
  245. return spanOptionFunc(func(cfg SpanConfig) SpanConfig {
  246. cfg.spanKind = kind
  247. return cfg
  248. })
  249. }
  250. // WithInstrumentationVersion sets the instrumentation version.
  251. func WithInstrumentationVersion(version string) TracerOption {
  252. return tracerOptionFunc(func(cfg TracerConfig) TracerConfig {
  253. cfg.instrumentationVersion = version
  254. return cfg
  255. })
  256. }
  257. // mergeSets returns the union of keys between a and b. Any duplicate keys will
  258. // use the value associated with b.
  259. func mergeSets(a, b attribute.Set) attribute.Set {
  260. // NewMergeIterator uses the first value for any duplicates.
  261. iter := attribute.NewMergeIterator(&b, &a)
  262. merged := make([]attribute.KeyValue, 0, a.Len()+b.Len())
  263. for iter.Next() {
  264. merged = append(merged, iter.Attribute())
  265. }
  266. return attribute.NewSet(merged...)
  267. }
  268. // WithInstrumentationAttributes adds the instrumentation attributes.
  269. //
  270. // This is equivalent to calling [WithInstrumentationAttributeSet] with an
  271. // [attribute.Set] created from a clone of the passed attributes.
  272. // [WithInstrumentationAttributeSet] is recommended for more control.
  273. //
  274. // If multiple [WithInstrumentationAttributes] or [WithInstrumentationAttributeSet]
  275. // options are passed, the attributes will be merged together in the order
  276. // they are passed. Attributes with duplicate keys will use the last value passed.
  277. func WithInstrumentationAttributes(attr ...attribute.KeyValue) TracerOption {
  278. set := attribute.NewSet(slices.Clone(attr)...)
  279. return WithInstrumentationAttributeSet(set)
  280. }
  281. // WithInstrumentationAttributeSet adds the instrumentation attributes.
  282. //
  283. // If multiple [WithInstrumentationAttributes] or [WithInstrumentationAttributeSet]
  284. // options are passed, the attributes will be merged together in the order
  285. // they are passed. Attributes with duplicate keys will use the last value passed.
  286. func WithInstrumentationAttributeSet(set attribute.Set) TracerOption {
  287. if set.Len() == 0 {
  288. return tracerOptionFunc(func(config TracerConfig) TracerConfig {
  289. return config
  290. })
  291. }
  292. return tracerOptionFunc(func(config TracerConfig) TracerConfig {
  293. if config.attrs.Len() == 0 {
  294. config.attrs = set
  295. } else {
  296. config.attrs = mergeSets(config.attrs, set)
  297. }
  298. return config
  299. })
  300. }
  301. // WithSchemaURL sets the schema URL for the Tracer.
  302. func WithSchemaURL(schemaURL string) TracerOption {
  303. return tracerOptionFunc(func(cfg TracerConfig) TracerConfig {
  304. cfg.schemaURL = schemaURL
  305. return cfg
  306. })
  307. }