Mountain/Environment/
DiagnosticProvider.rs1use CommonLibrary::{
41 Diagnostic::DiagnosticManager::DiagnosticManager,
42 Error::CommonError::CommonError,
43 IPC::SkyEvent::SkyEvent,
44};
45use async_trait::async_trait;
46use serde_json::{Value, json};
47
48use super::{MountainEnvironment::MountainEnvironment, Utility};
53use crate::{ApplicationState::DTO::MarkerDataDTO::MarkerDataDTO, IPC::SkyEmit::LogSkyEmit, dev_log};
54
55#[async_trait]
59impl DiagnosticManager for MountainEnvironment {
60 async fn SetDiagnostics(&self, Owner:String, EntriesDTOValue:Value) -> Result<(), CommonError> {
64 dev_log!("extensions", "[DiagnosticProvider] Setting diagnostics for owner: {}", Owner);
65
66 let DeserializedEntries:Vec<(Value, Option<Vec<MarkerDataDTO>>)> = serde_json::from_value(EntriesDTOValue)
67 .map_err(|Error| {
68 CommonError::InvalidArgument {
69 ArgumentName:"EntriesDTOValue".to_string(),
70 Reason:format!("Failed to deserialize diagnostic entries: {}", Error),
71 }
72 })?;
73
74 let mut DiagnosticsMapGuard = self
75 .ApplicationState
76 .Feature
77 .Diagnostics
78 .DiagnosticsMap
79 .lock()
80 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
81
82 let OwnerMap = DiagnosticsMapGuard.entry(Owner.clone()).or_default();
83
84 let mut ChangedURIKeys = Vec::new();
85
86 let mut ChangedEntries:Vec<serde_json::Value> = Vec::new();
93
94 for (URIComponentsValue, MarkersOption) in DeserializedEntries {
95 let URIKey = match Utility::UriParsing::Fn(&URIComponentsValue) {
105 Ok(Url) => Url.to_string(),
106
107 Err(Error) => {
108 dev_log!(
109 "extensions",
110 "warn: [DiagnosticProvider] skipping diagnostic entry with bad URI: {} (raw={:?})",
111 Error,
112 URIComponentsValue
113 );
114
115 continue;
116 },
117 };
118
119 if URIKey.is_empty() {
120 dev_log!(
121 "extensions",
122 "warn: [DiagnosticProvider] skipping diagnostic entry with empty URI string"
123 );
124
125 continue;
126 }
127
128 ChangedURIKeys.push(URIKey.clone());
129
130 let MarkersForEvent = match MarkersOption {
131 Some(Markers) => {
132 if Markers.is_empty() {
133 OwnerMap.remove(&URIKey);
134
135 Vec::new()
136 } else {
137 let MarkersClone = Markers.clone();
138
139 OwnerMap.insert(URIKey.clone(), Markers);
140
141 MarkersClone
142 }
143 },
144
145 None => {
146 OwnerMap.remove(&URIKey);
147
148 Vec::new()
149 },
150 };
151
152 ChangedEntries.push(json!({
153 "uri": URIKey,
154 "markers": MarkersForEvent,
155 }));
156 }
157
158 drop(DiagnosticsMapGuard);
159
160 let EventPayload = json!({
166 "Owner": Owner,
167 "owner": Owner,
168 "Uris": ChangedURIKeys,
169 "changedURIs": ChangedEntries,
170 });
171
172 if let Err(Error) = LogSkyEmit(&self.ApplicationHandle, SkyEvent::DiagnosticsChanged.AsStr(), EventPayload) {
179 dev_log!(
180 "extensions",
181 "error: [DiagnosticProvider] Failed to emit 'diagnostics_changed': {}",
182 Error
183 );
184 }
185
186 dev_log!(
187 "extensions",
188 "[DiagnosticProvider] Emitted diagnostics changed for {} URI(s)",
189 ChangedURIKeys.len()
190 );
191
192 Ok(())
193 }
194
195 async fn ClearDiagnostics(&self, Owner:String) -> Result<(), CommonError> {
197 dev_log!(
198 "extensions",
199 "[DiagnosticProvider] Clearing all diagnostics for owner: {}",
200 Owner
201 );
202
203 let (ClearedCount, ChangedURIKeys):(usize, Vec<String>) = {
204 let mut DiagnosticsMapGuard = self
205 .ApplicationState
206 .Feature
207 .Diagnostics
208 .DiagnosticsMap
209 .lock()
210 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
211
212 DiagnosticsMapGuard
213 .remove(&Owner)
214 .map(|OwnerMap| {
215 let keys:Vec<String> = OwnerMap.keys().cloned().collect();
216
217 (keys.len(), keys)
218 })
219 .unwrap_or((0, vec![]))
220 };
221
222 if !ChangedURIKeys.is_empty() {
223 dev_log!(
224 "extensions",
225 "[DiagnosticProvider] Cleared {} diagnostics across {} URI(s)",
226 ClearedCount,
227 ChangedURIKeys.len()
228 );
229
230 let ChangedEntries:Vec<serde_json::Value> =
234 ChangedURIKeys.iter().map(|Uri| json!({ "uri": Uri, "markers": [] })).collect();
235
236 let EventPayload = json!({
237 "Owner": Owner,
238 "owner": Owner,
239 "Uris": ChangedURIKeys,
240 "changedURIs": ChangedEntries,
241 });
242
243 if let Err(Error) = LogSkyEmit(&self.ApplicationHandle, SkyEvent::DiagnosticsChanged.AsStr(), EventPayload)
244 {
245 dev_log!(
246 "extensions",
247 "error: [DiagnosticProvider] Failed to emit 'diagnostics_changed' on clear: {}",
248 Error
249 );
250 }
251 }
252
253 Ok(())
254 }
255
256 async fn GetAllDiagnostics(&self, ResourceURIFilterOption:Option<Value>) -> Result<Value, CommonError> {
260 dev_log!(
261 "extensions",
262 "[DiagnosticProvider] Getting all diagnostics with filter: {:?}",
263 ResourceURIFilterOption
264 );
265
266 let FilterURIKey = ResourceURIFilterOption
270 .as_ref()
271 .map(|V| Utility::UriParsing::Fn(V).map(|U| U.to_string()))
272 .transpose()?;
273
274 let Snapshot:Vec<std::collections::HashMap<String, Vec<MarkerDataDTO>>> = {
275 let DiagnosticsMapGuard = self
276 .ApplicationState
277 .Feature
278 .Diagnostics
279 .DiagnosticsMap
280 .lock()
281 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
282
283 DiagnosticsMapGuard.values().cloned().collect()
284 };
285
286 let mut ResultMap:std::collections::HashMap<String, Vec<MarkerDataDTO>> = std::collections::HashMap::new();
287
288 if let Some(FilterKey) = FilterURIKey {
289 for OwnerMap in &Snapshot {
290 if let Some(Markers) = OwnerMap.get(&FilterKey) {
291 ResultMap.entry(FilterKey.clone()).or_default().extend(Markers.clone());
292 }
293 }
294 } else {
295 for OwnerMap in &Snapshot {
296 for (URIKey, Markers) in OwnerMap.iter() {
297 ResultMap.entry(URIKey.clone()).or_default().extend(Markers.clone());
298 }
299 }
300 }
301
302 let ResultList:Vec<(String, Vec<MarkerDataDTO>)> = ResultMap.into_iter().collect();
303
304 dev_log!(
305 "extensions",
306 "[DiagnosticProvider] Returning {} diagnostic collection(s)",
307 ResultList.len()
308 );
309
310 serde_json::to_value(ResultList).map_err(|Error| CommonError::from(Error))
311 }
312}