next_web_ai/observation/
simple_observation.rs1use std::collections::VecDeque;
2
3use next_web_core::{autoconfigure::context, convert::into_box::IntoBox};
4
5use crate::{
6 chat::observation::observation_convention::ObservationConvention,
7 observation::observation_documentation::BoxObservationConvention,
8};
9
10use super::{
11 observation::{Context, Observation},
12 observation_filter::ObservationFilter,
13 observation_handler::ObservationHandler,
14 observation_registry::ObservationRegistry,
15};
16
17pub struct SimpleObservation {
18 pub(crate) context: Box<dyn Context>,
19 pub(crate) registry: Box<dyn ObservationRegistry>,
20 pub(crate) convention: Option<BoxObservationConvention>,
21 pub(crate) handlers: VecDeque<Box<dyn ObservationHandler>>,
22 pub(crate) filters: Vec<Box<dyn ObservationFilter>>,
23}
24
25impl SimpleObservation {
26 pub fn new(
27 name: impl AsRef<str>,
28 registry: Box<dyn ObservationRegistry>,
29 mut context: impl Context + 'static,
30 ) -> Self {
31 context.set_name(name.as_ref());
32 let filters = registry
33 .observation_config()
34 .observation_filters
35 .data
36 .blocking_read()
37 .clone();
38 Self {
39 convention: Self::get_convention_from_config(®istry, &context),
40 handlers: Self::get_handlers_from_config(®istry, &context),
41 context: Box::new(context),
42 filters,
43 registry,
44 }
45 }
46
47 fn get_convention_from_config(
48 registry: &Box<dyn ObservationRegistry>,
49 context: &dyn Context,
50 ) -> Option<BoxObservationConvention> {
51 for convention in registry
52 .observation_config()
53 .observation_conventions
54 .data
55 .blocking_read()
56 .iter()
57 {
58 if convention.supports_context(context) {
59 return Some(convention.clone());
60 }
61 }
62 return None;
63 }
64
65 fn get_handlers_from_config(
66 registry: &Box<dyn ObservationRegistry>,
67 context: &dyn Context,
68 ) -> VecDeque<Box<dyn ObservationHandler>> {
69 let mut handlers = VecDeque::new();
70 for handler in registry
71 .observation_config()
72 .observation_handlers
73 .data
74 .blocking_read()
75 .iter()
76 {
77 if handler.supports_context(context) {
78 handlers.push_back(handler.clone());
79 }
80 }
81 handlers
82 }
83}
84
85impl SimpleObservation {
86 fn notify_on_observation_started(&mut self) {
87 for handler in self.handlers.iter_mut() {
88 handler.on_start(self.context.as_ref());
89 }
90 }
91
92 fn notify_on_observation_stopped(&mut self, context: &dyn Context) {
93 self.handlers
94 .iter_mut()
95 .rev()
96 .for_each(|handler| handler.on_stop(context));
97 }
98}
99impl Observation for SimpleObservation {
100 fn start(&mut self) {
101 if let Some(convention) = self.convention.as_ref() {
102 let low = convention.low_cardinality_key_values(self.context.as_ref());
103 let high = convention.high_cardinality_key_values(self.context.as_ref());
104
105 self.context.add_low_cardinality_key_values(low);
106 self.context.add_low_cardinality_key_values(high);
107
108 let new_name = convention.name();
109 if let Some(name) = new_name {
110 self.context.set_name(name);
111 }
112 }
113 self.notify_on_observation_started();
114 }
115
116 fn stop(&mut self) {
117 if let Some(convention) = self.convention.as_ref() {
118 let low = convention.low_cardinality_key_values(self.context.as_ref());
119 let high = convention.high_cardinality_key_values(self.context.as_ref());
120
121 self.context.add_low_cardinality_key_values(low);
122 self.context.add_low_cardinality_key_values(high);
123
124 let new_name = convention.contextual_name(self.context.as_ref());
125 if let Some(name) = new_name {
126 self.context.set_contextual_name(name);
127 }
128 }
129
130 let mut modified_context = self.context.clone();
131 for filter in self.filters.iter_mut() {
132 modified_context = filter.map(modified_context);
133 }
134
135 self.notify_on_observation_stopped(modified_context.as_ref());
136 }
137
138 fn context(&mut self) -> &mut dyn super::observation::Context {
139 self.context.as_mut()
140 }
141
142 fn contextual_name(&mut self, contextual_name: &str) {
143 self.context.set_contextual_name(contextual_name);
144 }
145
146 fn parent_observation(&mut self, parent_observation: Box<dyn Observation>) {
147 todo!()
148 }
149
150 fn low_cardinality_key_value(&mut self, key_value: Box<dyn crate::util::key_value::KeyValue>) {
151 todo!()
152 }
153
154 fn high_cardinality_key_value(&mut self, key_value: Box<dyn crate::util::key_value::KeyValue>) {
155 todo!()
156 }
157
158 fn observation_convention(&mut self, observation_convention: BoxObservationConvention) {
159 todo!()
160 }
161
162 fn error(&mut self, error: &next_web_core::error::BoxError) {
163 todo!()
164 }
165
166 fn event(&mut self, event: Box<dyn super::observation::Event>) {
167 todo!()
168 }
169
170 fn open_scope(&self) -> Box<dyn super::observation::Scope> {
171 todo!()
172 }
173}