@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.
- 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 -559
- 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/endpoint.md +1 -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.mdx +7 -2
- package/reference/openapi.md +3 -3
- package/reference/projection.md +654 -0
- package/reference/resource-management/index.md +1 -1
- 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/json/json.md +1 -0
- 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 +2 -2
- 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 +365 -185
- 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,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span-builder
|
|
3
|
+
title: "SpanBuilder"
|
|
4
|
+
description: "Mutable builder for creating spans with explicit kind, start timestamp, links, or parent context outside the normal Tracer.span lifecycle."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Manual Span Creation"
|
|
8
|
+
- "Explicit Span Configuration"
|
|
9
|
+
- "SpanBuilder"
|
|
10
|
+
sidebar_label: "SpanBuilder"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`SpanBuilder` is a mutable builder for creating a [`Span`](./span.md) by hand, outside the automatic [`trace.span`](./index.md) lifecycle, with control the `span(name, kind, attributes)` overloads cannot express: an explicit start timestamp, links to spans in other traces, or a non-default parent context.
|
|
14
|
+
|
|
15
|
+
Crucially, a span it starts bypasses the [`Tracer`](./tracer.md)'s [`Sampler`](./sampler.md) and [`SpanProcessor`](./span-processor.md) list — nothing samples it, no `onStart`/`onEnd` fires, and **it is never exported to a backend**. The span lives only in memory, readable via `toSpanData`, and you must `end()` it yourself. Use `SpanBuilder` for tests or local inspection; for any span that should reach your tracing pipeline, use `trace.span`.
|
|
16
|
+
|
|
17
|
+
```scala
|
|
18
|
+
object SpanBuilder {
|
|
19
|
+
def apply(name: String): SpanBuilder
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
final class SpanBuilder {
|
|
23
|
+
// Configuration
|
|
24
|
+
def setKind(kind: SpanKind): SpanBuilder
|
|
25
|
+
def setParent(parentContext: SpanContext): SpanBuilder
|
|
26
|
+
def setAttribute[A](key: AttributeKey[A], value: A): SpanBuilder
|
|
27
|
+
def addLink(link: SpanLink): SpanBuilder
|
|
28
|
+
def setStartTimestamp(nanos: Long): SpanBuilder
|
|
29
|
+
def setResource(resource: Resource): SpanBuilder
|
|
30
|
+
def setInstrumentationScope(scope: InstrumentationScope): SpanBuilder
|
|
31
|
+
|
|
32
|
+
// Finalization
|
|
33
|
+
def startSpan(): Span // parent's trace ID, or a random one at the root
|
|
34
|
+
def startSpan(traceIdHi: Long, traceIdLo: Long): Span // explicit trace ID
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
Obtain a pre-configured builder from `Tracer.spanBuilder` — it fills in the tracer's `Resource` and `InstrumentationScope` — set the metadata the `span` overloads cannot, then `startSpan()` and `end()` the span in a `try`/`finally`:
|
|
41
|
+
|
|
42
|
+
```scala
|
|
43
|
+
import zio.blocks.telemetry._
|
|
44
|
+
|
|
45
|
+
val tracer = TracerProvider.builder.build().get("com.example")
|
|
46
|
+
|
|
47
|
+
val span = tracer.spanBuilder("enqueue-message")
|
|
48
|
+
.setKind(SpanKind.Producer)
|
|
49
|
+
.addLink(SpanLink(SpanContext.invalid, Attributes.empty)) // in practice, an upstream context
|
|
50
|
+
.setStartTimestamp(System.nanoTime())
|
|
51
|
+
.startSpan()
|
|
52
|
+
|
|
53
|
+
try span.setAttribute("message.id", "msg-456")
|
|
54
|
+
finally span.end()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`SpanBuilder(name)` also builds one standalone, without a tracer. It is rarely what you want — the span it produces is attributed to `Resource.empty` and the scope name `"default"` rather than to your service and component, on top of reaching no sampler or processor. Reach for it only where no tracer exists yet, such as bridging a span in from another system. Note also that `startSpan()` marks the span sampled whenever there is no valid parent, so a standalone span always claims the sampled bit.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span-context
|
|
3
|
+
title: "SpanContext"
|
|
4
|
+
description: "Propagatable span identity: 128-bit trace ID (two Longs), SpanId, TraceFlags, trace state, and isRemote."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Context Propagation"
|
|
8
|
+
- "Trace Identity"
|
|
9
|
+
- "SpanContext"
|
|
10
|
+
sidebar_label: "SpanContext"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`SpanContext` is the propagatable identity of a span — the 128-bit trace ID (split into two `Long` fields to avoid boxing), the `SpanId`, the `TraceFlags`, a W3C trace-state string, and an `isRemote` flag that marks contexts extracted from an upstream request. It exists so telemetry from one request can be correlated across services and signals.
|
|
14
|
+
|
|
15
|
+
You rarely touch it directly: [`Tracer`](./tracer.md) generates one per span and logging stamps the active context onto every record automatically. Crossing a process boundary is explicit — a `Propagator` from the otel module injects it into outgoing headers and extracts it on the way in — so reach for it when you cross a boundary yourself. `SpanContext.invalid` is the sentinel for "no active span".
|
|
16
|
+
|
|
17
|
+
```scala
|
|
18
|
+
final case class SpanContext(
|
|
19
|
+
traceIdHi: Long, // high 64 bits of the 128-bit trace ID
|
|
20
|
+
traceIdLo: Long, // low 64 bits of the 128-bit trace ID
|
|
21
|
+
spanId: SpanId, // AnyVal wrapping a Long
|
|
22
|
+
traceFlags: TraceFlags, // AnyVal wrapping a Byte
|
|
23
|
+
traceState: String, // W3C tracestate header value
|
|
24
|
+
isRemote: Boolean // true when extracted from an incoming request
|
|
25
|
+
) {
|
|
26
|
+
def isValid: Boolean // true only when BOTH the trace ID and span ID are non-zero
|
|
27
|
+
def isSampled: Boolean // true when the sampled bit of traceFlags is set
|
|
28
|
+
def traceIdHex: String // 32-char lowercase hex trace ID
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
object SpanContext {
|
|
32
|
+
val invalid: SpanContext // sentinel: all-zero IDs, not sampled, not remote
|
|
33
|
+
def create(traceIdHi: Long, traceIdLo: Long, spanId: SpanId, traceFlags: TraceFlags,
|
|
34
|
+
traceState: String, isRemote: Boolean): SpanContext
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
`SpanContext` is read from `ContextStorage` by `Tracer.currentSpan` and by the logger on every emit for automatic trace–log correlation. [`SpanData`](./span-data.md) carries two of them: the span's own context and its parent's, where `SpanContext.invalid` marks a root span with no parent.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span-data
|
|
3
|
+
title: "SpanData"
|
|
4
|
+
description: "Immutable snapshot of a finished span — the read-only record a SpanProcessor exports."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Span Export"
|
|
8
|
+
- "Immutable Span Snapshot"
|
|
9
|
+
- "SpanData"
|
|
10
|
+
sidebar_label: "SpanData"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`SpanData` is an immutable, fully-populated snapshot of a finished span — its name, timing, attributes, events, status, and identity, captured when the span ends. You rarely handle it directly: it is the read-only record a [`SpanProcessor`](./span-processor.md) receives (`onEnd`) and serializes to a backend, and the value `trace.collectedSpans` returns for test assertions. You produce spans with [`trace.span`](./index.md), never `SpanData` itself.
|
|
14
|
+
|
|
15
|
+
```scala
|
|
16
|
+
final case class SpanData(
|
|
17
|
+
name: String,
|
|
18
|
+
kind: SpanKind,
|
|
19
|
+
spanContext: SpanContext,
|
|
20
|
+
parentSpanContext: SpanContext, // SpanContext.invalid for a root span
|
|
21
|
+
startTimeNanos: Long,
|
|
22
|
+
endTimeNanos: Long, // 0L if snapshotted before end()
|
|
23
|
+
attributes: Attributes,
|
|
24
|
+
events: List[SpanEvent],
|
|
25
|
+
links: List[SpanLink],
|
|
26
|
+
status: SpanStatus,
|
|
27
|
+
resource: Resource,
|
|
28
|
+
instrumentationScope: InstrumentationScope
|
|
29
|
+
)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Each field mirrors what the span recorded; a `SpanProcessor` or exporter reads them to ship the span to a backend (OTLP or another format).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span-kind
|
|
3
|
+
title: "SpanKind"
|
|
4
|
+
description: "SpanKind — the sealed enumeration classifying a span's role in a trace (Internal, Server, Client, Producer, Consumer) in the telemetry module's tracing area."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Span Classification"
|
|
8
|
+
- "SpanKind"
|
|
9
|
+
sidebar_label: "SpanKind"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
`SpanKind` is a sealed enumeration that classifies a span by its role in a trace — internal work, the client or server side of a synchronous RPC, or the producer or consumer side of an asynchronous message. It aligns with the [OpenTelemetry SpanKind specification](https://opentelemetry.io/docs/specs/otel/trace/api/#spankind), and a [`Tracer`](./tracer.md) records it on each [`Span`](./span.md) so backends can reconstruct client↔server and producer↔consumer relationships across services.
|
|
13
|
+
|
|
14
|
+
```scala
|
|
15
|
+
sealed trait SpanKind
|
|
16
|
+
object SpanKind {
|
|
17
|
+
case object Internal extends SpanKind
|
|
18
|
+
case object Server extends SpanKind
|
|
19
|
+
case object Client extends SpanKind
|
|
20
|
+
case object Producer extends SpanKind
|
|
21
|
+
case object Consumer extends SpanKind
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Each kind describes what the span covers and how it relates to a span in another process:
|
|
26
|
+
|
|
27
|
+
| Kind | Represents | Relationship in a trace |
|
|
28
|
+
|------------|----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
|
|
29
|
+
| `Internal` | Work performed internally in the application. The default when no kind is given. | No remote parent or child. |
|
|
30
|
+
| `Server` | The server side of a synchronous RPC — begins when the server starts processing the request and ends when it sends the response. | Usually the child of a remote `Client` span. |
|
|
31
|
+
| `Client` | The client side of a synchronous RPC — begins when the request is sent and ends when the response arrives. | Usually the parent of a remote `Server` span. |
|
|
32
|
+
| `Producer` | The producer side of an asynchronous message — begins when the message is sent and ends once it is dispatched. | Parent that often completes before the `Consumer` begins. |
|
|
33
|
+
| `Consumer` | The consumer side of an asynchronous message — begins when the message is received and ends when processing finishes. | Child of a `Producer` span. |
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
Pass a `SpanKind` as the second argument to [`trace.span`](./index.md) (or `Tracer#span`) to classify a span; omit it to accept the `Internal` default.
|
|
38
|
+
|
|
39
|
+
```scala
|
|
40
|
+
import zio.blocks.telemetry._
|
|
41
|
+
|
|
42
|
+
// Server span: handling an inbound request
|
|
43
|
+
trace.span("handle-order", SpanKind.Server) { _ =>
|
|
44
|
+
// Client span: an outbound call made while handling it
|
|
45
|
+
trace.span("charge-payment", SpanKind.Client)(_ => ())
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Setting the kind accurately lets a tracing backend pair a `Client` span in one service with the `Server` span it triggers in another, and a `Producer` span with the `Consumer` that eventually handles its message.
|
|
50
|
+
|
|
51
|
+
## See Also
|
|
52
|
+
|
|
53
|
+
- [Span](./span.md) — the unit of work a `SpanKind` classifies.
|
|
54
|
+
- [Tracing](./index.md) — the tracing overview and the `trace` entry point.
|
|
55
|
+
- [OpenTelemetry SpanKind specification](https://opentelemetry.io/docs/specs/otel/trace/api/#spankind) — the cross-language semantics this enumeration follows.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span-processor
|
|
3
|
+
title: "SpanProcessor"
|
|
4
|
+
description: "Hook for span lifecycle events (onStart, onEnd) in the telemetry module's tracing area. Implement to export or collect spans."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Span Export"
|
|
8
|
+
- "Lifecycle Hook"
|
|
9
|
+
- "SpanProcessor"
|
|
10
|
+
sidebar_label: "SpanProcessor"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`SpanProcessor` is the extension point exporter authors implement to do something with finished spans — ship them to a backend, buffer them, or collect them for tests. A [`Tracer`](./tracer.md) calls `onStart` when a recorded span begins — `RecordOnly` as well as `RecordAndSample` — and `onEnd` with the immutable [`SpanData`](./span-data.md) snapshot when it finishes. You rarely implement this directly: `SpanProcessor.noop` and the built-in in-memory collector cover development and testing, so you write one only to bridge spans to an export target such as OTLP.
|
|
14
|
+
|
|
15
|
+
```scala
|
|
16
|
+
trait SpanProcessor extends AutoCloseable {
|
|
17
|
+
def onStart(span: Span): Unit // span still mutable; RecordOnly + RecordAndSample
|
|
18
|
+
def onEnd(spanData: SpanData): Unit // immutable snapshot — export from here
|
|
19
|
+
def shutdown(): Unit // flush and release; called by TracerProvider.shutdown()
|
|
20
|
+
def forceFlush(): Unit // flush buffered data now
|
|
21
|
+
override def close(): Unit = shutdown()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
object SpanProcessor {
|
|
25
|
+
val noop: SpanProcessor // ignores every event
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Implementing a Processor
|
|
30
|
+
|
|
31
|
+
A custom processor forwards each `SpanData` to an export target. Register it on the provider with `addSpanProcessor`; when several are registered, they receive callbacks in insertion order.
|
|
32
|
+
|
|
33
|
+
`onEnd` runs synchronously, on the thread that just ended the span — so whatever it does lands in that request's latency. Keep it to handing the snapshot off to a queue or buffer, and let a background thread do the network call:
|
|
34
|
+
|
|
35
|
+
```scala
|
|
36
|
+
import zio.blocks.telemetry._
|
|
37
|
+
|
|
38
|
+
val exporter = new SpanProcessor {
|
|
39
|
+
def onStart(span: Span): Unit = ()
|
|
40
|
+
def onEnd(spanData: SpanData): Unit = println(s"[EXPORT] ${spanData.name}")
|
|
41
|
+
def shutdown(): Unit = ()
|
|
42
|
+
def forceFlush(): Unit = ()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
val provider = TracerProvider.builder.addSpanProcessor(exporter).build()
|
|
46
|
+
trace.install(provider)
|
|
47
|
+
trace.span("checkout") { _ => () } // prints: [EXPORT] checkout
|
|
48
|
+
provider.shutdown()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Integration
|
|
52
|
+
|
|
53
|
+
The global `trace` object's default provider already registers an `InMemorySpanProcessor`, so `trace.collectedSpans` and `trace.clearSpans` are available for test assertions without any additional setup.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span-status
|
|
3
|
+
title: "SpanStatus"
|
|
4
|
+
description: "SpanStatus — the sealed enumeration recording a span's completion outcome (Unset, Ok, Error) in the telemetry module's tracing area."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Span Outcome"
|
|
8
|
+
- "Completion Status"
|
|
9
|
+
- "SpanStatus"
|
|
10
|
+
sidebar_label: "SpanStatus"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`SpanStatus` records the outcome of the operation a [`Span`](./span.md) represents. The default is `SpanStatus.Unset`; instrumentation sets `Ok` on success or `Error(description)` on failure before the span's `end()`.
|
|
14
|
+
|
|
15
|
+
```scala
|
|
16
|
+
sealed trait SpanStatus
|
|
17
|
+
object SpanStatus {
|
|
18
|
+
case object Unset extends SpanStatus // default; outcome unknown or normal
|
|
19
|
+
case object Ok extends SpanStatus // explicit success
|
|
20
|
+
final case class Error(description: String) extends SpanStatus // explicit failure with description
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Set the status on the live span with `Span#setStatus` at any point before it ends:
|
|
25
|
+
|
|
26
|
+
```scala
|
|
27
|
+
import zio.blocks.telemetry._
|
|
28
|
+
|
|
29
|
+
val provider = TracerProvider.builder.build()
|
|
30
|
+
val tracer = provider.get("com.example")
|
|
31
|
+
|
|
32
|
+
tracer.span("process-payment") { span =>
|
|
33
|
+
val ok = true // result of processing
|
|
34
|
+
if (ok) span.setStatus(SpanStatus.Ok)
|
|
35
|
+
else span.setStatus(SpanStatus.Error("payment-gateway-timeout"))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
provider.shutdown()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`SpanStatus` becomes part of the exported [`SpanData`](./span-data.md) (`SpanData.status`) and is read by [`SpanProcessor`](./span-processor.md) implementations and test assertions.
|
|
42
|
+
|
|
43
|
+
## See Also
|
|
44
|
+
|
|
45
|
+
- [Span](./span.md) — the unit of work whose outcome `SpanStatus` records.
|
|
46
|
+
- [SpanKind](./span-kind.md) — the companion classification, set once at span creation.
|
|
47
|
+
- [Tracing](./index.md) — the tracing overview.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: span
|
|
3
|
+
title: "Span"
|
|
4
|
+
description: "A mutable, thread-safe unit of work in a distributed trace."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Span Lifecycle"
|
|
8
|
+
- "Unit of Work"
|
|
9
|
+
- "Span"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
`Span` is a mutable, thread-safe unit of work in a distributed trace — it records the name, kind, attributes, events, and outcome of one operation. You obtain a live `Span` from the higher-order [`trace.span`](./index.md) (or `Tracer#span`), which creates it, samples it, and ends it for you — you rarely create one directly.
|
|
13
|
+
|
|
14
|
+
Here is the full interface; the sections below cover the methods you reach for day to day:
|
|
15
|
+
|
|
16
|
+
```scala
|
|
17
|
+
trait Span {
|
|
18
|
+
// Identity — fixed at creation
|
|
19
|
+
def spanContext: SpanContext
|
|
20
|
+
def name: String
|
|
21
|
+
def kind: SpanKind
|
|
22
|
+
|
|
23
|
+
// Annotate — no-ops once the span has ended
|
|
24
|
+
def setAttribute[A](key: AttributeKey[A], value: A): Unit
|
|
25
|
+
def setAttribute(key: String, value: String): Unit
|
|
26
|
+
def setAttribute(key: String, value: Long): Unit
|
|
27
|
+
def setAttribute(key: String, value: Double): Unit
|
|
28
|
+
def setAttribute(key: String, value: Boolean): Unit
|
|
29
|
+
def addEvent(name: String): Unit
|
|
30
|
+
def addEvent(name: String, attributes: Attributes): Unit
|
|
31
|
+
def addEvent(name: String, timestamp: Long, attributes: Attributes): Unit
|
|
32
|
+
def setStatus(status: SpanStatus): Unit
|
|
33
|
+
|
|
34
|
+
// Lifecycle — managed for you by trace.span
|
|
35
|
+
def isRecording: Boolean
|
|
36
|
+
def end(): Unit
|
|
37
|
+
def end(endTimeNanos: Long): Unit
|
|
38
|
+
def toSpanData: SpanData
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
Open a span with `trace.span`: it hands your block a live `Span` and ends it automatically when the block returns. Inside, annotate the span with attributes, events, and a status:
|
|
45
|
+
|
|
46
|
+
```scala
|
|
47
|
+
import zio.blocks.telemetry._
|
|
48
|
+
|
|
49
|
+
trace.span("http.request", SpanKind.Server) { span =>
|
|
50
|
+
span.setAttribute("http.method", "GET")
|
|
51
|
+
span.setAttribute("http.status_code", 200L)
|
|
52
|
+
span.addEvent("auth.passed")
|
|
53
|
+
span.setStatus(SpanStatus.Ok)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`trace.span` manages the lifecycle: it ends the span when the block returns, and on end the span becomes an immutable [`SpanData`](./span-data.md) snapshot that `SpanProcessor`s receive (end-user code seldom reads it via `toSpanData` directly). For the rare cases `trace.span` can't cover — a custom start timestamp, links, or crossing an async boundary — [`SpanBuilder`](./span-builder.md) starts a span you `end()` yourself; it bypasses the sampler and processors, so prefer `trace.span`.
|
|
58
|
+
|
|
59
|
+
## Annotating a Span
|
|
60
|
+
|
|
61
|
+
The four convenience overloads cover the common value types; the typed `setAttribute[A](key, value)` form accepts any [`AttributeKey`](../common/attribute-key.md), including the sequence-valued ones (`AttributeKey.stringSeq` and friends) that have no shorthand.
|
|
62
|
+
|
|
63
|
+
Everything you do with a span happens inside the `trace.span` block, before it ends. Once the span ends, every `setAttribute`, `addEvent`, and `setStatus` call is silently ignored. If the sampler dropped the span you receive `Span.NoOp` — a no-op you can still call freely, so no guards are needed; check `isRecording` only to skip expensive annotation work for a dropped or ended span. Reading from a `NoOp` gives you blanks rather than errors: an invalid `spanContext`, an empty `name`, `SpanKind.Internal`, and `isRecording = false`.
|
|
64
|
+
|
|
65
|
+
### Attributes
|
|
66
|
+
|
|
67
|
+
Attach typed key-value pairs with `setAttribute` — there are convenience overloads for `String`, `Long`, `Double`, and `Boolean`. Setting the same key twice replaces the value:
|
|
68
|
+
|
|
69
|
+
```scala
|
|
70
|
+
import zio.blocks.telemetry._
|
|
71
|
+
|
|
72
|
+
trace.span("db.query") { span =>
|
|
73
|
+
span.setAttribute("db.system", "postgresql")
|
|
74
|
+
span.setAttribute("db.rows", 12L)
|
|
75
|
+
span.setAttribute("db.cached", false)
|
|
76
|
+
span.setAttribute("db.latency_ms", 3.14)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Events
|
|
81
|
+
|
|
82
|
+
Record a named point-in-time event with `addEvent`, optionally with its own attributes:
|
|
83
|
+
|
|
84
|
+
```scala
|
|
85
|
+
import zio.blocks.telemetry._
|
|
86
|
+
|
|
87
|
+
trace.span("payment.process") { span =>
|
|
88
|
+
span.addEvent("validation.passed")
|
|
89
|
+
span.addEvent("retry", Attributes.of(AttributeKey.long("attempt"), 2L))
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Status
|
|
94
|
+
|
|
95
|
+
Mark the outcome with `setStatus` — `SpanStatus.Ok` on success, `SpanStatus.Error(reason)` on failure (the default is `SpanStatus.Unset`):
|
|
96
|
+
|
|
97
|
+
```scala
|
|
98
|
+
import zio.blocks.telemetry._
|
|
99
|
+
|
|
100
|
+
trace.span("charge") { span =>
|
|
101
|
+
val paid = true
|
|
102
|
+
if (paid) span.setStatus(SpanStatus.Ok)
|
|
103
|
+
else span.setStatus(SpanStatus.Error("gateway timeout"))
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Identity
|
|
108
|
+
|
|
109
|
+
A span's `name`, `kind`, and [`spanContext`](./span-context.md) are set at creation and never change. `spanContext` is the span's identity — the trace and span IDs that let all the telemetry from one request be tied together.
|
|
110
|
+
|
|
111
|
+
You rarely touch it. Log correlation happens for you: logging stamps the active span's IDs onto every record automatically. Carrying the identity to another service is an explicit step — a `Propagator` from the otel module writes it into outgoing headers. Reach for `span.spanContext.traceIdHex` directly only in the low-level case — correlating with a system that isn't wired in, or crossing a boundary the instrumentation doesn't cover.
|
|
112
|
+
|
|
113
|
+
## Ending a Span
|
|
114
|
+
|
|
115
|
+
`trace.span` ends the span for you, including when the block throws — the span is closed on the way out and the exception propagates. Nothing sets an error status for you, though: a span whose block threw still reports `SpanStatus.Unset` unless you call `setStatus(SpanStatus.Error(...))` yourself.
|
|
116
|
+
|
|
117
|
+
Ending is idempotent. The first `end()` wins and any later call is silently ignored, so a `finally` block that ends a span already ended by `trace.span` is harmless. The `end(endTimeNanos)` overload exists for when you are replaying or bridging spans and need to state the finish time rather than take the clock's.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: tracer-provider
|
|
3
|
+
title: "TracerProvider"
|
|
4
|
+
description: "Root factory for distributed tracing: produces Tracer instances sharing a Resource, Sampler, SpanProcessors, and ContextStorage."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Tracing Configuration"
|
|
8
|
+
- "Tracer Factory"
|
|
9
|
+
- "TracerProvider"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
`TracerProvider` exists so tracing is configured once, in a single place. You set the service identity ([`Resource`](../common/resource.md)), the sampling policy ([`Sampler`](./sampler.md)), and where finished spans go ([`SpanProcessor`](./span-processor.md)s) when you build it at startup; from then on every [`Tracer`](./tracer.md) it hands out — and every span they create — shares that one configuration, so all your telemetry carries a consistent identity and policy. You build it once, install it, and rarely touch it again.
|
|
13
|
+
|
|
14
|
+
```scala
|
|
15
|
+
final class TracerProvider private[telemetry] (...) extends AutoCloseable {
|
|
16
|
+
def get(name: String, version: String = ""): Tracer // a Tracer for a named scope
|
|
17
|
+
|
|
18
|
+
def shutdown(): Unit // shut down every processor; call once at exit
|
|
19
|
+
def forceFlush(): Unit // ask processors to export buffered spans now
|
|
20
|
+
override def close(): Unit // alias for shutdown() — satisfies AutoCloseable
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
object TracerProvider {
|
|
24
|
+
def builder: TracerProviderBuilder
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
final class TracerProviderBuilder private[telemetry] (...) {
|
|
28
|
+
def setResource(resource: Resource): TracerProviderBuilder
|
|
29
|
+
def setSampler(sampler: Sampler): TracerProviderBuilder
|
|
30
|
+
def addSpanProcessor(processor: SpanProcessor): TracerProviderBuilder
|
|
31
|
+
def setContextStorage(contextStorage: ContextStorage[Option[SpanContext]]): TracerProviderBuilder
|
|
32
|
+
def build(): TracerProvider
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
Build a provider once at startup, set only what you need — a `Resource` for your service identity, a `Sampler`, and the `SpanProcessor`s that export your spans — then `get` a `Tracer` from it. Unset fields take defaults: `Resource.default` (whose `service.name` is the placeholder `unknown_service`) and `AlwaysOnSampler`, which records every span.
|
|
39
|
+
|
|
40
|
+
Do add a processor, though. The default processor list is **empty**, so a provider you build yourself samples spans and then discards them — nothing keeps or exports them. The in-memory buffer behind `trace.collectedSpans` belongs to the global `trace` object's own provider, not to yours:
|
|
41
|
+
|
|
42
|
+
```scala
|
|
43
|
+
import zio.blocks.telemetry._
|
|
44
|
+
|
|
45
|
+
val provider = TracerProvider.builder
|
|
46
|
+
.setResource(Resource.create(Attributes.of(Attributes.ServiceName, "payments")))
|
|
47
|
+
.setSampler(ParentBasedSampler(AlwaysOnSampler))
|
|
48
|
+
.addSpanProcessor(SpanProcessor.noop) // replace with an OTLP exporter
|
|
49
|
+
.build()
|
|
50
|
+
|
|
51
|
+
val tracer = provider.get("com.example.payments")
|
|
52
|
+
tracer.span("process-payment") { span =>
|
|
53
|
+
span.setAttribute("payment.id", "pay-001")
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
provider.shutdown()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Most applications never hold the provider directly. Install it once on the global `trace` object at startup and use [`trace.span`](./index.md) everywhere, removing the setup burden from individual call sites:
|
|
60
|
+
|
|
61
|
+
```scala
|
|
62
|
+
import zio.blocks.telemetry._
|
|
63
|
+
|
|
64
|
+
val provider = TracerProvider.builder
|
|
65
|
+
.setResource(Resource.create(Attributes.of(Attributes.ServiceName, "catalog")))
|
|
66
|
+
.addSpanProcessor(SpanProcessor.noop) // replace with your exporter
|
|
67
|
+
.build()
|
|
68
|
+
|
|
69
|
+
trace.install(provider)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Each `get` builds a new `Tracer` — there is no caching — so take one per component at startup and hold it, rather than calling `get` inside a request. Passing a `version` alongside the name records it on the scope, which is how you tell spans from two releases of the same library apart.
|
|
73
|
+
|
|
74
|
+
## Lifecycle
|
|
75
|
+
|
|
76
|
+
Call `shutdown()` once when the app exits — it forwards to every registered processor so each can flush what it is holding and release its resources. `forceFlush()` does the flushing without the release, for when you want buffered spans exported now.
|
|
77
|
+
|
|
78
|
+
`shutdown()` does not disable the provider: it still hands out tracers and still records spans afterwards, they just reach processors that have already been shut down. Treat it as the last thing you call, not a switch you can toggle. Since a provider is `AutoCloseable` — `close()` is an alias for `shutdown()` — you can also let the language make that call:
|
|
79
|
+
|
|
80
|
+
```scala
|
|
81
|
+
import zio.blocks.telemetry._
|
|
82
|
+
import scala.util.Using
|
|
83
|
+
|
|
84
|
+
Using.resource(TracerProvider.builder.addSpanProcessor(SpanProcessor.noop).build()) { provider =>
|
|
85
|
+
provider.get("com.example").span("startup")(_ => ())
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Trace–Log Correlation
|
|
90
|
+
|
|
91
|
+
Logs emitted inside a span are correlated with it automatically: a `TracerProvider` and a `LoggerProvider` share the same default context storage, so every log record carries that span's trace and span IDs with no wiring. (Override `setContextStorage` on both only to isolate correlation — e.g. in tests.) See the [Telemetry module index](../index.md).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: tracer
|
|
3
|
+
title: "Tracer"
|
|
4
|
+
description: "Reference page for Tracer, the span-creation engine in the telemetry module's tracing area."
|
|
5
|
+
keywords:
|
|
6
|
+
- "Distributed Tracing"
|
|
7
|
+
- "Span Creation"
|
|
8
|
+
- "Trace Instrumentation"
|
|
9
|
+
- "Tracer"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
`Tracer` creates spans within a single instrumentation scope — a named library or component. Call `Tracer#span` to wrap a block of work in a timed, attributed span; the tracer consults the configured [`Sampler`](./sampler.md), propagates the parent context so nested spans inherit the right trace, and notifies each [`SpanProcessor`](./span-processor.md) as spans start and end.
|
|
13
|
+
|
|
14
|
+
Library code takes a `Tracer` — obtained from a [`TracerProvider`](./tracer-provider.md) — to tag its spans with its own scope; application code usually prefers the global [`trace.span`](./index.md), which manages a tracer for you. A `Tracer` is always produced by a `TracerProvider` and cannot be constructed directly.
|
|
15
|
+
|
|
16
|
+
```scala
|
|
17
|
+
final class Tracer private[telemetry] (...) {
|
|
18
|
+
val instrumentationScope: InstrumentationScope
|
|
19
|
+
val resource: Resource
|
|
20
|
+
|
|
21
|
+
// Wrap a block in a span — three progressive overloads
|
|
22
|
+
def span[A](name: String)(f: Span => A): A
|
|
23
|
+
def span[A](name: String, kind: SpanKind)(f: Span => A): A
|
|
24
|
+
def span[A](name: String, kind: SpanKind, attributes: Attributes)(f: Span => A): A
|
|
25
|
+
|
|
26
|
+
// Manual span creation (advanced)
|
|
27
|
+
def spanBuilder(name: String): SpanBuilder
|
|
28
|
+
|
|
29
|
+
// The active span context, or None outside any span
|
|
30
|
+
def currentSpan: Option[SpanContext]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
Obtain a `Tracer` from a provider (or `trace.get` in application code), then wrap work in `span`. The three overloads add control progressively: `span(name)` defaults to `SpanKind.Internal`, `span(name, kind)` sets the kind, and `span(name, kind, attributes)` also seeds initial attributes. Nested `span` calls inherit the parent trace automatically:
|
|
37
|
+
|
|
38
|
+
```scala
|
|
39
|
+
import zio.blocks.telemetry._
|
|
40
|
+
|
|
41
|
+
val tracer = TracerProvider.builder.build().get("com.example.orders")
|
|
42
|
+
|
|
43
|
+
tracer.span("process-order", SpanKind.Server) { span =>
|
|
44
|
+
span.setAttribute("order.id", "ord-123")
|
|
45
|
+
|
|
46
|
+
tracer.span("persist-order", SpanKind.Client) { inner =>
|
|
47
|
+
inner.setAttribute("db.system", "postgresql")
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For advanced needs — a manual span lifecycle via [`SpanBuilder`](./span-builder.md) (local-only, never exported) or reading the active context with `currentSpan` (a [`SpanContext`](./span-context.md)) — see those pages. For all normal work, `span` is enough.
|
package/reference/typeid.md
CHANGED
|
@@ -2527,22 +2527,6 @@ cd zio-blocks
|
|
|
2527
2527
|
Demonstrates deriving TypeIds for case classes, accessing their properties (name, fullName, owner, arity), using predefined TypeIds for built-in types, and implicit derivation:
|
|
2528
2528
|
|
|
2529
2529
|
```scala title="schema-examples/src/main/scala/typeid/TypeIdBasicExample.scala"
|
|
2530
|
-
/*
|
|
2531
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
2532
|
-
*
|
|
2533
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
2534
|
-
* you may not use this file except in compliance with the License.
|
|
2535
|
-
* You may obtain a copy of the License at
|
|
2536
|
-
*
|
|
2537
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
2538
|
-
*
|
|
2539
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
2540
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
2541
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
2542
|
-
* See the License for the specific language governing permissions and
|
|
2543
|
-
* limitations under the License.
|
|
2544
|
-
*/
|
|
2545
|
-
|
|
2546
2530
|
package typeid
|
|
2547
2531
|
|
|
2548
2532
|
import zio.blocks.typeid.*
|
|
@@ -2789,22 +2773,6 @@ sbt "schema-examples/runMain typeid.TypeIdBasicExample"
|
|
|
2789
2773
|
Demonstrates subtype checking with `isSubtypeOf`, `isSupertypeOf`, and `isEquivalentTo`, including direct inheritance, transitive inheritance, sealed trait cases, and variance-aware subtyping for applied types like `List[Dog] <: List[Animal]`:
|
|
2790
2774
|
|
|
2791
2775
|
```scala title="schema-examples/src/main/scala/typeid/TypeIdSubtypingExample.scala"
|
|
2792
|
-
/*
|
|
2793
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
2794
|
-
*
|
|
2795
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
2796
|
-
* you may not use this file except in compliance with the License.
|
|
2797
|
-
* You may obtain a copy of the License at
|
|
2798
|
-
*
|
|
2799
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
2800
|
-
*
|
|
2801
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
2802
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
2803
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
2804
|
-
* See the License for the specific language governing permissions and
|
|
2805
|
-
* limitations under the License.
|
|
2806
|
-
*/
|
|
2807
|
-
|
|
2808
2776
|
package typeid
|
|
2809
2777
|
|
|
2810
2778
|
import zio.blocks.typeid._
|
|
@@ -2912,22 +2880,6 @@ sbt "schema-examples/runMain typeid.TypeIdSubtypingExample"
|
|
|
2912
2880
|
Demonstrates type alias handling, normalization to underlying types, structural equality, and building type-indexed registries using erased TypeIds:
|
|
2913
2881
|
|
|
2914
2882
|
```scala title="schema-examples/src/main/scala/typeid/TypeIdNormalizationExample.scala"
|
|
2915
|
-
/*
|
|
2916
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
2917
|
-
*
|
|
2918
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
2919
|
-
* you may not use this file except in compliance with the License.
|
|
2920
|
-
* You may obtain a copy of the License at
|
|
2921
|
-
*
|
|
2922
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
2923
|
-
*
|
|
2924
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
2925
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
2926
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
2927
|
-
* See the License for the specific language governing permissions and
|
|
2928
|
-
* limitations under the License.
|
|
2929
|
-
*/
|
|
2930
|
-
|
|
2931
2883
|
package typeid
|
|
2932
2884
|
|
|
2933
2885
|
import zio.blocks.typeid._
|
|
@@ -3044,22 +2996,6 @@ sbt "schema-examples/runMain typeid.TypeIdNormalizationExample"
|
|
|
3044
2996
|
Demonstrates how TypeId preserves the semantic distinction of opaque types, enabling runtime type safety that pure Scala reflection cannot provide. Shows building type-indexed validator registries keyed by opaque type identity:
|
|
3045
2997
|
|
|
3046
2998
|
```scala title="schema-examples/src/main/scala/typeid/OpaqueTypesExample.scala"
|
|
3047
|
-
/*
|
|
3048
|
-
* Copyright 2024-2026 John A. De Goes and the ZIO Contributors
|
|
3049
|
-
*
|
|
3050
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3051
|
-
* you may not use this file except in compliance with the License.
|
|
3052
|
-
* You may obtain a copy of the License at
|
|
3053
|
-
*
|
|
3054
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3055
|
-
*
|
|
3056
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
3057
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3058
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3059
|
-
* See the License for the specific language governing permissions and
|
|
3060
|
-
* limitations under the License.
|
|
3061
|
-
*/
|
|
3062
|
-
|
|
3063
2999
|
package typeid
|
|
3064
3000
|
|
|
3065
3001
|
import zio.blocks.typeid._
|