Merge pull request #867 from iceljc/master

refine statistics
This commit is contained in:
iceljc 2025-02-03 20:19:24 -06:00 committed by GitHub
commit 0aa14205cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 24 additions and 10 deletions

View file

@ -200,7 +200,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
#endregion #endregion
#region Statistics #region Statistics
BotSharpStats? GetGlobalStats(string metric, string dimension, DateTime recordTime, StatsInterval interval) BotSharpStats? GetGlobalStats(string metric, string dimension, string value, DateTime recordTime, StatsInterval interval)
=> throw new NotImplementedException(); => throw new NotImplementedException();
bool SaveGlobalStats(BotSharpStats body) bool SaveGlobalStats(BotSharpStats body)
=> throw new NotImplementedException(); => throw new NotImplementedException();

View file

@ -10,6 +10,9 @@ public class BotSharpStats
[JsonPropertyName("dimension")] [JsonPropertyName("dimension")]
public string Dimension { get; set; } = null!; public string Dimension { get; set; } = null!;
[JsonPropertyName("value")]
public string Value { get; set; } = null!;
[JsonPropertyName("data")] [JsonPropertyName("data")]
public IDictionary<string, double> Data { get; set; } = new Dictionary<string, double>(); public IDictionary<string, double> Data { get; set; } = new Dictionary<string, double>();
@ -43,7 +46,7 @@ public class BotSharpStats
public override string ToString() public override string ToString()
{ {
return $"{Metric}-{Dimension} ({Interval}): {Data?.Count ?? 0}"; return $"{Metric}-{Dimension}-{Value} ({Interval}): {Data?.Count ?? 0}";
} }
public static (DateTime, DateTime) BuildTimeInterval(DateTime recordTime, StatsInterval interval) public static (DateTime, DateTime) BuildTimeInterval(DateTime recordTime, StatsInterval interval)

View file

