Added a lot of functionality. Bugfixes and changes
This commit is contained in:
154
oAI/Services/EmailLogService.swift
Normal file
154
oAI/Services/EmailLogService.swift
Normal file
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// EmailLogService.swift
|
||||
// oAI
|
||||
//
|
||||
// Service for managing email handler activity logs
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
@Observable
|
||||
final class EmailLogService {
|
||||
static let shared = EmailLogService()
|
||||
|
||||
private let db = DatabaseService.shared
|
||||
private let log = Logger(subsystem: "com.oai.oAI", category: "email-log")
|
||||
|
||||
private init() {}
|
||||
|
||||
// MARK: - Log Operations
|
||||
|
||||
/// Save a successful email processing log
|
||||
func logSuccess(
|
||||
sender: String,
|
||||
subject: String,
|
||||
emailContent: String,
|
||||
aiResponse: String,
|
||||
tokens: Int?,
|
||||
cost: Double?,
|
||||
responseTime: TimeInterval?,
|
||||
modelId: String?
|
||||
) {
|
||||
let entry = EmailLog(
|
||||
sender: sender,
|
||||
subject: subject,
|
||||
emailContent: emailContent,
|
||||
aiResponse: aiResponse,
|
||||
status: .success,
|
||||
tokens: tokens,
|
||||
cost: cost,
|
||||
responseTime: responseTime,
|
||||
modelId: modelId
|
||||
)
|
||||
|
||||
db.saveEmailLog(entry)
|
||||
log.info("Email log saved: \(sender) - \(subject) [SUCCESS]")
|
||||
}
|
||||
|
||||
/// Save a failed email processing log
|
||||
func logError(
|
||||
sender: String,
|
||||
subject: String,
|
||||
emailContent: String,
|
||||
errorMessage: String,
|
||||
modelId: String?
|
||||
) {
|
||||
let entry = EmailLog(
|
||||
sender: sender,
|
||||
subject: subject,
|
||||
emailContent: emailContent,
|
||||
aiResponse: nil,
|
||||
status: .error,
|
||||
errorMessage: errorMessage,
|
||||
modelId: modelId
|
||||
)
|
||||
|
||||
db.saveEmailLog(entry)
|
||||
log.error("Email log saved: \(sender) - \(subject) [ERROR: \(errorMessage)]")
|
||||
}
|
||||
|
||||
/// Load recent email logs (default: 100 most recent)
|
||||
func loadLogs(limit: Int = 100) -> [EmailLog] {
|
||||
do {
|
||||
return try db.loadEmailLogs(limit: limit)
|
||||
} catch {
|
||||
log.error("Failed to load email logs: \(error.localizedDescription)")
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a specific log entry
|
||||
func deleteLog(id: UUID) {
|
||||
db.deleteEmailLog(id: id)
|
||||
log.info("Email log deleted: \(id.uuidString)")
|
||||
}
|
||||
|
||||
/// Clear all email logs
|
||||
func clearAllLogs() {
|
||||
db.clearEmailLogs()
|
||||
log.info("All email logs cleared")
|
||||
}
|
||||
|
||||
/// Get total count of email logs
|
||||
func getLogCount() -> Int {
|
||||
do {
|
||||
return try db.getEmailLogCount()
|
||||
} catch {
|
||||
log.error("Failed to get email log count: \(error.localizedDescription)")
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Statistics
|
||||
|
||||
/// Get email processing statistics
|
||||
func getStatistics() -> EmailStatistics {
|
||||
let logs = loadLogs(limit: 1000) // Last 1000 for stats
|
||||
|
||||
let total = logs.count
|
||||
let successful = logs.filter { $0.status == .success }.count
|
||||
let errors = logs.filter { $0.status == .error }.count
|
||||
|
||||
let totalTokens = logs.compactMap { $0.tokens }.reduce(0, +)
|
||||
let totalCost = logs.compactMap { $0.cost }.reduce(0.0, +)
|
||||
|
||||
let avgResponseTime: TimeInterval?
|
||||
let responseTimes = logs.compactMap { $0.responseTime }
|
||||
if !responseTimes.isEmpty {
|
||||
avgResponseTime = responseTimes.reduce(0, +) / Double(responseTimes.count)
|
||||
} else {
|
||||
avgResponseTime = nil
|
||||
}
|
||||
|
||||
return EmailStatistics(
|
||||
total: total,
|
||||
successful: successful,
|
||||
errors: errors,
|
||||
totalTokens: totalTokens,
|
||||
totalCost: totalCost,
|
||||
averageResponseTime: avgResponseTime
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Statistics Model
|
||||
|
||||
struct EmailStatistics {
|
||||
let total: Int
|
||||
let successful: Int
|
||||
let errors: Int
|
||||
let totalTokens: Int
|
||||
let totalCost: Double
|
||||
let averageResponseTime: TimeInterval?
|
||||
|
||||
var successRate: Double {
|
||||
guard total > 0 else { return 0.0 }
|
||||
return Double(successful) / Double(total)
|
||||
}
|
||||
|
||||
var errorRate: Double {
|
||||
guard total > 0 else { return 0.0 }
|
||||
return Double(errors) / Double(total)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user