msgpack_tracing/
restart.rs1use crate::tape::{Instruction, InstructionSet, SpanRecords, TapeMachine};
2use std::{collections::HashMap, num::NonZeroU64};
3
4pub struct RestartableMachine<T> {
5 forward: T,
6 span: HashMap<NonZeroU64, SpanRecords>,
7 current_span: Option<(NonZeroU64, SpanRecords)>,
8}
9impl<T> RestartableMachine<T>
10where
11 T: TapeMachine<InstructionSet>,
12{
13 pub fn new(forward: T) -> Self {
14 Self {
15 forward,
16 span: Default::default(),
17 current_span: None,
18 }
19 }
20}
21impl<T> TapeMachine<InstructionSet> for RestartableMachine<T>
22where
23 T: TapeMachine<InstructionSet>,
24{
25 fn needs_restart(&mut self) -> bool {
26 self.forward.needs_restart()
27 }
28
29 fn handle(&mut self, instruction: Instruction) {
30 match instruction {
31 Instruction::Restart => {
32 self.forward.handle(Instruction::Restart);
33
34 for (span, records) in self.span.iter() {
35 self.forward.handle(Instruction::NewSpan {
36 parent: records.parent,
37 span: *span,
38 name: records.name.as_ref(),
39 });
40
41 for record in records.records.iter() {
42 self.forward.handle(Instruction::AddValue(record.as_ref()));
43 }
44
45 self.forward.handle(Instruction::FinishedSpan);
46 }
47 }
48 Instruction::NewSpan { parent, span, name } => {
49 assert!(self.current_span.is_none());
50 self.current_span = Some((
51 span,
52 SpanRecords {
53 parent,
54 name: name.to_owned(),
55 records: Default::default(),
56 },
57 ));
58
59 self.forward
60 .handle(Instruction::NewSpan { parent, span, name });
61 }
62 Instruction::FinishedSpan => {
63 let (k, v) = self.current_span.take().unwrap();
64 self.span.insert(k, v);
65 self.forward.handle(Instruction::FinishedSpan)
66 }
67 Instruction::NewRecord(span) => {
68 assert!(self.current_span.is_none());
69 self.current_span = Some(self.span.remove_entry(&span).unwrap());
70 self.forward.handle(Instruction::NewRecord(span));
71 }
72 Instruction::FinishedRecord => {
73 let (k, v) = self.current_span.take().unwrap();
74 self.span.insert(k, v);
75 self.forward.handle(Instruction::FinishedRecord)
76 }
77 Instruction::StartEvent {
78 time,
79 span,
80 target,
81 priority,
82 } => {
83 self.forward.handle(Instruction::StartEvent {
84 time,
85 span,
86 target,
87 priority,
88 });
89 }
90 Instruction::FinishedEvent => self.forward.handle(Instruction::FinishedEvent),
91 Instruction::AddValue(field_value) => {
92 if let Some((_, current_span)) = self.current_span.as_mut() {
93 current_span.records.push(field_value.to_owned());
94 }
95 self.forward.handle(Instruction::AddValue(field_value));
96 }
97 Instruction::DeleteSpan(span) => {
98 self.span.remove(&span);
99 self.forward.handle(Instruction::DeleteSpan(span));
100 }
101 }
102 }
103}