@zio.dev/zio-blocks 0.0.51 → 0.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/adr/2026-07-18-data-migration.md +123 -0
  2. package/guides/async-getting-started.md +687 -0
  3. package/guides/compile-time-resource-safety-with-scope.md +6 -0
  4. package/guides/getting-started-with-mux.md +0 -112
  5. package/guides/query-dsl-extending.md +1 -1
  6. package/guides/query-dsl-fluent-builder.md +1 -1
  7. package/guides/query-dsl-reified-optics.md +1 -1
  8. package/guides/query-dsl-sql.md +395 -1
  9. package/guides/sql-checked-interpolation.md +173 -0
  10. package/guides/sql-transactions.md +286 -0
  11. package/guides/telemetry-guide.md +131 -70
  12. package/guides/zio-schema-migration.md +6 -6
  13. package/index.md +200 -559
  14. package/package.json +1 -1
  15. package/reference/async.md +1379 -531
  16. package/reference/chunk.md +3 -3
  17. package/reference/codegen/index.md +1 -1
  18. package/reference/combinators.md +4 -4
  19. package/reference/config/config-decoder.md +460 -0
  20. package/reference/config/config-source.md +489 -0
  21. package/reference/config/errors.md +278 -0
  22. package/reference/config/flags.md +369 -0
  23. package/reference/config/formats.md +314 -0
  24. package/reference/config/index.md +304 -0
  25. package/reference/config/rollout.md +336 -0
  26. package/reference/context.md +6 -49
  27. package/reference/data-migration.md +269 -0
  28. package/reference/datastar/attributes.md +302 -0
  29. package/reference/datastar/events.md +234 -0
  30. package/reference/datastar/index.md +256 -0
  31. package/reference/datastar/signals.md +230 -0
  32. package/reference/datastar/sse.md +295 -0
  33. package/reference/datastar.md +2 -2
  34. package/reference/docs.md +2 -2
  35. package/reference/endpoint/bulk-creation.md +96 -0
  36. package/reference/endpoint/endpoint.md +1 -0
  37. package/reference/endpoint/index.md +9 -89
  38. package/reference/endpoint/path-codec.md +12 -24
  39. package/reference/endpoint/route-pattern.md +4 -6
  40. package/reference/endpoint/segment-codec.md +19 -32
  41. package/reference/html.md +313 -9
  42. package/reference/htmx/index.md +4 -52
  43. package/reference/htmx/response-headers.md +240 -0
  44. package/reference/http-model/headers.md +735 -0
  45. package/reference/http-model/index.md +3 -1
  46. package/reference/http-model/model.md +107 -71
  47. package/reference/http-model/schema-codecs.md +522 -0
  48. package/reference/http-model/schema.md +6 -3
  49. package/reference/http-model/server-sent-event.md +341 -0
  50. package/reference/jwt.md +195 -0
  51. package/reference/maybe.md +128 -11
  52. package/reference/media-type.md +2 -2
  53. package/reference/mux.mdx +7 -2
  54. package/reference/openapi.md +3 -3
  55. package/reference/projection.md +654 -0
  56. package/reference/resource-management/index.md +1 -1
  57. package/reference/resource-management/resource.md +2 -98
  58. package/reference/resource-management/scope.md +1 -209
  59. package/reference/resource-management/wire.md +4 -50
  60. package/reference/ringbuffer/advanced.mdx +1 -1
  61. package/reference/ringbuffer/index.mdx +3 -3
  62. package/reference/ringbuffer/mpmc.mdx +38 -4
  63. package/reference/ringbuffer/mpsc.mdx +36 -4
  64. package/reference/ringbuffer/spmc.mdx +1 -1
  65. package/reference/ringbuffer/spsc.mdx +87 -15
  66. package/reference/schema/allows.md +0 -96
  67. package/reference/schema/binding.md +2 -2
  68. package/reference/schema/built-in-codecs/avro.md +2 -2
  69. package/reference/schema/built-in-codecs/bson.md +50 -20
  70. package/reference/schema/built-in-codecs/csv.md +2 -2
  71. package/reference/schema/built-in-codecs/index.md +3 -3
  72. package/reference/schema/built-in-codecs/json/index.md +2 -2
  73. package/reference/schema/built-in-codecs/json/json.md +1 -0
  74. package/reference/schema/built-in-codecs/messagepack.md +3 -3
  75. package/reference/schema/built-in-codecs/thrift.md +2 -2
  76. package/reference/schema/built-in-codecs/toon.md +3 -3
  77. package/reference/schema/built-in-codecs/yaml.md +2 -2
  78. package/reference/schema/codec.md +11 -11
  79. package/reference/schema/dynamic-optic.md +48 -3
  80. package/reference/schema/dynamic-schema.md +3 -3
  81. package/reference/schema/index.md +2 -0
  82. package/reference/schema/path-interpolator.md +2 -0
  83. package/reference/schema/reflect-transformer.md +140 -0
  84. package/reference/schema/schema-evolution/as.md +4 -4
  85. package/reference/schema/schema-evolution/into.md +2 -2
  86. package/reference/schema/schema-expr.md +2 -2
  87. package/reference/schema/schema-search.md +263 -0
  88. package/reference/schema/schema.md +10 -2
  89. package/reference/schema/type-class-derivation.md +1 -1
  90. package/reference/smithy.md +502 -3
  91. package/reference/sql/db-codec-deriver.md +3 -3
  92. package/reference/sql/db-codec.md +22 -22
  93. package/reference/sql/db-con.md +4 -4
  94. package/reference/sql/db-connection.md +1 -1
  95. package/reference/sql/db-param.md +1 -1
  96. package/reference/sql/db-result-reader.md +4 -2
  97. package/reference/sql/db-tx.md +46 -14
  98. package/reference/sql/ddl.md +1 -1
  99. package/reference/sql/frag.md +44 -10
  100. package/reference/sql/index.md +7 -7
  101. package/reference/sql/repo.md +15 -15
  102. package/reference/sql/sql-dialect.md +1 -1
  103. package/reference/sql/sql-logger.md +1 -1
  104. package/reference/sql/sql-name-mapper.md +3 -3
  105. package/reference/sql/table-metadata.md +3 -3
  106. package/reference/sql/table.md +10 -10
  107. package/reference/sql/transactor-zio.md +1 -1
  108. package/reference/sql/transactor.md +21 -11
  109. package/reference/sql-zio.md +2 -2
  110. package/reference/streams/core/index.md +32 -0
  111. package/reference/streams/{pipeline.md → core/pipeline.md} +210 -74
  112. package/reference/streams/{sink.md → core/sink.md} +331 -353
  113. package/reference/streams/{stream.md → core/stream.md} +919 -209
  114. package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
  115. package/reference/streams/execution-and-compatibility/index.md +35 -0
  116. package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
  117. package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
  118. package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
  119. package/reference/streams/index.md +140 -67
  120. package/reference/streams/primitives/index.md +30 -0
  121. package/reference/streams/primitives/reader.md +1992 -0
  122. package/reference/streams/{writer.md → primitives/writer.md} +254 -98
  123. package/reference/telemetry/common/any-value.md +90 -0
  124. package/reference/telemetry/common/attribute-key.md +87 -0
  125. package/reference/telemetry/common/attributes.md +118 -0
  126. package/reference/telemetry/common/index.md +39 -0
  127. package/reference/telemetry/common/instrumentation-scope.md +24 -0
  128. package/reference/telemetry/common/resource.md +34 -0
  129. package/reference/telemetry/index.md +311 -0
  130. package/reference/telemetry/logging/index.md +197 -0
  131. package/reference/telemetry/logging/log-enrichment.md +72 -0
  132. package/reference/telemetry/logging/log-formatter.md +100 -0
  133. package/reference/telemetry/logging/log-record-processor.md +56 -0
  134. package/reference/telemetry/logging/log-record.md +44 -0
  135. package/reference/telemetry/logging/log-writer.md +64 -0
  136. package/reference/telemetry/logging/logger-provider.md +142 -0
  137. package/reference/telemetry/logging/logger.md +83 -0
  138. package/reference/telemetry/logging/severity.md +62 -0
  139. package/reference/telemetry/metrics/index.md +150 -0
  140. package/reference/telemetry/metrics/instruments.md +183 -0
  141. package/reference/telemetry/metrics/labeled-instruments.md +74 -0
  142. package/reference/telemetry/metrics/meter-provider.md +76 -0
  143. package/reference/telemetry/metrics/meter.md +98 -0
  144. package/reference/telemetry/metrics/metric-data.md +57 -0
  145. package/reference/telemetry/otel/custom-exporter.md +216 -0
  146. package/reference/telemetry/otel/index.md +212 -0
  147. package/reference/telemetry/tracing/index.md +155 -0
  148. package/reference/telemetry/tracing/sampler.md +89 -0
  149. package/reference/telemetry/tracing/span-builder.md +57 -0
  150. package/reference/telemetry/tracing/span-context.md +39 -0
  151. package/reference/telemetry/tracing/span-data.md +32 -0
  152. package/reference/telemetry/tracing/span-kind.md +55 -0
  153. package/reference/telemetry/tracing/span-processor.md +53 -0
  154. package/reference/telemetry/tracing/span-status.md +47 -0
  155. package/reference/telemetry/tracing/span.md +117 -0
  156. package/reference/telemetry/tracing/tracer-provider.md +91 -0
  157. package/reference/telemetry/tracing/tracer.md +52 -0
  158. package/reference/typeid.md +0 -64
  159. package/sidebars.js +365 -185
  160. package/undocumented-report.md +528 -270
  161. package/reference/config.md +0 -158
  162. package/reference/streams/concurrent-operators.md +0 -106
  163. package/reference/streams/reader.md +0 -1284
  164. package/reference/streams/scala-2-compatibility.md +0 -55
  165. package/reference/streams/zero-boxing.md +0 -275
  166. package/reference/telemetry.md +0 -693
