Skip to content

Commit 226ecf4

Browse files
committed
feat: add metrics and refactor tracing
Signed-off-by: Andrew Steurer <[email protected]>
1 parent 885283c commit 226ecf4

File tree

8 files changed

+436
-8
lines changed

8 files changed

+436
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Phase 0
99
### Champions
1010

1111
- [Caleb Schoepp](https://github.com/calebschoepp)
12+
- [Andrew Steurer](https://github.com/asteurer)
1213

1314
### Portability Criteria
1415

wit/deps/example-dep/example-api.wit

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package wasi:clocks@0.2.0;
2+
3+
/// WASI Monotonic Clock is a clock API intended to let users measure elapsed
4+
/// time.
5+
///
6+
/// It is intended to be portable at least between Unix-family platforms and
7+
/// Windows.
8+
///
9+
/// A monotonic clock is a clock which has an unspecified initial value, and
10+
/// successive reads of the clock will produce non-decreasing values.
11+
///
12+
/// It is intended for measuring elapsed time.
13+
interface monotonic-clock {
14+
use wasi:io/poll@0.2.0.{pollable};
15+
16+
/// An instant in time, in nanoseconds. An instant is relative to an
17+
/// unspecified initial value, and can only be compared to instances from
18+
/// the same monotonic-clock.
19+
type instant = u64;
20+
21+
/// A duration of time, in nanoseconds.
22+
type duration = u64;
23+
24+
/// Read the current value of the clock.
25+
///
26+
/// The clock is monotonic, therefore calling this function repeatedly will
27+
/// produce a sequence of non-decreasing values.
28+
now: func() -> instant;
29+
30+
/// Query the resolution of the clock. Returns the duration of time
31+
/// corresponding to a clock tick.
32+
resolution: func() -> duration;
33+
34+
/// Create a `pollable` which will resolve once the specified instant
35+
/// occured.
36+
subscribe-instant: func(when: instant) -> pollable;
37+
38+
/// Create a `pollable` which will resolve once the given duration has
39+
/// elapsed, starting at the time at which this function was called.
40+
/// occured.
41+
subscribe-duration: func(when: duration) -> pollable;
42+
}
43+
44+
/// WASI Wall Clock is a clock API intended to let users query the current
45+
/// time. The name "wall" makes an analogy to a "clock on the wall", which
46+
/// is not necessarily monotonic as it may be reset.
47+
///
48+
/// It is intended to be portable at least between Unix-family platforms and
49+
/// Windows.
50+
///
51+
/// A wall clock is a clock which measures the date and time according to
52+
/// some external reference.
53+
///
54+
/// External references may be reset, so this clock is not necessarily
55+
/// monotonic, making it unsuitable for measuring elapsed time.
56+
///
57+
/// It is intended for reporting the current date and time for humans.
58+
interface wall-clock {
59+
/// A time and date in seconds plus nanoseconds.
60+
record datetime {
61+
seconds: u64,
62+
nanoseconds: u32,
63+
}
64+
65+
/// Read the current value of the clock.
66+
///
67+
/// This clock is not monotonic, therefore calling this function repeatedly
68+
/// will not necessarily produce a sequence of non-decreasing values.
69+
///
70+
/// The returned timestamps represent the number of seconds since
71+
/// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],
72+
/// also known as [Unix Time].
73+
///
74+
/// The nanoseconds field of the output is always less than 1000000000.
75+
///
76+
/// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16
77+
/// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time
78+
now: func() -> datetime;
79+
80+
/// Query the resolution of the clock.
81+
///
82+
/// The nanoseconds field of the output is always less than 1000000000.
83+
resolution: func() -> datetime;
84+
}
85+
86+
world imports {
87+
import wasi:io/poll@0.2.0;
88+
import monotonic-clock;
89+
import wall-clock;
90+
}

wit/deps/wasi-io-0.2.0/package.wit

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package wasi:io@0.2.0;
2+
3+
interface poll {
4+
resource pollable {
5+
ready: func() -> bool;
6+
block: func();
7+
}
8+
9+
poll: func(in: list<borrow<pollable>>) -> list<u32>;
10+
}
11+

wit/metrics.wit

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
interface metrics {
2+
use wasi:clocks/wall-clock@0.2.0.{datetime};
3+
use wasi:clocks/monotonic-clock@0.2.0.{duration};
4+
use types.{key-value, instrumentation-scope};
5+
use tracing.{span-id, trace-id};
6+
7+
/// `collect` gathers all metric data related to a Reader from the SDK
8+
collect: func(metrics: resource-metrics) -> result<_, otel-error>;
9+
10+
/// `resource-metrics` is a collection of `scope-metrics` and the associated `resource`
11+
/// that created them.
12+
///
13+
/// See https://github.com/open-telemetry/opentelemetry-rust/blob/c811cde1ae21c624870c1b952190e687b16f76b8/opentelemetry-sdk/src/metrics/data/mod.rs#L13
14+
record resource-metrics {
15+
/// The entity that collected the metrics.
16+
%resource: %resource,
17+
/// The collection of metrics with unique `instrumentation-scope`s.
18+
scope-metrics: list<scope-metrics>,
19+
}
20+
21+
/// An immutable representation of the entity producing telemetry as attributes.
22+
record %resource {
23+
inner: resource-inner,
24+
}
25+
26+
/// Inner structure of `resource` holding the actual data.
27+
record resource-inner {
28+
attributes: list<key-value>,
29+
schema-url: option<string>,
30+
}
31+
32+
/// `scope-metrics` is a collection of `metric`s produced by a meter.
33+
record scope-metrics {
34+
/// The `instrumentation-scope` that the meter was created with.
35+
scope: instrumentation-scope,
36+
/// The list of aggregations created by the meter.
37+
metrics: list<metric>,
38+
}
39+
40+
/// `metric` is a collection of one or more aggregated time series from an instrument
41+
record metric {
42+
/// The name of the instrument that created this data.
43+
name: string,
44+
/// The description of the instrument, which can be used in documentation.
45+
description: string,
46+
/// The unit in which the instrument reports.
47+
unit: string,
48+
/// The aggregated data from an instrument.
49+
data: aggregated-metrics,
50+
}
51+
52+
/// Aggregated metrics data from an instrument.
53+
variant aggregated-metrics {
54+
/// All metric data with `f64` value type.
55+
%f64(metric-data),
56+
/// All metric data with `u64` value type.
57+
%u64(metric-data),
58+
/// All metric data with `s64` value type.
59+
%s64(metric-data),
60+
}
61+
62+
/// Metric data for all types.
63+
variant metric-data {
64+
/// Metric data for `gauge`.
65+
gauge(gauge),
66+
/// Metric data for `sum`.
67+
sum(sum),
68+
/// Metric data for `histogram`.
69+
histogram(histogram),
70+
/// Metric data for `exponential-histogram`.
71+
exponential-histogram(exponential-histogram),
72+
}
73+
74+
/// A measurement of the current value of an instrument.
75+
record gauge {
76+
/// Represents individual aggregated measurements with unique attributes.
77+
data-points: list<gauge-data-point>,
78+
/// The time when the time series was started.
79+
start-time: option<datetime>,
80+
/// The time when the time series was recorded.
81+
time: datetime,
82+
}
83+
84+
/// `gauge-data-point` is a single data point in a time series.
85+
record gauge-data-point {
86+
/// `attributes` is the set of key value pairs that uniquely identify the
87+
/// time series.
88+
attributes: list<key-value>,
89+
/// The value of this data point.
90+
value: metric-number,
91+
/// The sampled `exemplar`s collected during the time series.
92+
exemplars: list<exemplar>,
93+
}
94+
95+
/// Represents the sum of all measurements of values from an instrument.
96+
record sum {
97+
/// Represents individual aggregated measurements with unique attributes.
98+
data-points: list<sum-data-point>,
99+
/// The time when the time series was started.
100+
start-time: datetime,
101+
/// The time when the time series was recorded.
102+
time: datetime,
103+
/// Describes if the aggregation is reported as the change from the last report
104+
/// time, or the cumulative changes since a fixed start time.
105+
temporality: temporality,
106+
/// Whether this aggregation only increases or decreases.
107+
is-monotonic: bool,
108+
}
109+
110+
/// `sum-data-point` is a single data point in a time series.
111+
record sum-data-point {
112+
/// `attributes` is the set of key value pairs that uniquely identify the
113+
/// time series.
114+
attributes: list<key-value>,
115+
/// The value of this data point.
116+
value: metric-number,
117+
/// The sampled `exemplar`s collected during the time series.
118+
exemplars: list<exemplar>,
119+
}
120+
121+
/// Represents the histogram of all measurements of values from an instrument.
122+
record histogram {
123+
/// Individual aggregated measurements with unique attributes.
124+
data-points: list<histogram-data-point>,
125+
/// The time when the time series was started.
126+
start-time: datetime,
127+
/// The time when the time series was recorded.
128+
time: datetime,
129+
/// Describes if the aggregation is reported as the change from the last report
130+
/// time, or the cumulative changes since a fixed start time.
131+
temporality: temporality,
132+
}
133+
134+
/// A single histogram data point in a time series.
135+
record histogram-data-point {
136+
/// The set of key value pairs that uniquely identify the time series.
137+
attributes: list<key-value>,
138+
/// The number of updates this histogram has been calculated with.
139+
count: u64,
140+
/// The upper bounds of the buckets of the histogram.
141+
bounds: list<f64>,
142+
/// The count of each of the buckets.
143+
bucket-counts: list<u64>,
144+
/// The minimum value recorded.
145+
min: option<metric-number>,
146+
/// The maximum value recorded.
147+
max: option<metric-number>,
148+
/// The sum of the values recorded
149+
sum: metric-number,
150+
/// The sampled `exemplar`s collected during the time series.
151+
exemplars: list<exemplar>,
152+
}
153+
154+
/// The histogram of all measurements of values from an instrument.
155+
record exponential-histogram {
156+
/// The individual aggregated measurements with unique attributes.
157+
data-points: list<exponential-histogram-data-point>,
158+
/// When the time series was started.
159+
start-time: datetime,
160+
/// The time when the time series was recorded.
161+
time: datetime,
162+
/// Describes if the aggregation is reported as the change from the last report
163+
/// time, or the cumulative changes since a fixed start time.
164+
temporality: temporality,
165+
}
166+
167+
/// A single exponential histogram data point in a time series.
168+
record exponential-histogram-data-point {
169+
/// The set of key value pairs that uniquely identify the time series.
170+
attributes: list<key-value>,
171+
/// The number of updates this histogram has been calculated with.
172+
count: u64, // TODO: check that u64 is an acceptable replacement for usize
173+
/// The minimum value recorded.
174+
min: option<metric-number>,
175+
/// The maximum value recorded.
176+
max: option<metric-number>,
177+
/// The maximum value recorded.
178+
sum: metric-number,
179+
/// Describes the resolution of the histogram.
180+
///
181+
/// Boundaries are located at powers of the base, where:
182+
///
183+
/// base = 2 ^ (2 ^ -scale)
184+
scale: s8,
185+
/// The number of values whose absolute value is less than or equal to
186+
/// `zero_threshold`.
187+
///
188+
/// When `zero_threshold` is `0`, this is the number of values that cannot be
189+
/// expressed using the standard exponential formula as well as values that have
190+
/// been rounded to zero.
191+
zero-count: u64,
192+
/// The range of positive value bucket counts.
193+
positive-bucket: exponential-bucket,
194+
/// The range of negative value bucket counts.
195+
negative-bucket: exponential-bucket,
196+
/// The width of the zero region.
197+
///
198+
/// Where the zero region is defined as the closed interval
199+
/// [-zero_threshold, zero_threshold].
200+
zero-threshold: f64,
201+
/// The sampled exemplars collected during the time series.
202+
exemplars: list<exemplar>,
203+
}
204+
205+
/// A set of bucket counts, encoded in a contiguous array of counts.
206+
record exponential-bucket {
207+
/// The bucket index of the first entry in the `counts` list.
208+
offset: s32,
209+
/// A list where `counts[i]` carries the count of the bucket at index `offset + i`.
210+
///
211+
/// `counts[i]` is the count of values greater than base^(offset+i) and less than
212+
/// or equal to base^(offset+i+1).
213+
counts: list<u64>,
214+
}
215+
216+
/// A measurement sampled from a time series providing a typical example.
217+
record exemplar {
218+
/// The attributes recorded with the measurement but filtered out of the
219+
/// time series' aggregated data.
220+
filtered-attributes: list<key-value>,
221+
/// The time when the measurement was recorded.
222+
time: datetime,
223+
/// The measured value.
224+
value: metric-number,
225+
/// The ID of the span that was active during the measurement.
226+
///
227+
/// If no span was active or the span was not sampled this will be empty.
228+
span-id: span-id,
229+
/// The ID of the trace the active span belonged to during the measurement.
230+
///
231+
/// If no span was active or the span was not sampled this will be empty.
232+
trace-id: trace-id,
233+
}
234+
235+
/// Defines the window that an aggregation was calculated over.
236+
enum temporality {
237+
/// A measurement interval that continues to expand forward in time from a
238+
/// starting point.
239+
///
240+
/// New measurements are added to all previous measurements since a start time.
241+
///
242+
/// This is the default temporality
243+
cumulative,
244+
/// A measurement interval that resets each cycle.
245+
///
246+
/// Measurements from one cycle are recorded independently, measurements from
247+
/// other cycles do not affect them.
248+
delta,
249+
/// Configures Synchronous Counter and Histogram instruments to use
250+
/// Delta aggregation temporality, which allows them to shed memory
251+
/// following a cardinality explosion, thus use less memory.
252+
low-memory,
253+
}
254+
255+
/// The number types available for use with the OpenTelemetry SDKs.
256+
///
257+
/// This makes it easier to use generics when converting to and from WASI data types.
258+
variant metric-number {
259+
%f64(f64),
260+
%s64(s64),
261+
%u64(u64),
262+
}
263+
264+
/// The WASI representation of the `OTelSdkError`.
265+
///
266+
/// See https://github.com/open-telemetry/opentelemetry-rust/blob/353bbb0d80fc35a26a00b4f4fed0dcaed23e5523/opentelemetry-sdk/src/error.rs#L15
267+
variant otel-error {
268+
already-shutdown,
269+
timeout(duration),
270+
internal-failure(string),
271+
}
272+
}

0 commit comments

Comments
 (0)