@zio.dev/zio-blocks 0.0.51 → 0.0.55
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.
- package/adr/2026-07-18-data-migration.md +123 -0
- package/guides/async-getting-started.md +687 -0
- package/guides/compile-time-resource-safety-with-scope.md +6 -0
- package/guides/getting-started-with-mux.md +0 -112
- package/guides/query-dsl-extending.md +1 -1
- package/guides/query-dsl-fluent-builder.md +1 -1
- package/guides/query-dsl-reified-optics.md +1 -1
- package/guides/query-dsl-sql.md +395 -1
- package/guides/sql-checked-interpolation.md +173 -0
- package/guides/sql-transactions.md +286 -0
- package/guides/telemetry-guide.md +131 -70
- package/guides/zio-schema-migration.md +6 -6
- package/index.md +200 -583
- package/package.json +1 -1
- package/reference/async.md +1379 -531
- package/reference/chunk.md +3 -3
- package/reference/codegen/index.md +1 -1
- package/reference/combinators.md +4 -4
- package/reference/config/config-decoder.md +460 -0
- package/reference/config/config-source.md +489 -0
- package/reference/config/errors.md +278 -0
- package/reference/config/flags.md +369 -0
- package/reference/config/formats.md +314 -0
- package/reference/config/index.md +304 -0
- package/reference/config/rollout.md +336 -0
- package/reference/context.md +6 -49
- package/reference/data-migration.md +269 -0
- package/reference/datastar/attributes.md +302 -0
- package/reference/datastar/events.md +234 -0
- package/reference/datastar/index.md +256 -0
- package/reference/datastar/signals.md +230 -0
- package/reference/datastar/sse.md +295 -0
- package/reference/datastar.md +2 -2
- package/reference/docs.md +2 -2
- package/reference/endpoint/bulk-creation.md +96 -0
- package/reference/endpoint/index.md +9 -89
- package/reference/endpoint/path-codec.md +12 -24
- package/reference/endpoint/route-pattern.md +4 -6
- package/reference/endpoint/segment-codec.md +19 -32
- package/reference/html.md +313 -9
- package/reference/htmx/index.md +4 -52
- package/reference/htmx/response-headers.md +240 -0
- package/reference/http-model/headers.md +735 -0
- package/reference/http-model/index.md +3 -1
- package/reference/http-model/model.md +107 -71
- package/reference/http-model/schema-codecs.md +522 -0
- package/reference/http-model/schema.md +6 -3
- package/reference/http-model/server-sent-event.md +341 -0
- package/reference/jwt.md +195 -0
- package/reference/maybe.md +128 -11
- package/reference/media-type.md +2 -2
- package/reference/mux.md +254 -0
- package/reference/mux.mdx +7 -2
- package/reference/openapi.md +3 -3
- package/reference/projection.md +654 -0
- package/reference/resource-management/resource.md +2 -98
- package/reference/resource-management/scope.md +1 -209
- package/reference/resource-management/wire.md +4 -50
- package/reference/ringbuffer/advanced.mdx +1 -1
- package/reference/ringbuffer/index.mdx +3 -3
- package/reference/ringbuffer/mpmc.mdx +38 -4
- package/reference/ringbuffer/mpsc.mdx +36 -4
- package/reference/ringbuffer/spmc.mdx +1 -1
- package/reference/ringbuffer/spsc.mdx +87 -15
- package/reference/schema/allows.md +0 -96
- package/reference/schema/binding.md +2 -2
- package/reference/schema/built-in-codecs/avro.md +2 -2
- package/reference/schema/built-in-codecs/bson.md +50 -20
- package/reference/schema/built-in-codecs/csv.md +2 -2
- package/reference/schema/built-in-codecs/index.md +3 -3
- package/reference/schema/built-in-codecs/json/index.md +2 -2
- package/reference/schema/built-in-codecs/messagepack.md +3 -3
- package/reference/schema/built-in-codecs/thrift.md +2 -2
- package/reference/schema/built-in-codecs/toon.md +3 -3
- package/reference/schema/built-in-codecs/yaml.md +2 -2
- package/reference/schema/codec.md +11 -11
- package/reference/schema/dynamic-optic.md +48 -3
- package/reference/schema/dynamic-schema.md +3 -3
- package/reference/schema/index.md +2 -0
- package/reference/schema/path-interpolator.md +2 -0
- package/reference/schema/reflect-transformer.md +140 -0
- package/reference/schema/schema-evolution/as.md +4 -4
- package/reference/schema/schema-evolution/into.md +2 -2
- package/reference/schema/schema-expr.md +2 -2
- package/reference/schema/schema-search.md +263 -0
- package/reference/schema/schema.md +10 -2
- package/reference/schema/type-class-derivation.md +1 -1
- package/reference/smithy.md +502 -3
- package/reference/sql/db-codec-deriver.md +3 -3
- package/reference/sql/db-codec.md +22 -22
- package/reference/sql/db-con.md +4 -4
- package/reference/sql/db-connection.md +1 -1
- package/reference/sql/db-param.md +1 -1
- package/reference/sql/db-result-reader.md +4 -2
- package/reference/sql/db-tx.md +46 -14
- package/reference/sql/ddl.md +1 -1
- package/reference/sql/frag.md +44 -10
- package/reference/sql/index.md +7 -7
- package/reference/sql/repo.md +15 -15
- package/reference/sql/sql-dialect.md +1 -1
- package/reference/sql/sql-logger.md +1 -1
- package/reference/sql/sql-name-mapper.md +3 -3
- package/reference/sql/table-metadata.md +3 -3
- package/reference/sql/table.md +10 -10
- package/reference/sql/transactor-zio.md +1 -1
- package/reference/sql/transactor.md +21 -11
- package/reference/sql-zio.md +1 -1
- package/reference/streams/core/index.md +32 -0
- package/reference/streams/{pipeline.md → core/pipeline.md} +210 -74
- package/reference/streams/{sink.md → core/sink.md} +331 -353
- package/reference/streams/{stream.md → core/stream.md} +919 -209
- package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
- package/reference/streams/execution-and-compatibility/index.md +35 -0
- package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
- package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
- package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
- package/reference/streams/index.md +140 -67
- package/reference/streams/primitives/index.md +30 -0
- package/reference/streams/primitives/reader.md +1992 -0
- package/reference/streams/{writer.md → primitives/writer.md} +254 -98
- package/reference/telemetry/common/any-value.md +90 -0
- package/reference/telemetry/common/attribute-key.md +87 -0
- package/reference/telemetry/common/attributes.md +118 -0
- package/reference/telemetry/common/index.md +39 -0
- package/reference/telemetry/common/instrumentation-scope.md +24 -0
- package/reference/telemetry/common/resource.md +34 -0
- package/reference/telemetry/index.md +311 -0
- package/reference/telemetry/logging/index.md +197 -0
- package/reference/telemetry/logging/log-enrichment.md +72 -0
- package/reference/telemetry/logging/log-formatter.md +100 -0
- package/reference/telemetry/logging/log-record-processor.md +56 -0
- package/reference/telemetry/logging/log-record.md +44 -0
- package/reference/telemetry/logging/log-writer.md +64 -0
- package/reference/telemetry/logging/logger-provider.md +142 -0
- package/reference/telemetry/logging/logger.md +83 -0
- package/reference/telemetry/logging/severity.md +62 -0
- package/reference/telemetry/metrics/index.md +150 -0
- package/reference/telemetry/metrics/instruments.md +183 -0
- package/reference/telemetry/metrics/labeled-instruments.md +74 -0
- package/reference/telemetry/metrics/meter-provider.md +76 -0
- package/reference/telemetry/metrics/meter.md +98 -0
- package/reference/telemetry/metrics/metric-data.md +57 -0
- package/reference/telemetry/otel/custom-exporter.md +216 -0
- package/reference/telemetry/otel/index.md +212 -0
- package/reference/telemetry/tracing/index.md +155 -0
- package/reference/telemetry/tracing/sampler.md +89 -0
- package/reference/telemetry/tracing/span-builder.md +57 -0
- package/reference/telemetry/tracing/span-context.md +39 -0
- package/reference/telemetry/tracing/span-data.md +32 -0
- package/reference/telemetry/tracing/span-kind.md +55 -0
- package/reference/telemetry/tracing/span-processor.md +53 -0
- package/reference/telemetry/tracing/span-status.md +47 -0
- package/reference/telemetry/tracing/span.md +117 -0
- package/reference/telemetry/tracing/tracer-provider.md +91 -0
- package/reference/telemetry/tracing/tracer.md +52 -0
- package/reference/typeid.md +0 -64
- package/sidebars.js +150 -12
- package/undocumented-report.md +528 -270
- package/reference/config.md +0 -158
- package/reference/streams/concurrent-operators.md +0 -106
- package/reference/streams/reader.md +0 -1284
- package/reference/streams/scala-2-compatibility.md +0 -55
- package/reference/streams/zero-boxing.md +0 -275
- 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. |
|