use std::collections::VecDeque;
use obs_proto::obs::v1::ObsEnvelope;
use crate::codegen_helpers::SpanFrame;
#[derive(Debug, Clone)]
pub enum ScopeField {
TraceId(String),
SpanId(String),
ParentSpanId(String),
Label(&'static str, String),
}
impl ScopeField {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::TraceId(_) => "trace_id",
Self::SpanId(_) => "span_id",
Self::ParentSpanId(_) => "parent_span_id",
Self::Label(k, _) => k,
}
}
#[must_use]
pub fn value(&self) -> &str {
match self {
Self::TraceId(v) | Self::SpanId(v) | Self::ParentSpanId(v) | Self::Label(_, v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ScopeKind {
Scope,
Context,
}
#[derive(Debug, Clone)]
pub struct ScopeFrame {
fields: Vec<ScopeField>,
kind: ScopeKind,
tail_capacity: u16,
tail_buffer: VecDeque<ObsEnvelope>,
seen_error: bool,
traceparent_sampled: Option<bool>,
span_name: Option<&'static str>,
span_target: Option<&'static str>,
}
impl ScopeFrame {
#[must_use]
pub fn new(fields: Vec<ScopeField>, kind: ScopeKind, tail_capacity: u16) -> Self {
let cap = match kind {
ScopeKind::Scope => tail_capacity as usize,
ScopeKind::Context => 0,
};
Self {
fields,
kind,
tail_capacity,
tail_buffer: VecDeque::with_capacity(cap),
seen_error: false,
traceparent_sampled: None,
span_name: None,
span_target: None,
}
}
pub fn set_traceparent_sampled(&mut self, sampled: bool) {
self.traceparent_sampled = Some(sampled);
}
pub fn set_span_identity(&mut self, name: &'static str, target: &'static str) {
self.span_name = Some(name);
self.span_target = Some(target);
}
#[must_use]
pub fn traceparent_sampled(&self) -> Option<bool> {
self.traceparent_sampled
}
#[must_use]
pub fn fields(&self) -> &[ScopeField] {
&self.fields
}
#[must_use]
pub fn kind(&self) -> ScopeKind {
self.kind
}
#[must_use]
pub fn seen_error(&self) -> bool {
self.seen_error
}
pub fn mark_error(&mut self) {
self.seen_error = true;
}
#[must_use]
pub fn tail_capacity(&self) -> u16 {
self.tail_capacity
}
pub fn push_tail(&mut self, env: ObsEnvelope) {
if self.kind == ScopeKind::Context {
return;
}
if self.tail_capacity == 0 {
return;
}
if self.tail_buffer.len() >= self.tail_capacity as usize {
self.tail_buffer.pop_front();
}
self.tail_buffer.push_back(env);
}
#[must_use]
pub fn drain_tail(&mut self) -> Vec<ObsEnvelope> {
self.tail_buffer.drain(..).collect()
}
#[must_use]
pub fn tail_snapshot(&self) -> Vec<ObsEnvelope> {
self.tail_buffer.iter().cloned().collect()
}
#[must_use]
pub fn as_span_frame(&self) -> Option<SpanFrame<'_>> {
Some(SpanFrame {
name: self.span_name?,
target: self.span_target?,
})
}
}