systemprompt_analytics/feedback/
totals.rs1use super::{FactsTotals, FeedbackFactsRepository, validation};
8use crate::Result;
9use chrono::{DateTime, Utc};
10use systemprompt_identifiers::{ManagedResourceId, UserId};
11
12impl FeedbackFactsRepository {
13 pub async fn reference_totals(
14 &self,
15 owner: &UserId,
16 from: DateTime<Utc>,
17 to: DateTime<Utc>,
18 resource: Option<&ManagedResourceId>,
19 ) -> Result<FactsTotals> {
20 if from >= to {
21 return Err(validation::invalid());
22 }
23 let resource = resource.map(ManagedResourceId::as_str);
24 let mut tx = self.pool.begin().await?;
25 sqlx::query!("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY")
26 .execute(&mut *tx)
27 .await?;
28 let invocations = sqlx::query!(r#"SELECT COUNT(*) AS "total!",COUNT(*) FILTER(WHERE resource_id IS NOT NULL) AS "verified!" FROM analytics_normalized_facts WHERE owner_id=$1 AND fact_kind='invocation' AND NOT deleted AND occurred_at>=$2 AND occurred_at<$3 AND ($4::text IS NULL OR resource_id=$4)"#, owner.as_str(), from, to, resource).fetch_one(&mut *tx).await?;
29 let requests = sqlx::query!(r#"SELECT COUNT(*) AS "total!",COUNT(*) FILTER(WHERE NOT succeeded) AS "failed!",COUNT(*) FILTER(WHERE amount_micros IS NOT NULL) AS "priced!",COUNT(*) FILTER(WHERE latency_micros IS NOT NULL) AS "measured!",COUNT(*) FILTER(WHERE input_tokens IS NOT NULL AND output_tokens IS NOT NULL) AS "tokens_measured!" FROM analytics_normalized_facts r WHERE owner_id=$1 AND fact_kind='request' AND NOT deleted AND occurred_at>=$2 AND occurred_at<$3 AND ($4::text IS NULL OR EXISTS(SELECT 1 FROM analytics_normalized_facts a WHERE a.owner_id=r.owner_id AND a.fact_kind='resource_association' AND NOT a.deleted AND a.resource_id=$4 AND a.request_source=r.source AND a.request_id=r.fact_id))"#, owner.as_str(), from, to, resource).fetch_one(&mut *tx).await?;
30 let spend = sqlx::query!(r#"SELECT currency AS "currency!",SUM(amount_micros)::text AS "amount!" FROM analytics_normalized_facts r WHERE owner_id=$1 AND fact_kind='request' AND NOT deleted AND occurred_at>=$2 AND occurred_at<$3 AND currency IS NOT NULL AND ($4::text IS NULL OR EXISTS(SELECT 1 FROM analytics_normalized_facts a WHERE a.owner_id=r.owner_id AND a.fact_kind='resource_association' AND NOT a.deleted AND a.resource_id=$4 AND a.request_source=r.source AND a.request_id=r.fact_id)) GROUP BY currency"#, owner.as_str(), from, to, resource).fetch_all(&mut *tx).await?;
31 let assessments = sqlx::query!(r#"SELECT COUNT(DISTINCT (conversation_source,conversation_id)) AS "total!",COUNT(DISTINCT (conversation_source,conversation_id)) FILTER(WHERE assessment_status='scored') AS "scored!",COUNT(DISTINCT (conversation_source,conversation_id)) FILTER(WHERE assessment_status='failed') AS "failed!" FROM (SELECT DISTINCT ON (conversation_source,conversation_id) * FROM analytics_normalized_facts WHERE owner_id=$1 AND fact_kind='assessment' AND NOT deleted ORDER BY conversation_source,conversation_id,occurred_at DESC,source,fact_id) a WHERE occurred_at>=$2 AND occurred_at<$3 AND ($4::text IS NULL OR EXISTS(SELECT 1 FROM analytics_normalized_facts i WHERE i.owner_id=a.owner_id AND i.fact_kind='invocation' AND NOT i.deleted AND i.resource_id=$4 AND i.source=a.invocation_source AND i.fact_id=a.invocation_id))"#, owner.as_str(), from, to, resource).fetch_one(&mut *tx).await?;
32 let mut totals = FactsTotals {
33 invocations: invocations.total,
34 verified_invocations: invocations.verified,
35 requests: requests.total,
36 failed_requests: requests.failed,
37 priced_requests: requests.priced,
38 latency_measured_requests: requests.measured,
39 token_measured_requests: requests.tokens_measured,
40 assessed_conversations: assessments.scored,
41 assessment_conversations: assessments.total,
42 failed_assessments: assessments.failed,
43 related_spend_non_additive: resource.is_some(),
44 ..FactsTotals::default()
45 };
46 for row in spend {
47 totals.spend_by_currency.insert(
48 row.currency,
49 row.amount.parse().map_err(|_error| validation::invalid())?,
50 );
51 }
52 tx.commit().await?;
53 Ok(totals)
54 }
55}