Move tracing configuration to the rust side.

This commit is contained in:
Stefan Ceriu
2025-01-09 13:23:14 +02:00
committed by Stefan Ceriu
parent 2671d90bc1
commit 57b85d2650
14 changed files with 100 additions and 244 deletions
@@ -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
}
}
}
+4 -4
View File
@@ -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)")
}
}
@@ -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: ",")
}
}