From 201bec529b21a477285e82810a4a6ed9f73343f4 Mon Sep 17 00:00:00 2001 From: boxbeam Date: Tue, 9 Apr 2024 15:41:29 -0400 Subject: [PATCH] Fix languages, implement Other query, and fix analytics bug --- Cargo.lock | 1 + Cargo.toml | 1 + crates/tabby/Cargo.toml | 2 +- ee/tabby-db/src/user_completions.rs | 17 ++++++-- ee/tabby-webserver/Cargo.toml | 1 + ee/tabby-webserver/src/schema/analytic.rs | 45 +++++++++++++--------- ee/tabby-webserver/src/service/analytic.rs | 16 ++++++-- 7 files changed, 57 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbc02e25d2e6..d1a489bc37ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4620,6 +4620,7 @@ dependencies = [ "serde", "serde_json", "serial_test 3.0.0", + "strum", "tabby-common", "tabby-db", "tarpc", diff --git a/Cargo.toml b/Cargo.toml index 448ddbadc0dc..48727848f057 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ derive_builder = "0.12.0" futures = "0.3.28" async-stream = "0.3.5" regex = "1.10.0" +strum = { version = "0.24", features = ["derive"] } thiserror = "1.0.49" utoipa = "3.3" axum = "0.6" diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml index c14c17b57f50..9cba5f71c7e3 100644 --- a/crates/tabby/Cargo.toml +++ b/crates/tabby/Cargo.toml @@ -32,7 +32,7 @@ serde_json = { workspace = true } tower-http = { version = "0.4.0", features = ["cors", "timeout"] } clap = { version = "4.3.0", features = ["derive"] } lazy_static = { workspace = true } -strum = { version = "0.24", features = ["derive"] } +strum = { workspace = true } strfmt = "0.2.4" tracing = { workspace = true } tracing-subscriber = { workspace = true } diff --git a/ee/tabby-db/src/user_completions.rs b/ee/tabby-db/src/user_completions.rs index 639f7cf27e52..0ce85dd3241b 100644 --- a/ee/tabby-db/src/user_completions.rs +++ b/ee/tabby-db/src/user_completions.rs @@ -101,13 +101,23 @@ impl DbConn { end: DateTime, users: Vec, languages: Vec, + not_languages: Vec, ) -> Result> { let users = users .iter() .map(|u| u.to_string()) .collect::>() .join(","); - let languages = languages.join(","); + let languages = languages + .into_iter() + .map(|l| format!("{:?}", l.to_string())) + .collect::>() + .join(","); + let not_languages = not_languages + .into_iter() + .map(|l| format!("{:?}", l.to_string())) + .collect::>() + .join(","); let res = sqlx::query_as!( UserCompletionDailyStatsDAO, r#" @@ -117,14 +127,15 @@ impl DbConn { FROM user_completions WHERE created_at >= ?1 AND created_at < ?2 AND (?3 = '' OR user_id IN (?3)) - AND (?4 = '' OR language IN (?4)) + AND ((?4 = '' OR '"' + language + '"' IN (?4)) AND (?5 = '' OR '"' + language + '"' NOT IN (?5))) GROUP BY 1 ORDER BY 1 ASC "#, start, end, users, - languages + languages, + not_languages ) .fetch_all(&self.pool) .await?; diff --git a/ee/tabby-webserver/Cargo.toml b/ee/tabby-webserver/Cargo.toml index d59047df3ef4..551fe323fa26 100644 --- a/ee/tabby-webserver/Cargo.toml +++ b/ee/tabby-webserver/Cargo.toml @@ -31,6 +31,7 @@ reqwest = { workspace = true, features = ["json"] } rust-embed = "8.0.0" serde.workspace = true serde_json.workspace = true +strum.workspace = true tabby-common = { path = "../../crates/tabby-common" } tabby-db = { path = "../../ee/tabby-db" } tarpc = { version = "0.33.0", features = ["serde-transport"] } diff --git a/ee/tabby-webserver/src/schema/analytic.rs b/ee/tabby-webserver/src/schema/analytic.rs index 42c85bc6a196..5e7067b2f58b 100644 --- a/ee/tabby-webserver/src/schema/analytic.rs +++ b/ee/tabby-webserver/src/schema/analytic.rs @@ -1,8 +1,7 @@ -use std::fmt::Display; - use async_trait::async_trait; use chrono::{DateTime, Utc}; use juniper::{GraphQLEnum, GraphQLObject, ID}; +use strum::{EnumIter, IntoEnumIterator}; use crate::schema::Result; @@ -15,38 +14,46 @@ pub struct CompletionStats { pub selects: i32, } -#[derive(GraphQLEnum, Clone, Debug)] +#[derive(GraphQLEnum, Clone, Debug, Eq, PartialEq, EnumIter)] pub enum Language { Rust, Python, Java, Kotlin, - JavascriptTypescript, + Javascript, + Typescript, Go, Ruby, CSharp, C, - CPlusPlus, + CPP, Solidity, Other, } -impl Display for Language { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Language { + pub fn all_known() -> impl Iterator { + Language::iter().filter(|l| l != &Language::Other) + } + + pub fn to_strings(&self) -> impl IntoIterator { match self { - Language::Rust => write!(f, "rust"), - Language::Python => write!(f, "python"), - Language::Java => write!(f, "java"), - Language::Kotlin => write!(f, "kotlin"), - Language::JavascriptTypescript => write!(f, "javascript-typescript"), - Language::Go => write!(f, "go"), - Language::Ruby => write!(f, "ruby"), - Language::CSharp => write!(f, "csharp"), - Language::C => write!(f, "c"), - Language::CPlusPlus => write!(f, "cpp"), - Language::Solidity => write!(f, "solidity"), - Language::Other => write!(f, "other"), + Language::Rust => vec!["rust"], + Language::Python => vec!["python"], + Language::Java => vec!["java"], + Language::Kotlin => vec!["kotlin"], + Language::Javascript => vec!["javascript", "javascriptreact"], + Language::Typescript => vec!["typescript", "typescriptreact"], + Language::Go => vec!["go"], + Language::Ruby => vec!["ruby"], + Language::CSharp => vec!["csharp"], + Language::C => vec!["c"], + Language::CPP => vec!["cpp"], + Language::Solidity => vec!["solidity"], + Language::Other => vec!["other"], } + .into_iter() + .map(|s| s.to_string()) } } diff --git a/ee/tabby-webserver/src/service/analytic.rs b/ee/tabby-webserver/src/service/analytic.rs index d4774b09892a..708fc7e20962 100644 --- a/ee/tabby-webserver/src/service/analytic.rs +++ b/ee/tabby-webserver/src/service/analytic.rs @@ -39,13 +39,23 @@ impl AnalyticService for AnalyticServiceImpl { start: DateTime, end: DateTime, users: Vec, - languages: Vec, + mut languages: Vec, ) -> Result> { let users = convert_ids(users); - let languages = languages.into_iter().map(|l| l.to_string()).collect(); + + let not_languages = languages + .iter() + .position(|l| l == &Language::Other) + .map(|i| { + languages.remove(i); + Language::all_known().flat_map(|l| l.to_strings()).collect() + }) + .unwrap_or_default(); + + let languages = languages.into_iter().flat_map(|l| l.to_strings()).collect(); let stats = self .db - .compute_daily_stats(start, end, users, languages) + .compute_daily_stats(start, end, users, languages, not_languages) .await?; let stats = stats .into_iter()