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 (keys.len(), keys)
217 })
218 .unwrap_or((0, vec![]))
219 };
220
221 if !ChangedURIKeys.is_empty() {
222 dev_log!(
223 "extensions",
224 "[DiagnosticProvider] Cleared {} diagnostics across {} URI(s)",
225 ClearedCount,
226 ChangedURIKeys.len()
227 );
228
229 let ChangedEntries:Vec<serde_json::Value> =
233 ChangedURIKeys.iter().map(|Uri| json!({ "uri": Uri, "markers": [] })).collect();
234
235 let EventPayload = json!({
236 "Owner": Owner,
237 "owner": Owner,
238 "Uris": ChangedURIKeys,
239 "changedURIs": ChangedEntries,
240 });
241
242 if let Err(Error) = LogSkyEmit(&self.ApplicationHandle, SkyEvent::DiagnosticsChanged.AsStr(), EventPayload)
243 {
244 dev_log!(
245 "extensions",
246 "error: [DiagnosticProvider] Failed to emit 'diagnostics_changed' on clear: {}",
247 Error
248 );
249 }
250 }
251
252 Ok(())
253 }
254
255 async fn GetAllDiagnostics(&self, ResourceURIFilterOption:Option<Value>) -> Result<Value, CommonError> {
259 dev_log!(
260 "extensions",
261 "[DiagnosticProvider] Getting all diagnostics with filter: {:?}",
262 ResourceURIFilterOption
263 );
264
265 let FilterURIKey = ResourceURIFilterOption
269 .as_ref()
270 .map(|V| Utility::UriParsing::Fn(V).map(|U| U.to_string()))
271 .transpose()?;
272
273 let Snapshot:Vec<std::collections::HashMap<String, Vec<MarkerDataDTO>>> = {
274 let DiagnosticsMapGuard = self
275 .ApplicationState
276 .Feature
277 .Diagnostics
278 .DiagnosticsMap
279 .lock()
280 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
281
282 DiagnosticsMapGuard.values().cloned().collect()
283 };
284
285 let mut ResultMap:std::collections::HashMap<String, Vec<MarkerDataDTO>> = std::collections::HashMap::new();
286
287 if let Some(FilterKey) = FilterURIKey {
288 for OwnerMap in &Snapshot {
289 if let Some(Markers) = OwnerMap.get(&FilterKey) {
290 ResultMap.entry(FilterKey.clone()).or_default().extend(Markers.clone());
291 }
292 }
293 } else {
294 for OwnerMap in &Snapshot {
295 for (URIKey, Markers) in OwnerMap.iter() {
296 ResultMap.entry(URIKey.clone()).or_default().extend(Markers.clone());
297 }
298 }
299 }
300
301 let ResultList:Vec<(String, Vec<MarkerDataDTO>)> = ResultMap.into_iter().collect();
302
303 dev_log!(
304 "extensions",
305 "[DiagnosticProvider] Returning {} diagnostic collection(s)",
306 ResultList.len()
307 );
308
309 serde_json::to_value(ResultList).map_err(|Error| CommonError::from(Error))
310 }
311}