@@ -0,0 +1,90 @@
1
+ ---
2
+ id: any-value
3
+ title: "AttributeValue"
4
+ description: "Boxed existential wrapper for the eight attribute kinds — the value type accepted by Logger, Span#setAttribute, and metric label maps when the type isn't known ahead of time."
5
+ keywords:
6
+ - "Telemetry Metadata"
7
+ - "Attribute Value"
8
+ - "OTLP AnyValue"
9
+ - "AttributeValue"
10
+ ---
11
+
12
+ `AttributeValue` is the closed set of eight kinds an attribute can hold — one case class per kind, so code that accepts "any attribute value" can pattern match on which one it got. It exists at the boundary of the telemetry API: `Attributes` itself never stores one (see [Attributes](./attributes.md) for the unboxed parallel-array representation it uses instead), but constructing or reading one at a boundary — a log call, a span attribute buffer, a metric label map, an exporter — needs a single type that can be any of the eight, and `AttributeValue` is it. Its eight variants:
13
+
14
+ ```scala
15
+ sealed trait AttributeValue
16
+
17
+ object AttributeValue {
18
+ final case class StringValue(value: String) extends AttributeValue
19
+ final case class BooleanValue(value: Boolean) extends AttributeValue
20
+ final case class LongValue(value: Long) extends AttributeValue
21
+ final case class DoubleValue(value: Double) extends AttributeValue
22
+ final case class StringSeqValue(value: Seq[String]) extends AttributeValue
23
+ final case class LongSeqValue(value: Seq[Long]) extends AttributeValue
24
+ final case class DoubleSeqValue(value: Seq[Double]) extends AttributeValue
25
+ final case class BooleanSeqValue(value: Seq[Boolean]) extends AttributeValue
26
+ }
27
+ ```
28
+
29
+ The name in this page's title is the Scala identifier; the file uses `any-value` because the type's own doc comment describes it as mirroring OpenTelemetry's `AnyValue` protobuf message, which supports the same eight shapes: a string, a boolean, a 64-bit integer, a double, and an array of each.
30
+
31
+ ## Where It Shows Up
32
+
33
+ `AttributeValue` is the value type wherever an attribute is accepted without a pre-declared [`AttributeKey`](./attribute-key.md). The `Logger` API is the clearest example — every logging method takes a variadic list of name/value pairs typed against it:
34
+
35
+ ```scala
36
+ import zio.blocks.telemetry._
37
+
38
+ val provider = LoggerProvider.builder.build()
39
+ val logger = provider.get("com.example")
40
+
41
+ logger.info(
42
+ "order placed",
43
+ "orderId" -> AttributeValue.StringValue("ord_123"),
44
+ "total" -> AttributeValue.DoubleValue(49.99),
45
+ "rush" -> AttributeValue.BooleanValue(true)
46
+ )
47
+
48
+ provider.shutdown()
49
+ ```
50
+
51
+ The same ADT appears on the reading side of `Attributes` — `Attributes#foreach` and `Attributes#toMap` box each stored value into an `AttributeValue` so you can match on its kind, which [Attributes](./attributes.md#iterating) covers in full, including why `Attributes#accept` is the zero-allocation alternative for a hot path. `Span#setAttribute`, `Tracer`'s span-creation attribute maps, and the label maps `Counter`/`Histogram`/`Gauge`/`UpDownCounter` accept all convert through `AttributeValue` the same way `Logger` does — construct or match on one of the eight cases, never a ninth.
52
+
53
+ ## Relationship to AttributeType
54
+
55
+ Each `AttributeValue` variant corresponds to exactly one [`AttributeType`](./attribute-key.md) discriminator and one `AttributeKey` factory — the three are the same eight-way split viewed from three angles: the runtime value, the compile-time type tag, and the typed key constructor:
56
+
57
+ | `AttributeValue` variant | `AttributeType` | `AttributeKey` factory |
58
+ | ------------------------- | ---------------- | ------------------------ |
59
+ | `StringValue(String)` | `StringType` | `AttributeKey.string` |
60
+ | `BooleanValue(Boolean)` | `BooleanType` | `AttributeKey.boolean` |
61
+ | `LongValue(Long)` | `LongType` | `AttributeKey.long` |
62
+ | `DoubleValue(Double)` | `DoubleType` | `AttributeKey.double` |
63
+ | `StringSeqValue(Seq[String])` | `StringSeqType` | `AttributeKey.stringSeq` |
64
+ | `LongSeqValue(Seq[Long])` | `LongSeqType` | `AttributeKey.longSeq` |
65
+ | `DoubleSeqValue(Seq[Double])` | `DoubleSeqType` | `AttributeKey.doubleSeq` |
66
+ | `BooleanSeqValue(Seq[Boolean])` | `BooleanSeqType` | `AttributeKey.booleanSeq` |
67
+
68
+ `AttributeType` never appears on its own in application code — it's the tag `AttributeKey[A]#type` carries so a key and a stored value can be checked against each other without reflecting on `A` itself.
69
+
70
+ ## OTLP JSON Mapping
71
+
72
+ The [OTLP exporter](../otel/index.md) converts every `Attributes` set to OTLP's `AnyValue` JSON shape by boxing each entry into an `AttributeValue` and matching on it. The eight cases map onto four wire keys, with sequences nesting under `arrayValue`:
73
+
74
+ | `AttributeValue` variant | OTLP JSON field | Notes |
75
+ | -------------------------- | ------------------ | ------- |
76
+ | `StringValue` | `"stringValue"` | plain JSON string |
77
+ | `BooleanValue` | `"boolValue"` | plain JSON boolean |
78
+ | `LongValue` | `"intValue"` | JSON string, per OTLP's `int64` mapping — `42L` becomes `"42"` |
79
+ | `DoubleValue` | `"doubleValue"` | plain JSON number |
80
+ | `StringSeqValue` | `"arrayValue":{"values":[{"stringValue":...}, ...]}` | one wrapped element per entry |
81
+ | `LongSeqValue` | `"arrayValue":{"values":[{"intValue":"..."}, ...]}` | each element quoted, same as scalar `LongValue` |
82
+ | `DoubleSeqValue` | `"arrayValue":{"values":[{"doubleValue":...}, ...]}` | |
83
+ | `BooleanSeqValue` | `"arrayValue":{"values":[{"boolValue":...}, ...]}` | |
84
+
85
+ ## See Also
86
+
87
+ - [Attributes](./attributes.md#iterating) — `Attributes#foreach`/`Attributes#toMap` (which box into `AttributeValue`) versus `Attributes#accept` (which doesn't)
88
+ - [AttributeKey](./attribute-key.md) — the typed key that pairs with a specific `AttributeValue` variant for allocation-free reads
89
+ - [OTLP Export](../otel/index.md) — where `AttributeValue` becomes OTLP's `AnyValue` JSON representation
90
+ - [Common Types](./index.md) — the types every telemetry pillar uses
@@ -0,0 +1,87 @@
1
+ ---
2
+ id: attribute-key
3
+ title: "AttributeKey"
4
+ description: "Type-safe key for Attributes storage. Binds a string name to a specific value type A (String, Boolean, Long, Double, and their Seq variants)."
5
+ keywords:
6
+ - "Telemetry Metadata"
7
+ - "Type-Safe Key"
8
+ - "Typed Attributes"
9
+ - "AttributeKey"
10
+ ---
11
+
12
+ `AttributeKey[A]` is the type-safe key type for reading and writing entries in an `Attributes` collection. It binds a string name to a specific value type `A` via an `AttributeType` discriminator, so `Attributes#get[A](key)` returns `Option[A]` without casting. There are eight supported value types, each with its own factory method on the companion object.
13
+
14
+ ```scala
15
+ sealed trait AttributeKey[A] {
16
+ def name: String // the string label used as the key
17
+ def `type`: AttributeType // discriminator: StringType, LongType, DoubleType, BooleanType, + 4 Seq variants
18
+ }
19
+
20
+ object AttributeKey {
21
+ // Scalar factory methods
22
+ def string(name: String): AttributeKey[String]
23
+ def boolean(name: String): AttributeKey[Boolean]
24
+ def long(name: String): AttributeKey[Long]
25
+ def double(name: String): AttributeKey[Double]
26
+
27
+ // Sequence factory methods
28
+ def stringSeq(name: String): AttributeKey[Seq[String]]
29
+ def longSeq(name: String): AttributeKey[Seq[Long]]
30
+ def doubleSeq(name: String): AttributeKey[Seq[Double]]
31
+ def booleanSeq(name: String): AttributeKey[Seq[Boolean]]
32
+ }
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```scala
38
+ import zio.blocks.telemetry._
39
+
40
+ // Typed factory methods
41
+ val envKey = AttributeKey.string("environment")
42
+ val retryKey = AttributeKey.long("retry.count")
43
+ val debugKey = AttributeKey.boolean("debug.enabled")
44
+ val latencyKey = AttributeKey.double("latency.ms")
45
+ val tagsKey = AttributeKey.stringSeq("tags")
46
+
47
+ // Build an Attributes collection using typed keys
48
+ val attrs = Attributes.builder
49
+ .put(envKey, "production")
50
+ .put(retryKey, 3L)
51
+ .put(debugKey, false)
52
+ .put(latencyKey, 12.5)
53
+ .put(tagsKey, Seq("important", "v2"))
54
+ .build
55
+ ```
56
+
57
+ ## Passing to Span and Metric APIs
58
+
59
+ `AttributeKey` is used directly in `Span#setAttribute` and `Attributes.of`:
60
+
61
+ ```scala
62
+ import zio.blocks.telemetry._
63
+
64
+ val provider = TracerProvider.builder.build()
65
+ val tracer = provider.get("com.example")
66
+
67
+ val dbSystem = AttributeKey.string("db.system")
68
+ val rowCount = AttributeKey.long("db.rows")
69
+
70
+ tracer.span("db.query", SpanKind.Client) { span =>
71
+ span.setAttribute(dbSystem, "postgresql")
72
+ span.setAttribute(rowCount, 42L)
73
+ }
74
+
75
+ provider.shutdown()
76
+ ```
77
+
78
+ ## Predefined Constants
79
+
80
+ `Attributes.ServiceName` and `Attributes.ServiceVersion` are predefined `AttributeKey[String]` constants for the standard OTel `"service.name"` and `"service.version"` attribute names. Use them instead of string literals to avoid typos:
81
+
82
+ ```scala
83
+ import zio.blocks.telemetry._
84
+
85
+ val attrs = Attributes.of(Attributes.ServiceName, "order-service")
86
+ assert(attrs.get(Attributes.ServiceName) == Some("order-service"))
87
+ ```
@@ -0,0 +1,118 @@
1
+ ---
2
+ id: attributes
3
+ title: "Attributes"
4
+ description: "Typed key-value metadata attached to spans, log records, and measurements — built once, read by key, and cheap enough for a hot path."
5
+ keywords:
6
+ - "Telemetry Metadata"
7
+ - "Typed Key-Value Pairs"
8
+ - "Boxing-Free Collection"
9
+ - "Attributes"
10
+ ---
11
+
12
+ `Attributes` is the metadata carried alongside a signal — the `http.route` on a span, the `orderId` on a log record, the `method=GET` on a measurement. It's a set of key-value pairs, and every signal the telemetry module emits has one.
13
+
14
+ It exists because a signal without detail can't answer questions. "A request was slow" is useless; "a `GET` on `/orders` that returned `503` was slow" is something you can search for, filter on, and group by. Attributes are what carry that detail into your backend.
15
+
16
+ Two properties shape the type. Values are reached through a typed [`AttributeKey`](./attribute-key.md), so reading one gives you back a `String` or a `Long` rather than something you must cast. And because a set is built on every span and every measurement — the hottest paths in an instrumented application — primitives are stored without boxing, and a finished set is immutable, so it can be shared rather than copied.
17
+
18
+ ## Building a Set
19
+
20
+ Three ways in, depending on how many pairs you have:
21
+
22
+ ```scala
23
+ import zio.blocks.telemetry._
24
+
25
+ val none = Attributes.empty
26
+
27
+ val one = Attributes.of(Attributes.ServiceName, "payments")
28
+
29
+ val several = Attributes.builder
30
+ .put(AttributeKey.string("http.route"), "/orders")
31
+ .put("http.status_code", 200L)
32
+ .put("cache.hit", false)
33
+ .build
34
+ ```
35
+
36
+ `of` takes exactly one pair, so reach for `builder` as soon as you have two. The builder accepts either a typed key or a plain name with a `String`, `Long`, `Double`, or `Boolean` value, and putting the same key twice keeps the last value. `Attributes.ServiceName` and `ServiceVersion` are predefined keys for the conventional OpenTelemetry names; define your own with [`AttributeKey`](./attribute-key.md).
37
+
38
+ ## Reading a Value
39
+
40
+ `get` takes a key and returns the value at that key's declared type:
41
+
42
+ ```scala
43
+ import zio.blocks.telemetry._
44
+
45
+ val route = AttributeKey.string("http.route")
46
+ val attrs = Attributes.of(route, "/orders")
47
+
48
+ val found: Option[String] = attrs.get(route) // Some("/orders")
49
+ val missing = attrs.get(AttributeKey.string("db.system")) // None
50
+ ```
51
+
52
+ The `Option` covers a key that isn't there. `size` and `isEmpty` report how many pairs a set holds without reading any of them.
53
+
54
+ ## Merging Two Sets
55
+
56
+ `++` combines sets, which is how a signal's own attributes join those of its surroundings:
57
+
58
+ ```scala
59
+ import zio.blocks.telemetry._
60
+
61
+ val env = AttributeKey.string("deployment.environment")
62
+
63
+ val base = Attributes.of(env, "staging")
64
+ val merged = base ++ Attributes.of(env, "production")
65
+
66
+ merged.get(env) // Some("production") — the right side wins
67
+ ```
68
+
69
+ Merging appends rather than deduplicates, so a key on both sides stays in the set twice: the right side wins every lookup, but `size` counts it twice and anything iterating the set — an exporter included — sees it twice. Where two sets may share a key, build one set with a builder instead.
70
+
71
+ ## Iterating
72
+
73
+ Reading a whole set back — to export it, or to check it in a test — comes in two forms, and the difference is worth understanding before you pick one.
74
+
75
+ A `Long` you store here is kept as a plain number, not as an object. Handing it to code that accepts *any* kind of value means wrapping it in an object first — **boxing** — and that wrapper is a small allocation, per attribute, every time. Fine once in a test; not fine on a path that runs on every request.
76
+
77
+ `accept` avoids it by asking you for one method per kind of value. Each method's parameter is that exact type, so the number is passed as a number and nothing is wrapped:
78
+
79
+ ```scala
80
+ import zio.blocks.telemetry._
81
+
82
+ val attrs = Attributes.builder.put("http.route", "/orders").put("http.status_code", 200L).build
83
+
84
+ attrs.accept(new AttributeVisitor {
85
+ def visitString(key: String, value: String): Unit = println(s"$key=$value")
86
+ def visitLong(key: String, value: Long): Unit = println(s"$key=$value")
87
+ def visitDouble(key: String, value: Double): Unit = println(s"$key=$value")
88
+ def visitBoolean(key: String, value: Boolean): Unit = println(s"$key=$value")
89
+ })
90
+ ```
91
+
92
+ Those four are the only methods you must write. There are four more for sequence values, and they already do nothing — so if you store a sequence attribute and don't override its method, `accept` passes over it in silence. Nothing fails; the attribute simply never reaches your exporter.
93
+
94
+ The other form is for when convenience matters more than a few allocations, which is most code outside an exporter. `foreach` and `toMap` do the wrapping for you, handing each value over as an [`AttributeValue`](./any-value.md) — one wrapper per kind, so you can match on which kind you got:
95
+
96
+ ```scala
97
+ import zio.blocks.telemetry._
98
+
99
+ val attrs = Attributes.of(Attributes.ServiceName, "payments")
100
+
101
+ attrs.foreach { (key, value) =>
102
+ value match {
103
+ case AttributeValue.StringValue(s) => println(s"$key is text: $s")
104
+ case other => println(s"$key is $other")
105
+ }
106
+ }
107
+
108
+ val asMap: Map[String, AttributeValue] = attrs.toMap
109
+ ```
110
+
111
+ Two sets holding the same pairs are equal regardless of the order they were built in, so a test can compare an expected set directly against a recorded one.
112
+
113
+ ## See Also
114
+
115
+ - [AttributeKey](./attribute-key.md) — defining typed keys
116
+ - [AttributeValue](./any-value.md) — the boxed wrapper `foreach`/`toMap` hand back
117
+ - [Resource](./resource.md) — service identity, itself an `Attributes` set
118
+ - [Common Types](./index.md) — the types every pillar uses
@@ -0,0 +1,39 @@
1
+ ---
2
+ id: index
3
+ title: "Common Types"
4
+ description: "The four types every signal carries — Attributes and AttributeKey for its detail, Resource and InstrumentationScope for what produced it."
5
+ keywords:
6
+ - "Telemetry Metadata"
7
+ - "Signal Attributes"
8
+ - "Service Identity"
9
+ - "Common Types"
10
+ sidebar_label: "Common Types"
11
+ ---
12
+
13
+ These four types describe every signal, across all three telemetry pillars — tracing, logging, and metrics. Every span, log record, and metric data point is annotated with `Attributes`; every provider accepts a `Resource`; every scope instance is tagged with an `InstrumentationScope`. Understanding these four types unlocks the rest of the module.
14
+
15
+ ## Types
16
+
17
+ | Type | Description |
18
+ |------|-------------|
19
+ | [Attributes](./attributes.md) | Immutable, unboxed parallel-array collection of typed key-value pairs. Carried by every signal: `Span`, `LogRecord`, `Counter`, `Resource`, and `InstrumentationScope`. |
20
+ | [AttributeKey](./attribute-key.md) | Typed key for an `Attributes` entry. Binds a string name to one of eight value types (`String`, `Long`, `Double`, `Boolean`, and their `Seq` variants). |
21
+ | [AttributeValue](./any-value.md) | Boxed existential wrapper for the same eight kinds, used at API boundaries — `Logger`'s vararg attributes, `Span#setAttribute`, metric label maps — where the type isn't known ahead of time. |
22
+ | [Resource](./resource.md) | Immutable `Attributes` wrapper that describes the entity producing telemetry (service name, SDK version, deployment environment). Shared across all three providers. |
23
+ | [InstrumentationScope](./instrumentation-scope.md) | Named and versioned identity for the library or component that created a signal. Set when calling `TracerProvider.get`, `LoggerProvider.get`, or `MeterProvider.get`. |
24
+
25
+ ## Design
26
+
27
+ All four types are designed for hot-path telemetry code:
28
+
29
+ - **`Attributes`** stores `Long`, `Double`, and `Boolean` values unboxed in a parallel primitive array via bit-casting. Reading a value back boxes it — through `get`, `foreach`, or a conversion to `Map` — so hot paths that only write stay allocation-free.
30
+ - **`AttributeKey`** is a small case class carrying the name and the value type, so a typo in a name or a mismatched type is a compile error rather than a silently separate series.
31
+ - **`Resource`** is immutable and stamped onto a signal when it is created, not at export: `Tracer` puts it on every span and `Logger` on every log record. Metric instruments do not carry it — a `MeterProvider` holds a `Resource`, but the `Meter` and the collected `MetricData` never see it.
32
+ - **`InstrumentationScope`** is constructed once per scope by the provider and referenced from all signals that scope creates.
33
+
34
+ ## See Also
35
+
36
+ - [Telemetry](../index.md) — module overview and the three-pillar architecture
37
+ - [Tracing](../tracing/index.md) — span lifecycle types that use `Attributes` and `Resource`
38
+ - [Logging](../logging/index.md) — structured log record types that carry `Attributes`
39
+ - [Metrics](../metrics/index.md) — dimensional measurement types that use `Attributes` as labels
@@ -0,0 +1,24 @@
1
+ ---
2
+ id: instrumentation-scope
3
+ title: "InstrumentationScope"
4
+ description: "Identifies the library or component that produced a signal, so a backend can tell your telemetry apart from a dependency's."
5
+ keywords:
6
+ - "Telemetry Metadata"
7
+ - "Signal Origin"
8
+ - "Instrumentation Identity"
9
+ - "InstrumentationScope"
10
+ sidebar_label: "InstrumentationScope"
11
+ ---
12
+
13
+ `InstrumentationScope` records which library or component produced a signal. It's what lets a backend tell spans from your own code apart from spans emitted by a dependency, and group or filter by either.
14
+
15
+ ```scala
16
+ final case class InstrumentationScope(
17
+ name: String,
18
+ version: Option[String] = None,
19
+ attributes: Attributes = Attributes.empty
20
+ )
21
+ ```
22
+
23
+ You rarely name the type: it's built for you from the name you pass to `TracerProvider#get`, `LoggerProvider#get`, or `MeterProvider#get`, and every [`Span`](../tracing/span.md), [`SpanData`](../tracing/span-data.md), [`LogRecord`](../logging/log-record.md), [`Tracer`](../tracing/tracer.md), and [`Meter`](../metrics/meter.md) then carries it.
24
+
@@ -0,0 +1,34 @@
1
+ ---
2
+ id: resource
3
+ title: "Resource"
4
+ description: "Describes the entity producing telemetry (service, container, host). An immutable wrapper around Attributes shared by TracerProvider, LoggerProvider, and MeterProvider."
5
+ keywords:
6
+ - "Telemetry Metadata"
7
+ - "Resource Attributes"
8
+ - "Semantic Conventions"
9
+ - "Resource"
10
+ ---
11
+
12
+ `Resource` is an immutable wrapper around `Attributes` that describes the entity producing telemetry — the service, container, host, or runtime. It is stamped on every span and every log record so that a backend can group signals by their origin. All three provider types (`TracerProvider`, `LoggerProvider`, `MeterProvider`) accept a `Resource` at configuration time; `Tracer` and `Logger` propagate it onto the signals they emit, while metric instruments do not carry it — collected `MetricData` holds only the per-measurement `Attributes`.
13
+
14
+ ```scala
15
+ final case class Resource(attributes: Attributes)
16
+
17
+ object Resource {
18
+ val empty: Resource // no attributes
19
+ val default: Resource // service.name + telemetry.sdk.* attributes
20
+ def create(attrs: Attributes): Resource
21
+
22
+ // merge comes from an implicit class on the companion
23
+ implicit class ResourceOps(val self: Resource) {
24
+ def merge(other: Resource): Resource // other's attributes take precedence on duplicate keys
25
+ }
26
+ }
27
+ ```
28
+
29
+ ## Predefined Instances
30
+
31
+ | Instance | Description |
32
+ |--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
33
+ | `Resource.empty` | A `Resource` with no attributes. Use as a neutral base. |
34
+ | `Resource.default` | Pre-populated with `service.name = "unknown_service"`, `telemetry.sdk.name = "zio-blocks"`, `telemetry.sdk.language = "scala"`, and the SDK version from build info. |