-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCostTrackingDecorator.cs
More file actions
110 lines (87 loc) · 4.49 KB
/
CostTrackingDecorator.cs
File metadata and controls
110 lines (87 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using ProjectVG.Application.Models.Chat;
namespace ProjectVG.Application.Services.Chat.CostTracking
{
public class CostTrackingDecorator<T> : ICostTrackingDecorator<T> where T : class
{
private readonly T _service;
private readonly IChatMetricsService _metricsService;
private readonly string _processName;
public CostTrackingDecorator(T service, IChatMetricsService metricsService, string processName)
{
_service = service;
_metricsService = metricsService;
_processName = processName;
}
public T Service => _service;
private decimal ExtractCost(object? result)
{
if (result == null) return 0;
var resultType = result.GetType();
// Cost 속성이 있는 경우
var costProperty = resultType.GetProperty("Cost");
if (costProperty != null)
{
var costValue = costProperty.GetValue(result);
if (costValue != null)
{
// double, decimal, int 등 다양한 타입 지원
return Convert.ToDecimal(costValue);
}
}
return 0;
}
public async Task ProcessAsync(ChatProcessContext context)
{
_metricsService.StartProcessMetrics(_processName);
try
{
// 리플렉션으로 ProcessAsync 메서드 호출
var method = typeof(T).GetMethod("ProcessAsync", new[] { typeof(ChatProcessContext) });
if (method == null)
throw new InvalidOperationException($"ProcessAsync 메서드를 찾을 수 없습니다: {typeof(T).Name}");
var invokeResult = method.Invoke(_service, new object[] { context });
if (invokeResult == null)
throw new InvalidOperationException($"ProcessAsync 메서드 호출 결과가 null입니다: {typeof(T).Name}");
if (invokeResult is not Task taskResult)
throw new InvalidOperationException($"ProcessAsync 메서드 반환 타입이 올바르지 않습니다: {typeof(T).Name}");
await taskResult;
// Cost 값만 직접 추출
var cost = ExtractCost(context);
Console.WriteLine($"[COST_TRACKING] {_processName} - 추출된 비용: {cost:F0} Cost");
Console.WriteLine($"[COST_TRACKING] {_processName} - 컨텍스트 타입: {context?.GetType().Name}, Cost 속성 값: {context?.GetType().GetProperty("Cost")?.GetValue(context)}");
_metricsService.EndProcessMetrics(_processName, cost);
}
catch (Exception ex)
{
_metricsService.EndProcessMetrics(_processName, 0, ex.Message);
throw;
}
}
public async Task ProcessAsync(ChatRequestCommand request)
{
_metricsService.StartProcessMetrics(_processName);
try
{
// 리플렉션으로 ProcessAsync 메서드 호출
var method = typeof(T).GetMethod("ProcessAsync", new[] { typeof(ChatRequestCommand) });
if (method == null)
throw new InvalidOperationException($"ProcessAsync 메서드를 찾을 수 없습니다: {typeof(T).Name}");
var invokeResult = method.Invoke(_service, new object[] { request });
if (invokeResult == null)
throw new InvalidOperationException($"ProcessAsync 메서드 호출 결과가 null입니다: {typeof(T).Name}");
if (invokeResult is not Task taskResult)
throw new InvalidOperationException($"ProcessAsync 메서드 반환 타입이 올바르지 않습니다: {typeof(T).Name}");
await taskResult;
// Cost는 request 객체에서 직접 가져올 수 있음
var cost = request.Cost;
Console.WriteLine($"[COST_TRACKING] {_processName} - 추출된 비용: {cost:F0} Cost");
_metricsService.EndProcessMetrics(_processName, (decimal)cost);
}
catch (Exception ex)
{
_metricsService.EndProcessMetrics(_processName, 0, ex.Message);
throw;
}
}
}
}