@ -6,6 +6,7 @@ public class BotSharpStatsInput
{ {
public string Metric { get; set; } public string Metric { get; set; }
public string Dimension { get; set; } public string Dimension { get; set; }
public string Value { get; set; }
public List<StatsKeyValuePair> Data { get; set; } = []; public List<StatsKeyValuePair> Data { get; set; } = [];
public DateTime RecordTime { get; set; } = DateTime.UtcNow; public DateTime RecordTime { get; set; } = DateTime.UtcNow;
public StatsInterval IntervalType { get; set; } = StatsInterval.Day; public StatsInterval IntervalType { get; set; } = StatsInterval.Day;

View file

@ -64,7 +64,8 @@ public class TokenStatistics : ITokenStatistics
var body = new BotSharpStatsInput var body = new BotSharpStatsInput
{ {
Metric = StatsCategory.AgentLlmCost, Metric = StatsCategory.AgentLlmCost,
Dimension = message.CurrentAgentId, Dimension = "agent",
Value = message.CurrentAgentId,
RecordTime = DateTime.UtcNow, RecordTime = DateTime.UtcNow,
IntervalType = StatsInterval.Day, IntervalType = StatsInterval.Day,
Data = [ Data = [

View file

@ -4,7 +4,7 @@ namespace BotSharp.Core.Repository;
public partial class FileRepository public partial class FileRepository
{ {
public BotSharpStats? GetGlobalStats(string metric, string dimension, DateTime recordTime, StatsInterval interval) public BotSharpStats? GetGlobalStats(string metric, string dimension, string value, DateTime recordTime, StatsInterval interval)
{ {
var baseDir = Path.Combine(_dbSettings.FileRepository, STATS_FOLDER); var baseDir = Path.Combine(_dbSettings.FileRepository, STATS_FOLDER);
var (startTime, endTime) = BotSharpStats.BuildTimeInterval(recordTime, interval); var (startTime, endTime) = BotSharpStats.BuildTimeInterval(recordTime, interval);
@ -18,6 +18,7 @@ public partial class FileRepository
var list = JsonSerializer.Deserialize<List<BotSharpStats>>(text, _options); var list = JsonSerializer.Deserialize<List<BotSharpStats>>(text, _options);
var found = list?.FirstOrDefault(x => x.Metric.IsEqualTo(metric) var found = list?.FirstOrDefault(x => x.Metric.IsEqualTo(metric)
&& x.Dimension.IsEqualTo(dimension) && x.Dimension.IsEqualTo(dimension)
&& x.Value.IsEqualTo(value)
&& x.StartTime == startTime && x.StartTime == startTime
&& x.EndTime == endTime); && x.EndTime == endTime);
@ -49,6 +50,7 @@ public partial class FileRepository
var list = JsonSerializer.Deserialize<List<BotSharpStats>>(text, _options); var list = JsonSerializer.Deserialize<List<BotSharpStats>>(text, _options);
var found = list?.FirstOrDefault(x => x.Metric.IsEqualTo(body.Metric) var found = list?.FirstOrDefault(x => x.Metric.IsEqualTo(body.Metric)
&& x.Dimension.IsEqualTo(body.Dimension) && x.Dimension.IsEqualTo(body.Dimension)
&& x.Value.IsEqualTo(body.Value)
&& x.StartTime == startTime && x.StartTime == startTime
&& x.EndTime == endTime); && x.EndTime == endTime);
@ -56,6 +58,7 @@ public partial class FileRepository
{ {
found.Metric = body.Metric; found.Metric = body.Metric;
found.Dimension = body.Dimension; found.Dimension = body.Dimension;
found.Value = body.Value;
found.Data = body.Data; found.Data = body.Data;
found.RecordTime = body.RecordTime; found.RecordTime = body.RecordTime;
found.StartTime = body.StartTime; found.StartTime = body.StartTime;

View file

@ -31,6 +31,7 @@ public class BotSharpStatsService : IBotSharpStatsService
|| input == null || input == null
|| string.IsNullOrEmpty(input.Metric) || string.IsNullOrEmpty(input.Metric)
|| string.IsNullOrEmpty(input.Dimension) || string.IsNullOrEmpty(input.Dimension)
|| string.IsNullOrEmpty(input.Value)
|| input.Data.IsNullOrEmpty()) || input.Data.IsNullOrEmpty())
{ {
return false; return false;
@ -40,13 +41,14 @@ public class BotSharpStatsService : IBotSharpStatsService
var res = locker.Lock(resourceKey, () => var res = locker.Lock(resourceKey, () =>
{ {
var db = _services.GetRequiredService<IBotSharpRepository>(); var db = _services.GetRequiredService<IBotSharpRepository>();
var body = db.GetGlobalStats(input.Metric, input.Dimension, input.RecordTime, input.IntervalType); var body = db.GetGlobalStats(input.Metric, input.Dimension, input.Value, input.RecordTime, input.IntervalType);
if (body == null) if (body == null)
{ {
var stats = new BotSharpStats var stats = new BotSharpStats
{ {
Metric = input.Metric, Metric = input.Metric,
Dimension = input.Dimension, Dimension = input.Dimension,
Value = input.Value,
RecordTime = input.RecordTime, RecordTime = input.RecordTime,
IntervalType = input.IntervalType, IntervalType = input.IntervalType,
Data = input.Data.ToDictionary(x => x.Key, x => x.Value) Data = input.Data.ToDictionary(x => x.Key, x => x.Value)
@ -87,7 +89,7 @@ public class BotSharpStatsService : IBotSharpStatsService
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError($"Error when updating global stats {input.Metric}-{input.Dimension}. {ex.Message}\r\n{ex.InnerException}"); _logger.LogError($"Error when updating global stats {input.Metric}-{input.Dimension}-{input.Value}. {ex.Message}\r\n{ex.InnerException}");
return false; return false;
} }
} }

View file

@ -32,7 +32,8 @@ public class GlobalStatsConversationHook : ConversationHookBase
var body = new BotSharpStatsInput var body = new BotSharpStatsInput
{ {
Metric = StatsCategory.AgentCall, Metric = StatsCategory.AgentCall,
Dimension = message.CurrentAgentId, Dimension = "agent",
Value = message.CurrentAgentId,
RecordTime = DateTime.UtcNow, RecordTime = DateTime.UtcNow,
IntervalType = StatsInterval.Day, IntervalType = StatsInterval.Day,
Data = [ Data = [

View file

@ -1,11 +1,10 @@
using BotSharp.Abstraction.Statistics.Enums;
namespace BotSharp.Plugin.MongoStorage.Collections; namespace BotSharp.Plugin.MongoStorage.Collections;
public class GlobalStatisticsDocument : MongoBase public class GlobalStatisticsDocument : MongoBase
{ {
public string Metric { get; set; } public string Metric { get; set; }
public string Dimension { get; set; } public string Dimension { get; set; }
public string Value { get; set; }
public IDictionary<string, double> Data { get; set; } = new Dictionary<string, double>(); public IDictionary<string, double> Data { get; set; } = new Dictionary<string, double>();
public DateTime RecordTime { get; set; } public DateTime RecordTime { get; set; }
public DateTime StartTime { get; set; } public DateTime StartTime { get; set; }

View file

@ -5,7 +5,7 @@ namespace BotSharp.Plugin.MongoStorage.Repository;
public partial class MongoRepository public partial class MongoRepository
{ {
public BotSharpStats? GetGlobalStats(string metric, string dimension, DateTime recordTime, StatsInterval interval) public BotSharpStats? GetGlobalStats(string metric, string dimension, string value, DateTime recordTime, StatsInterval interval)
{ {
var (startTime, endTime) = BotSharpStats.BuildTimeInterval(recordTime, interval); var (startTime, endTime) = BotSharpStats.BuildTimeInterval(recordTime, interval);
@ -14,6 +14,7 @@ public partial class MongoRepository
{ {
builder.Eq(x => x.Metric, metric), builder.Eq(x => x.Metric, metric),
builder.Eq(x => x.Dimension, dimension), builder.Eq(x => x.Dimension, dimension),
builder.Eq(x => x.Value, value),
builder.Eq(x => x.StartTime, startTime), builder.Eq(x => x.StartTime, startTime),
builder.Eq(x => x.EndTime, endTime) builder.Eq(x => x.EndTime, endTime)
}; };
@ -26,6 +27,7 @@ public partial class MongoRepository
{ {
Metric = found.Metric, Metric = found.Metric,
Dimension = found.Dimension, Dimension = found.Dimension,
Value = found.Value,
Data = found.Data, Data = found.Data,
RecordTime = found.RecordTime, RecordTime = found.RecordTime,
StartTime = startTime, StartTime = startTime,
@ -46,6 +48,7 @@ public partial class MongoRepository
{ {
builder.Eq(x => x.Metric, body.Metric), builder.Eq(x => x.Metric, body.Metric),
builder.Eq(x => x.Dimension, body.Dimension), builder.Eq(x => x.Dimension, body.Dimension),
builder.Eq(x => x.Value, body.Value),
builder.Eq(x => x.StartTime, startTime), builder.Eq(x => x.StartTime, startTime),
builder.Eq(x => x.EndTime, endTime) builder.Eq(x => x.EndTime, endTime)
}; };
@ -55,6 +58,7 @@ public partial class MongoRepository
.SetOnInsert(x => x.Id, Guid.NewGuid().ToString()) .SetOnInsert(x => x.Id, Guid.NewGuid().ToString())
.Set(x => x.Metric, body.Metric) .Set(x => x.Metric, body.Metric)
.Set(x => x.Dimension, body.Dimension) .Set(x => x.Dimension, body.Dimension)
.Set(x => x.Value, body.Value)
.Set(x => x.Data, body.Data) .Set(x => x.Data, body.Data)
.Set(x => x.StartTime, body.StartTime) .Set(x => x.StartTime, body.StartTime)
.Set(x => x.EndTime, body.EndTime) .Set(x => x.EndTime, body.EndTime)