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::GetURLFromURIComponentsDTO(&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 DiagnosticsMapGuard = self
266 .ApplicationState
267 .Feature
268 .Diagnostics
269 .DiagnosticsMap
270 .lock()
271 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
272
273 let mut ResultMap:std::collections::HashMap<String, Vec<MarkerDataDTO>> = std::collections::HashMap::new();
274
275 if let Some(FilterURIValue) = ResourceURIFilterOption {
276 let FilterURIKey = Utility::UriParsing::GetURLFromURIComponentsDTO(&FilterURIValue)?.to_string();
277
278 for OwnerMap in DiagnosticsMapGuard.values() {
279 if let Some(Markers) = OwnerMap.get(&FilterURIKey) {
280 ResultMap.entry(FilterURIKey.clone()).or_default().extend(Markers.clone());
281 }
282 }
283 } else {
284 for OwnerMap in DiagnosticsMapGuard.values() {
286 for (URIKey, Markers) in OwnerMap.iter() {
287 ResultMap.entry(URIKey.clone()).or_default().extend(Markers.clone());
288 }
289 }
290 }
291
292 let ResultList:Vec<(String, Vec<MarkerDataDTO>)> = ResultMap.into_iter().collect();
293
294 dev_log!(
295 "extensions",
296 "[DiagnosticProvider] Returning {} diagnostic collection(s)",
297 ResultList.len()
298 );
299
300 serde_json::to_value(ResultList).map_err(|Error| CommonError::from(Error))
301 }
302}