mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Move tracing configuration to the rust side.
This commit is contained in:
committed by
Stefan Ceriu
parent
2671d90bc1
commit
57b85d2650
@@ -368,7 +368,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
}
|
||||
|
||||
if oldVersion < Version(1, 6, 7) {
|
||||
RustTracing.deleteLogFiles()
|
||||
Tracing.deleteLogFiles()
|
||||
MXLog.info("Migrating to v1.6.7, log files have been wiped")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import SwiftUI
|
||||
|
||||
// Common settings between app and NSE
|
||||
protocol CommonSettingsProtocol {
|
||||
var logLevel: TracingConfiguration.LogLevel { get }
|
||||
var logLevel: LogLevel { get }
|
||||
var enableOnlySignedDeviceIsolationMode: Bool { get }
|
||||
var hideTimelineMedia: Bool { get }
|
||||
var eventCacheEnabled: Bool { get }
|
||||
@@ -294,7 +294,7 @@ final class AppSettings {
|
||||
|
||||
// MARK: - Shared
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: TracingConfiguration.LogLevel.info, storageType: .userDefaults(store))
|
||||
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: LogLevel.info, storageType: .userDefaults(store))
|
||||
var logLevel
|
||||
|
||||
/// Configuration to enable only signed device isolation mode for crypto. In this mode only devices signed by their owner will be considered in e2ee rooms.
|
||||
|
||||
@@ -66,7 +66,7 @@ enum ExtensionLogger {
|
||||
return "\(formattedStr) MB"
|
||||
}
|
||||
|
||||
static func configure(currentTarget: String, logLevel: TracingConfiguration.LogLevel) {
|
||||
static func configure(currentTarget: String, logLevel: LogLevel) {
|
||||
guard !isConfigured else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
enum LogLevel: String, Codable, Hashable {
|
||||
case error, warn, info, debug, trace
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .error:
|
||||
return "Error"
|
||||
case .warn:
|
||||
return "Warning"
|
||||
case .info:
|
||||
return "Info"
|
||||
case .debug:
|
||||
return "Debug"
|
||||
case .trace:
|
||||
return "Trace"
|
||||
}
|
||||
}
|
||||
|
||||
var rustLogLevel: MatrixRustSDK.LogLevel {
|
||||
switch self {
|
||||
case .error:
|
||||
.error
|
||||
case .warn:
|
||||
.warn
|
||||
case .info:
|
||||
.info
|
||||
case .debug:
|
||||
.debug
|
||||
case .trace:
|
||||
.trace
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,10 +26,10 @@ enum MXLog {
|
||||
|
||||
static func configure(currentTarget: String,
|
||||
filePrefix: String?,
|
||||
logLevel: TracingConfiguration.LogLevel) {
|
||||
logLevel: LogLevel) {
|
||||
guard !didConfigureOnce else { return }
|
||||
|
||||
RustTracing.setup(configuration: .init(logLevel: logLevel, currentTarget: currentTarget, filePrefix: filePrefix))
|
||||
Tracing.setup(logLevel: logLevel, currentTarget: currentTarget, filePrefix: filePrefix)
|
||||
|
||||
self.currentTarget = currentTarget
|
||||
|
||||
@@ -135,7 +135,7 @@ enum MXLog {
|
||||
rootSpan.enter()
|
||||
}
|
||||
|
||||
return Span(file: file, line: UInt32(line), level: level, target: currentTarget, name: name)
|
||||
return Span(file: file, line: UInt32(line), level: level.rustLogLevel, target: currentTarget, name: name)
|
||||
}
|
||||
|
||||
// periphery:ignore:parameters function,column,context
|
||||
@@ -154,6 +154,6 @@ enum MXLog {
|
||||
rootSpan.enter()
|
||||
}
|
||||
|
||||
logEvent(file: (file as NSString).lastPathComponent, line: UInt32(line), level: level, target: currentTarget, message: "\(message)")
|
||||
logEvent(file: (file as NSString).lastPathComponent, line: UInt32(line), level: level.rustLogLevel, target: currentTarget, message: "\(message)")
|
||||
}
|
||||
}
|
||||
|
||||
+15
-13
@@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
enum RustTracing {
|
||||
enum Tracing {
|
||||
/// The base filename used for log files. This may be suffixed by the target
|
||||
/// name and other log management metadata during rotation.
|
||||
static let filePrefix = "console"
|
||||
@@ -21,27 +21,29 @@ enum RustTracing {
|
||||
}
|
||||
}
|
||||
|
||||
private(set) static var currentTracingConfiguration: TracingConfiguration?
|
||||
static func setup(configuration: TracingConfiguration) {
|
||||
currentTracingConfiguration = configuration
|
||||
static let fileExtension = "log"
|
||||
|
||||
static func setup(logLevel: LogLevel, currentTarget: String, filePrefix: String?) {
|
||||
let fileName = if let filePrefix {
|
||||
"\(Tracing.filePrefix)-\(filePrefix)"
|
||||
} else {
|
||||
Tracing.filePrefix
|
||||
}
|
||||
|
||||
// Keep a minimum of 1 week of log files. In reality it will be longer
|
||||
// as the app is unlikely to be running continuously.
|
||||
let maxFiles: UInt64 = 24 * 7
|
||||
|
||||
// Log everything on integration tests to check whether
|
||||
// the logs contain any sensitive data. See `UserFlowTests.swift`
|
||||
let filter = if ProcessInfo.isRunningIntegrationTests {
|
||||
TracingConfiguration(logLevel: .trace, currentTarget: "integrationtests", filePrefix: nil).filter
|
||||
} else {
|
||||
configuration.filter
|
||||
}
|
||||
// the logs contain any sensitive data. See `integration-tests.yml`
|
||||
let level: LogLevel = ProcessInfo.isRunningIntegrationTests ? .trace : logLevel
|
||||
|
||||
setupTracing(config: .init(filter: filter,
|
||||
setupTracing(config: .init(logLevel: level.rustLogLevel,
|
||||
extraTargets: [currentTarget],
|
||||
writeToStdoutOrSystem: true,
|
||||
writeToFiles: .init(path: logsDirectory.path(percentEncoded: false),
|
||||
filePrefix: configuration.fileName,
|
||||
fileSuffix: configuration.fileExtension,
|
||||
filePrefix: fileName,
|
||||
fileSuffix: fileExtension,
|
||||
maxFiles: maxFiles)))
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
//
|
||||
// Copyright 2024 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Collections
|
||||
|
||||
// This exposes the full Rust side tracing subscriber filter for more flexibility.
|
||||
// We can filter by level, crate and even file. See more details here:
|
||||
// https://docs.rs/tracing-subscriber/0.2.7/tracing_subscriber/filter/struct.EnvFilter.html#examples
|
||||
struct TracingConfiguration {
|
||||
enum LogLevel: String, Codable, Hashable, Comparable {
|
||||
case error, warn, info, debug, trace
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .error:
|
||||
return "Error"
|
||||
case .warn:
|
||||
return "Warning"
|
||||
case .info:
|
||||
return "Info"
|
||||
case .debug:
|
||||
return "Debug"
|
||||
case .trace:
|
||||
return "Trace"
|
||||
}
|
||||
}
|
||||
|
||||
static func < (lhs: TracingConfiguration.LogLevel, rhs: TracingConfiguration.LogLevel) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.error, _):
|
||||
true
|
||||
case (.warn, .error):
|
||||
false
|
||||
case (.warn, _):
|
||||
true
|
||||
case (.info, .error), (.info, .warn):
|
||||
false
|
||||
case (.info, _):
|
||||
true
|
||||
case (.debug, .error), (.debug, .warn), (.debug, .info):
|
||||
false
|
||||
case (.debug, _):
|
||||
true
|
||||
case (.trace, _):
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Target: String {
|
||||
case hyper, matrix_sdk_ffi, matrix_sdk_crypto
|
||||
|
||||
case matrix_sdk_client = "matrix_sdk::client"
|
||||
case matrix_sdk_crypto_account = "matrix_sdk_crypto::olm::account"
|
||||
case matrix_sdk_oidc = "matrix_sdk::oidc"
|
||||
case matrix_sdk_http_client = "matrix_sdk::http_client"
|
||||
case matrix_sdk_sliding_sync = "matrix_sdk::sliding_sync"
|
||||
case matrix_sdk_base_sliding_sync = "matrix_sdk_base::sliding_sync"
|
||||
case matrix_sdk_ui_timeline = "matrix_sdk_ui::timeline"
|
||||
case matrix_sdk_event_cache = "matrix_sdk::event_cache"
|
||||
case matrix_sdk_sqlite_event_cache_store = "matrix_sdk_sqlite::event_cache_store"
|
||||
}
|
||||
|
||||
// The `common` target is excluded because 3rd-party crates might end up logging user data.
|
||||
static let targets: OrderedDictionary<Target, LogLevel> = [
|
||||
.hyper: .warn,
|
||||
.matrix_sdk_ffi: .info,
|
||||
.matrix_sdk_client: .trace,
|
||||
.matrix_sdk_crypto: .debug,
|
||||
.matrix_sdk_crypto_account: .trace,
|
||||
.matrix_sdk_oidc: .trace,
|
||||
.matrix_sdk_http_client: .debug,
|
||||
.matrix_sdk_sliding_sync: .info,
|
||||
.matrix_sdk_base_sliding_sync: .info,
|
||||
.matrix_sdk_ui_timeline: .info,
|
||||
.matrix_sdk_event_cache: .info,
|
||||
.matrix_sdk_sqlite_event_cache_store: .info
|
||||
]
|
||||
|
||||
let filter: String
|
||||
|
||||
/// The filename that logs should be written to.
|
||||
let fileName: String
|
||||
/// The file extension to use for log files.
|
||||
let fileExtension = "log"
|
||||
|
||||
/// Sets the same log level for all Targets
|
||||
/// - Parameter logLevel: the desired log level
|
||||
/// - Parameter target: the name of the target being configured
|
||||
/// - Returns: a custom tracing configuration
|
||||
init(logLevel: LogLevel, currentTarget: String, filePrefix: String?) {
|
||||
fileName = if let filePrefix {
|
||||
"\(RustTracing.filePrefix)-\(filePrefix)"
|
||||
} else {
|
||||
RustTracing.filePrefix
|
||||
}
|
||||
|
||||
let overrides = Self.targets.keys.reduce(into: [Target: LogLevel]()) { partialResult, target in
|
||||
// Keep the defaults here
|
||||
let ignoredTargets: [Target] = [.hyper]
|
||||
|
||||
if ignoredTargets.contains(target) {
|
||||
return
|
||||
}
|
||||
|
||||
guard let defaultTargetLogLevel = Self.targets[target] else {
|
||||
return
|
||||
}
|
||||
|
||||
// Only change the targets that have default values
|
||||
// smaller than the desired log level
|
||||
if defaultTargetLogLevel < logLevel {
|
||||
partialResult[target] = logLevel
|
||||
}
|
||||
}
|
||||
|
||||
var newTargets = Self.targets
|
||||
for (target, logLevel) in overrides {
|
||||
newTargets.updateValue(logLevel, forKey: target)
|
||||
}
|
||||
|
||||
var components = newTargets.map { (target: Target, logLevel: LogLevel) in
|
||||
guard !target.rawValue.isEmpty else {
|
||||
return logLevel.rawValue
|
||||
}
|
||||
|
||||
return "\(target.rawValue)=\(logLevel.rawValue)"
|
||||
}
|
||||
|
||||
// With `common` not being used we manually need to specify the log
|
||||
// level for passed in targets
|
||||
components.append("\(currentTarget)=\(logLevel.rawValue)")
|
||||
|
||||
filter = components.joined(separator: ",")
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class LogViewerScreenViewModel: LogViewerScreenViewModelType, LogViewerScreenVie
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(initialViewState: LogViewerScreenViewState(urls: RustTracing.logFiles))
|
||||
super.init(initialViewState: LogViewerScreenViewState(urls: Tracing.logFiles))
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ enum DeveloperOptionsScreenViewAction {
|
||||
}
|
||||
|
||||
protocol DeveloperOptionsProtocol: AnyObject {
|
||||
var logLevel: TracingConfiguration.LogLevel { get set }
|
||||
var logLevel: LogLevel { get set }
|
||||
var slidingSyncDiscovery: AppSettings.SlidingSyncDiscovery { get set }
|
||||
var publicSearchEnabled: Bool { get set }
|
||||
var hideUnreadMessagesBadge: Bool { get set }
|
||||
|
||||
+2
-2
@@ -152,7 +152,7 @@ struct DeveloperOptionsScreen: View {
|
||||
}
|
||||
|
||||
private struct LogLevelConfigurationView: View {
|
||||
@Binding var logLevel: TracingConfiguration.LogLevel
|
||||
@Binding var logLevel: LogLevel
|
||||
|
||||
var body: some View {
|
||||
Picker(selection: $logLevel) {
|
||||
@@ -166,7 +166,7 @@ private struct LogLevelConfigurationView: View {
|
||||
}
|
||||
|
||||
/// Allows the picker to work with associated values
|
||||
private var logLevels: [TracingConfiguration.LogLevel] {
|
||||
private var logLevels: [LogLevel] {
|
||||
[.error, .warn, .info, .debug, .trace]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class BugReportService: NSObject, BugReportServiceProtocol {
|
||||
}
|
||||
|
||||
if bugReport.includeLogs {
|
||||
let logAttachments = await zipFiles(RustTracing.logFiles)
|
||||
let logAttachments = await zipFiles(Tracing.logFiles)
|
||||
for url in logAttachments.files {
|
||||
params.append(MultipartFormData(key: "compressed-log", type: .file(url: url)))
|
||||
}
|
||||
@@ -163,8 +163,7 @@ class BugReportService: NSObject, BugReportServiceProtocol {
|
||||
MultipartFormData(key: "fallback_language", type: .text(value: Bundle.app.developmentLocalization ?? "null")),
|
||||
MultipartFormData(key: "local_time", type: .text(value: localTime)),
|
||||
MultipartFormData(key: "utc_time", type: .text(value: utcTime)),
|
||||
MultipartFormData(key: "base_bundle_identifier", type: .text(value: InfoPlistReader.main.baseBundleIdentifier)),
|
||||
MultipartFormData(key: "rust_tracing_filter", type: .text(value: RustTracing.currentTracingConfiguration?.filter ?? "null"))
|
||||
MultipartFormData(key: "base_bundle_identifier", type: .text(value: InfoPlistReader.main.baseBundleIdentifier))
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user