systemprompt-analytics 0.2.2

Analytics for systemprompt.io AI governance infrastructure. Session, agent, tool, and microdollar-precision cost attribution across the MCP governance pipeline.
Documentation
use anyhow::Result;
use sqlx::PgPool;
use systemprompt_identifiers::SessionId;

pub async fn mark_as_behavioral_bot(
    pool: &PgPool,
    session_id: &SessionId,
    reason: &str,
) -> Result<()> {
    let id = session_id.as_str();
    sqlx::query!(
        r#"
        UPDATE user_sessions
        SET is_behavioral_bot = true,
            behavioral_bot_reason = $1
        WHERE session_id = $2
        "#,
        reason,
        id
    )
    .execute(pool)
    .await?;
    Ok(())
}

pub async fn check_and_mark_behavioral_bot(
    pool: &PgPool,
    session_id: &SessionId,
    request_count_threshold: i32,
) -> Result<bool> {
    let id = session_id.as_str();
    let result = sqlx::query!(
        r#"
        UPDATE user_sessions
        SET is_behavioral_bot = true,
            behavioral_bot_reason = 'request_count_exceeded'
        WHERE session_id = $1
          AND request_count > $2
          AND is_bot = false
          AND is_scanner = false
          AND is_behavioral_bot = false
        RETURNING session_id
        "#,
        id,
        request_count_threshold
    )
    .fetch_optional(pool)
    .await?;
    Ok(result.is_some())
}

pub async fn update_behavioral_detection(
    pool: &PgPool,
    session_id: &SessionId,
    score: i32,
    is_behavioral_bot: bool,
    reason: Option<&str>,
) -> Result<()> {
    let id = session_id.as_str();

    sqlx::query!(
        r#"
        UPDATE user_sessions
        SET behavioral_bot_score = $1,
            is_behavioral_bot = $2,
            behavioral_bot_reason = $3,
            last_activity_at = CURRENT_TIMESTAMP
        WHERE session_id = $4
        "#,
        score,
        is_behavioral_bot,
        reason,
        id
    )
    .execute(pool)
    .await?;

    Ok(())
}