Salva telemetria client (OS, app, device, operatore) sulle sessioni per il debug admin.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Network
|
||||
import CoreTelephony
|
||||
|
||||
struct DeviceHealth: Sendable {
|
||||
let batteryPercent: Int
|
||||
@@ -8,6 +9,16 @@ struct DeviceHealth: Sendable {
|
||||
let networkType: String
|
||||
}
|
||||
|
||||
struct ClientInfoPayload: Encodable, Sendable {
|
||||
let os: String
|
||||
let appVersion: String?
|
||||
let appBuild: String?
|
||||
let deviceManufacturer: String?
|
||||
let deviceModel: String?
|
||||
let osVersion: String?
|
||||
let carrier: String?
|
||||
}
|
||||
|
||||
enum DeviceTelemetry {
|
||||
static func snapshot(thermalState: ThermalState? = nil) -> DeviceHealth {
|
||||
UIDevice.current.isBatteryMonitoringEnabled = true
|
||||
@@ -20,6 +31,24 @@ enum DeviceTelemetry {
|
||||
)
|
||||
}
|
||||
|
||||
static func clientInfo() -> ClientInfoPayload {
|
||||
let bundle = Bundle.main
|
||||
let version = bundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
|
||||
let build = bundle.object(forInfoDictionaryKey: "CFBundleVersion") as? String
|
||||
let model = UIDevice.current.model
|
||||
// Prefer machine identifier when available (e.g. iPhone15,2)
|
||||
let machine = utsnameMachine()
|
||||
return ClientInfoPayload(
|
||||
os: "ios",
|
||||
appVersion: version,
|
||||
appBuild: build,
|
||||
deviceManufacturer: "Apple",
|
||||
deviceModel: machine ?? model,
|
||||
osVersion: UIDevice.current.systemVersion,
|
||||
carrier: carrierName()
|
||||
)
|
||||
}
|
||||
|
||||
private static func currentNetworkType() -> String {
|
||||
let monitor = NWPathMonitor()
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
@@ -40,4 +69,27 @@ enum DeviceTelemetry {
|
||||
monitor.cancel()
|
||||
return result
|
||||
}
|
||||
|
||||
private static func carrierName() -> String? {
|
||||
let info = CTTelephonyNetworkInfo()
|
||||
if let providers = info.serviceSubscriberCellularProviders {
|
||||
for carrier in providers.values {
|
||||
if let name = carrier.carrierName?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!name.isEmpty {
|
||||
return name
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func utsnameMachine() -> String? {
|
||||
var systemInfo = utsname()
|
||||
uname(&systemInfo)
|
||||
return withUnsafePointer(to: &systemInfo.machine) {
|
||||
$0.withMemoryRebound(to: CChar.self, capacity: 1) {
|
||||
String(validatingUTF8: $0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,6 +435,7 @@ struct CreateSessionRequest: Encodable {
|
||||
let targetBitrate: Int
|
||||
let targetFps: Int
|
||||
let youtubeChannel: String?
|
||||
let client: ClientInfoPayload?
|
||||
}
|
||||
|
||||
struct AudioMuteRequest: Encodable {
|
||||
@@ -531,6 +532,7 @@ struct TelemetryRequest: Encodable {
|
||||
let targetBitrate: Int?
|
||||
let fps: Int?
|
||||
let thermalState: String?
|
||||
let client: ClientInfoPayload?
|
||||
}
|
||||
|
||||
extension ScoringRules {
|
||||
|
||||
@@ -25,7 +25,8 @@ final class SessionRepository {
|
||||
qualityPreset: qualityPreset,
|
||||
targetBitrate: targetBitrate,
|
||||
targetFps: targetFps,
|
||||
youtubeChannel: youtubeChannel
|
||||
youtubeChannel: youtubeChannel,
|
||||
client: DeviceTelemetry.clientInfo()
|
||||
)
|
||||
).toDomain()
|
||||
}
|
||||
@@ -97,7 +98,8 @@ final class SessionRepository {
|
||||
currentBitrate: currentBitrate,
|
||||
targetBitrate: targetBitrate,
|
||||
fps: fps,
|
||||
thermalState: health.thermalState.apiValue
|
||||
thermalState: health.thermalState.apiValue,
|
||||
client: DeviceTelemetry.clientInfo()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user