Add analytics

This commit is contained in:
Mubelotix
2025-07-21 15:12:46 +02:00
parent 69dfd2c76e
commit 1f0d319c67
2 changed files with 115 additions and 11 deletions

View File

@ -28,6 +28,7 @@ use crate::analytics::Analytics;
use crate::extractors::authentication::policies::DoubleActionPolicy; use crate::extractors::authentication::policies::DoubleActionPolicy;
use crate::extractors::authentication::GuardedData; use crate::extractors::authentication::GuardedData;
use crate::extractors::sequential_extractor::SeqHandler; use crate::extractors::sequential_extractor::SeqHandler;
use crate::routes::indexes::render_analytics::RenderAggregator;
#[derive(OpenApi)] #[derive(OpenApi)]
#[openapi( #[openapi(
@ -92,14 +93,16 @@ pub async fn render_post(
let query = params.into_inner(); let query = params.into_inner();
debug!(parameters = ?query, "Render template"); debug!(parameters = ?query, "Render template");
//let mut aggregate = SimilarAggregator::<SimilarPOST>::from_query(&query); let mut aggregate = RenderAggregator::from_query(&query);
let result = render(index, query).await?; let result = render(index, query).await;
// if let Ok(similar) = &similar { if result.is_ok() {
// aggregate.succeed(similar); aggregate.succeed();
// } }
// analytics.publish(aggregate, &req); analytics.publish(aggregate, &req);
let result = result?;
debug!(returns = ?result, "Render template"); debug!(returns = ?result, "Render template");
Ok(HttpResponse::Ok().json(result)) Ok(HttpResponse::Ok().json(result))
@ -551,20 +554,20 @@ pub struct RenderQuery {
#[deserr(error = DeserrJsonError<InvalidRenderTemplate>, rename_all = camelCase, deny_unknown_fields)] #[deserr(error = DeserrJsonError<InvalidRenderTemplate>, rename_all = camelCase, deny_unknown_fields)]
pub struct RenderQueryTemplate { pub struct RenderQueryTemplate {
#[deserr(default, error = DeserrJsonError<InvalidRenderTemplateId>)] #[deserr(default, error = DeserrJsonError<InvalidRenderTemplateId>)]
id: Option<String>, pub id: Option<String>,
#[deserr(default, error = DeserrJsonError<InvalidRenderTemplateInline>)] #[deserr(default, error = DeserrJsonError<InvalidRenderTemplateInline>)]
inline: Option<serde_json::Value>, pub inline: Option<serde_json::Value>,
} }
#[derive(Debug, Clone, Default, PartialEq, Deserr, ToSchema)] #[derive(Debug, Clone, Default, PartialEq, Deserr, ToSchema)]
#[deserr(error = DeserrJsonError<InvalidRenderInput>, rename_all = camelCase, deny_unknown_fields)] #[deserr(error = DeserrJsonError<InvalidRenderInput>, rename_all = camelCase, deny_unknown_fields)]
pub struct RenderQueryInput { pub struct RenderQueryInput {
#[deserr(default, error = DeserrJsonError<InvalidRenderInputDocumentId>)] #[deserr(default, error = DeserrJsonError<InvalidRenderInputDocumentId>)]
document_id: Option<String>, pub document_id: Option<String>,
#[deserr(default, error = DeserrJsonError<InvalidRenderInputFields>)] #[deserr(default, error = DeserrJsonError<InvalidRenderInputFields>)]
insert_fields: Option<bool>, pub insert_fields: Option<bool>,
#[deserr(default, error = DeserrJsonError<InvalidRenderInputInline>)] #[deserr(default, error = DeserrJsonError<InvalidRenderInputInline>)]
inline: Option<BTreeMap<String, serde_json::Value>>, pub inline: Option<BTreeMap<String, serde_json::Value>>,
} }
#[derive(Debug, Clone, Serialize, PartialEq, ToSchema)] #[derive(Debug, Clone, Serialize, PartialEq, ToSchema)]

View File

@ -1 +1,102 @@
use serde_json::json;
use crate::analytics::Aggregate;
use crate::routes::indexes::render::RenderQuery;
#[derive(Default)]
pub struct RenderAggregator {
// requests
total_received: usize,
total_succeeded: usize,
// parameters
template_inline: bool,
template_id: bool,
input_inline: bool,
input_id: bool,
input_omitted: bool,
fields_forced: bool,
fields_disabled: bool,
}
impl RenderAggregator {
#[allow(clippy::field_reassign_with_default)]
pub fn from_query(query: &RenderQuery) -> Self {
let RenderQuery {
template,
input,
} = query;
let mut ret = Self::default();
ret.total_received = 1;
ret.template_inline = template.inline.is_some();
ret.template_id = template.id.is_some();
ret.input_inline = input.as_ref().is_some_and(|i| i.inline.is_some());
ret.input_id = input.as_ref().is_some_and(|i| i.document_id.is_some());
ret.input_omitted = input.as_ref().is_none();
ret.fields_forced = input.as_ref().is_some_and(|i| i.insert_fields.is_some());
ret.fields_disabled = input.as_ref().is_some_and(|i| i.insert_fields.is_none());
ret
}
pub fn succeed(&mut self) {
self.total_succeeded += 1;
}
}
impl Aggregate for RenderAggregator {
fn event_name(&self) -> &'static str {
"Documents Rendered"
}
fn aggregate(mut self: Box<Self>, new: Box<Self>) -> Box<Self> {
self.total_received += new.total_received;
self.total_succeeded += new.total_succeeded;
self.template_inline |= new.template_inline;
self.template_id |= new.template_id;
self.input_inline |= new.input_inline;
self.input_id |= new.input_id;
self.input_omitted |= new.input_omitted;
self.fields_forced |= new.fields_forced;
self.fields_disabled |= new.fields_disabled;
self
}
fn into_event(self: Box<Self>) -> serde_json::Value {
let Self {
total_received,
total_succeeded,
template_inline,
template_id,
input_inline,
input_id,
input_omitted,
fields_forced,
fields_disabled,
} = *self;
json!({
"requests": {
"total_received": total_received,
"total_succeeded": total_succeeded,
"total_failed": total_received.saturating_sub(total_succeeded) // just to be sure we never panics
},
"template": {
"inline": template_inline,
"id": template_id,
},
"input": {
"inline": input_inline,
"id": input_id,
"omitted": input_omitted,
"fields_forced": fields_forced,
"fields_disabled": fields_disabled,
},
})
}
}