Skip to content

Commit 0da665b

Browse files
committed
add SpanExporter and StdoutExporter
Signed-off-by: drumato <[email protected]>
1 parent bfd1415 commit 0da665b

File tree

6 files changed

+123
-0
lines changed

6 files changed

+123
-0
lines changed

src/api/trace.zig

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ pub const Tracer = @import("trace/tracer.zig").Tracer;
22
pub const TracerProvider = @import("trace/provider.zig").TracerProvider;
33
pub const TracerConfig = @import("trace/config.zig").TracerConfig;
44

5+
pub const TraceID = [16]u8;
6+
pub const SpanID = [8]u8;
7+
58
test {
69
_ = @import("trace/config.zig");
710
_ = @import("trace/provider.zig");

src/sdk/trace.zig

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
pub const exporter = @import("trace/exporter.zig");
12
test {
3+
_ = @import("trace/exporter.zig");
4+
_ = @import("trace/id_generator.zig");
25
_ = @import("trace/provider.zig");
6+
_ = @import("trace/span_exporter.zig");
37
}

src/sdk/trace/exporter.zig

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
test {
2+
_ = @import("exporters/stdout_exporter.zig");
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const std = @import("std");
2+
const pb = @import("../../../opentelemetry/proto/trace/v1.pb.zig");
3+
const protobuf = @import("protobuf");
4+
const SpanExporter = @import("../span_exporter.zig").SpanExporter;
5+
6+
/// GenericWriterExporter is the generic SpanExporter that outputs spans to the given writer.
7+
fn GenericWriterExporter(
8+
comptime Writer: type,
9+
) type {
10+
return struct {
11+
writer: Writer,
12+
13+
const Self = @This();
14+
15+
pub fn init(writer: Writer) Self {
16+
return Self{
17+
.writer = writer,
18+
};
19+
}
20+
21+
pub fn exportSpans(ctx: *anyopaque, spans: []pb.Span) anyerror!void {
22+
const self: *Self = @ptrCast(@alignCast(ctx));
23+
try std.json.stringify(spans, .{}, self.writer);
24+
}
25+
26+
pub fn shutdown(_: *anyopaque) anyerror!void {}
27+
28+
pub fn asSpanExporter(self: *Self) SpanExporter {
29+
return .{
30+
.ptr = self,
31+
.vtable = &.{
32+
.exportSpansFn = exportSpans,
33+
.shutdownFn = shutdown,
34+
},
35+
};
36+
}
37+
};
38+
}
39+
40+
/// StdoutExporter outputs spans into OS stdout.
41+
/// ref: https://opentelemetry.io/docs/specs/otel/trace/sdk_exporters/stdout/
42+
pub const StdoutExporter = GenericWriterExporter(std.io.Writer(std.fs.File, std.fs.File.WriteError, std.fs.File.write));
43+
44+
/// InmemoryExporter exports spans to in-memory buffer.
45+
/// it is designed for testing GenericWriterExporter.
46+
pub const InmemoryExporter = GenericWriterExporter(std.ArrayList(u8).Writer);
47+
48+
test "GenericWriterExporter" {
49+
var out_buf = std.ArrayList(u8).init(std.testing.allocator);
50+
defer out_buf.deinit();
51+
var inmemory_exporter = InmemoryExporter.init(out_buf.writer());
52+
var exporter = inmemory_exporter.asSpanExporter();
53+
54+
var spans = [_]pb.Span{};
55+
try exporter.exportSpans(spans[0..spans.len]);
56+
57+
// TODO: detailed output test
58+
}

src/sdk/trace/id_generator.zig

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const trace = @import("../../api/trace.zig");
2+
/// IDGenerator is the interface that generates traceID/spanID.
3+
pub const IDGenerator = struct {
4+
newIDsFn: *const fn (
5+
*IDGenerator,
6+
) TraceSpanID,
7+
newSpanIDFn: *const fn (
8+
*IDGenerator,
9+
trace_id: trace.TraceID,
10+
) trace.SpanID,
11+
};
12+
13+
/// TraceSpanID is the set of traceID/spanID.
14+
pub const TraceSpanID = struct {
15+
traceID: trace.TraceID,
16+
spanID: trace.SpanID,
17+
};
18+
19+
/// RandomIDGenerator generates traceID/spanID randomly.
20+
pub const RandomIDGenerator = struct {
21+
const Self = @This();
22+
pub fn init() Self {
23+
return .{};
24+
}
25+
};

src/sdk/trace/span_exporter.zig

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const pb = @import("../../opentelemetry/proto/trace/v1.pb.zig");
2+
3+
/// SpanExporter is the interface that provides an
4+
pub const SpanExporter = struct {
5+
// std.mem.Allocator's style
6+
ptr: *anyopaque,
7+
vtable: *const VTable,
8+
9+
const Self = @This();
10+
11+
/// VTable defines the methods that the SpanExporter's instance must implement.
12+
pub const VTable = struct {
13+
/// exportSpans is the method that export a batch of spans.
14+
/// NOTE: In other languages, the span types is ReadOnlySpan for improving stability.
15+
/// but it is not defined in the OpenTelemetry specification, so for now we don't use it.
16+
exportSpansFn: *const fn (
17+
ctx: *anyopaque,
18+
spans: []pb.Span,
19+
) anyerror!void,
20+
21+
shutdownFn: *const fn (ctx: *anyopaque) anyerror!void,
22+
};
23+
24+
pub fn exportSpans(
25+
self: Self,
26+
spans: []pb.Span,
27+
) anyerror!void {
28+
return self.vtable.exportSpansFn(self.ptr, spans);
29+
}
30+
};

0 commit comments

Comments
 (0)