@@ -268,6 +268,90 @@ pub fn delete_setting(conn: &Connection, key: &str) -> anyhow::Result<()> {
268268 Ok ( ( ) )
269269}
270270
271+ // ---------------------------------------------------------------------------
272+ // Usage Logs
273+ // ---------------------------------------------------------------------------
274+
275+ pub fn insert_usage_log (
276+ conn : & Connection ,
277+ id : & str ,
278+ thread_id : & str ,
279+ session_id : Option < & str > ,
280+ input_tokens : i64 ,
281+ output_tokens : i64 ,
282+ cache_read_tokens : i64 ,
283+ cache_write_tokens : i64 ,
284+ cost_usd : f64 ,
285+ model : Option < & str > ,
286+ created_at : & str ,
287+ ) -> anyhow:: Result < ( ) > {
288+ conn. execute (
289+ "INSERT INTO usage_logs (id, thread_id, session_id, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_usd, model, created_at) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)" ,
290+ params ! [ id, thread_id, session_id, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_usd, model, created_at] ,
291+ ) ?;
292+ Ok ( ( ) )
293+ }
294+
295+ pub fn get_usage_totals ( conn : & Connection ) -> anyhow:: Result < ( i64 , i64 , i64 , i64 , f64 ) > {
296+ let mut stmt = conn. prepare (
297+ "SELECT COALESCE(SUM(input_tokens),0), COALESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read_tokens),0), COALESCE(SUM(cache_write_tokens),0), COALESCE(SUM(cost_usd),0.0) FROM usage_logs" ,
298+ ) ?;
299+ let result = stmt. query_row ( [ ] , |row| {
300+ Ok ( (
301+ row. get :: < _ , i64 > ( 0 ) ?,
302+ row. get :: < _ , i64 > ( 1 ) ?,
303+ row. get :: < _ , i64 > ( 2 ) ?,
304+ row. get :: < _ , i64 > ( 3 ) ?,
305+ row. get :: < _ , f64 > ( 4 ) ?,
306+ ) )
307+ } ) ?;
308+ Ok ( result)
309+ }
310+
311+ pub fn get_usage_by_thread ( conn : & Connection ) -> anyhow:: Result < Vec < ( String , f64 , i64 ) > > {
312+ let mut stmt = conn. prepare (
313+ "SELECT u.thread_id, COALESCE(SUM(u.cost_usd),0.0), COALESCE(SUM(u.input_tokens + u.output_tokens),0) FROM usage_logs u GROUP BY u.thread_id ORDER BY SUM(u.cost_usd) DESC" ,
314+ ) ?;
315+ let rows = stmt. query_map ( [ ] , |row| {
316+ Ok ( (
317+ row. get :: < _ , String > ( 0 ) ?,
318+ row. get :: < _ , f64 > ( 1 ) ?,
319+ row. get :: < _ , i64 > ( 2 ) ?,
320+ ) )
321+ } ) ?;
322+ rows. map ( |r| r. map_err ( Into :: into) ) . collect ( )
323+ }
324+
325+ pub fn get_usage_by_model ( conn : & Connection ) -> anyhow:: Result < Vec < ( String , f64 , i64 ) > > {
326+ let mut stmt = conn. prepare (
327+ "SELECT COALESCE(model,'unknown'), COALESCE(SUM(cost_usd),0.0), COALESCE(SUM(input_tokens + output_tokens),0) FROM usage_logs GROUP BY model ORDER BY SUM(cost_usd) DESC" ,
328+ ) ?;
329+ let rows = stmt. query_map ( [ ] , |row| {
330+ Ok ( (
331+ row. get :: < _ , String > ( 0 ) ?,
332+ row. get :: < _ , f64 > ( 1 ) ?,
333+ row. get :: < _ , i64 > ( 2 ) ?,
334+ ) )
335+ } ) ?;
336+ rows. map ( |r| r. map_err ( Into :: into) ) . collect ( )
337+ }
338+
339+ pub fn get_usage_for_thread ( conn : & Connection , thread_id : & str ) -> anyhow:: Result < ( i64 , i64 , i64 , i64 , f64 ) > {
340+ let mut stmt = conn. prepare (
341+ "SELECT COALESCE(SUM(input_tokens),0), COALESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read_tokens),0), COALESCE(SUM(cache_write_tokens),0), COALESCE(SUM(cost_usd),0.0) FROM usage_logs WHERE thread_id = ?1" ,
342+ ) ?;
343+ let result = stmt. query_row ( params ! [ thread_id] , |row| {
344+ Ok ( (
345+ row. get :: < _ , i64 > ( 0 ) ?,
346+ row. get :: < _ , i64 > ( 1 ) ?,
347+ row. get :: < _ , i64 > ( 2 ) ?,
348+ row. get :: < _ , i64 > ( 3 ) ?,
349+ row. get :: < _ , f64 > ( 4 ) ?,
350+ ) )
351+ } ) ?;
352+ Ok ( result)
353+ }
354+
271355// ---------------------------------------------------------------------------
272356// Internal row types for mapping from SQLite text columns
273357// ---------------------------------------------------------------------------
0 commit comments