mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Allow setting custom log levels (#1592)
* Allow using custom tracing configuration from the developer options screen. Clean up RustTracing * Move log level configurations to a separate view * Disable autocorrection * Fix unit tests * Use TracingConfiguration.info as the default text value, switch to a TextEditor
This commit is contained in:
@@ -59,7 +59,7 @@ enum MXLog {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setupTracing(configuration: .custom(logLevel: logLevel), otlpConfiguration: otlpConfiguration)
|
setupTracing(configuration: .init(logLevel: logLevel), otlpConfiguration: otlpConfiguration)
|
||||||
|
|
||||||
if let target {
|
if let target {
|
||||||
self.target = target
|
self.target = target
|
||||||
|
|||||||
@@ -27,31 +27,45 @@ struct OTLPConfiguration {
|
|||||||
// We can filter by level, crate and even file. See more details here:
|
// 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
|
// https://docs.rs/tracing-subscriber/0.2.7/tracing_subscriber/filter/struct.EnvFilter.html#examples
|
||||||
struct TracingConfiguration {
|
struct TracingConfiguration {
|
||||||
/// Configure tracing with certain overrides in place
|
enum LogLevel: Codable, Hashable {
|
||||||
/// - Parameter overrides: the desired overrides
|
case error, warn, info, debug, trace
|
||||||
/// - Returns: a custom tracing configuration
|
case custom(String)
|
||||||
static func custom(overrides: [Target: LogLevel]) -> TracingConfiguration {
|
|
||||||
TracingConfiguration(overrides: overrides)
|
var title: String {
|
||||||
}
|
switch self {
|
||||||
|
case .error:
|
||||||
/// Sets the same log level for all Targets
|
return "Error"
|
||||||
/// - Parameter logLevel: the desired log level
|
case .warn:
|
||||||
/// - Returns: a custom tracing configuration
|
return "Warning"
|
||||||
static func custom(logLevel: LogLevel) -> TracingConfiguration {
|
case .info:
|
||||||
let overrides = targets.keys.reduce(into: [Target: LogLevel]()) { partialResult, target in
|
return "Info"
|
||||||
// Keep the defaults here
|
case .debug:
|
||||||
if target == .common || target == .hyper {
|
return "Debug"
|
||||||
return
|
case .trace:
|
||||||
|
return "Trace"
|
||||||
|
case .custom:
|
||||||
|
return "Custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var rawValue: String {
|
||||||
|
switch self {
|
||||||
|
case .error:
|
||||||
|
return "error"
|
||||||
|
case .warn:
|
||||||
|
return "warn"
|
||||||
|
case .info:
|
||||||
|
return "info"
|
||||||
|
case .debug:
|
||||||
|
return "debug"
|
||||||
|
case .trace:
|
||||||
|
return "trace"
|
||||||
|
case .custom(let filter):
|
||||||
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
partialResult[target] = logLevel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TracingConfiguration(overrides: overrides)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LogLevel: String, Codable, CaseIterable { case error, warn, info, debug, trace }
|
|
||||||
|
|
||||||
enum Target: String {
|
enum Target: String {
|
||||||
case common = ""
|
case common = ""
|
||||||
|
|
||||||
@@ -77,9 +91,26 @@ struct TracingConfiguration {
|
|||||||
.matrix_sdk_ui_timeline: .info
|
.matrix_sdk_ui_timeline: .info
|
||||||
]
|
]
|
||||||
|
|
||||||
var overrides = [Target: LogLevel]()
|
let filter: String
|
||||||
|
|
||||||
var filter: String {
|
/// Sets the same log level for all Targets
|
||||||
|
/// - Parameter logLevel: the desired log level
|
||||||
|
/// - Returns: a custom tracing configuration
|
||||||
|
init(logLevel: LogLevel) {
|
||||||
|
if case let .custom(filter) = logLevel {
|
||||||
|
self.filter = filter
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let overrides = Self.targets.keys.reduce(into: [Target: LogLevel]()) { partialResult, target in
|
||||||
|
// Keep the defaults here
|
||||||
|
if target == .common || target == .hyper {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
partialResult[target] = logLevel
|
||||||
|
}
|
||||||
|
|
||||||
var newTargets = Self.targets
|
var newTargets = Self.targets
|
||||||
for (target, logLevel) in overrides {
|
for (target, logLevel) in overrides {
|
||||||
newTargets.updateValue(logLevel, forKey: target)
|
newTargets.updateValue(logLevel, forKey: target)
|
||||||
@@ -93,7 +124,7 @@ struct TracingConfiguration {
|
|||||||
return "\(target.rawValue)=\(logLevel.rawValue)"
|
return "\(target.rawValue)=\(logLevel.rawValue)"
|
||||||
}
|
}
|
||||||
|
|
||||||
return components.joined(separator: ",")
|
filter = components.joined(separator: ",")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-9
@@ -19,18 +19,11 @@ import SwiftUI
|
|||||||
struct DeveloperOptionsScreen: View {
|
struct DeveloperOptionsScreen: View {
|
||||||
@ObservedObject var context: DeveloperOptionsScreenViewModel.Context
|
@ObservedObject var context: DeveloperOptionsScreenViewModel.Context
|
||||||
@State private var showConfetti = false
|
@State private var showConfetti = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
Section("Logging") {
|
Section("Logging") {
|
||||||
Picker(selection: $context.logLevel) {
|
LogLevelConfigurationView(logLevel: $context.logLevel)
|
||||||
ForEach(TracingConfiguration.LogLevel.allCases, id: \.self) { logLevel in
|
|
||||||
Text(logLevel.rawValue.capitalized)
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
Text("Log level")
|
|
||||||
Text("Requires app reboot")
|
|
||||||
}
|
|
||||||
|
|
||||||
Toggle(isOn: $context.otlpTracingEnabled) {
|
Toggle(isOn: $context.otlpTracingEnabled) {
|
||||||
Text("OTLP tracing")
|
Text("OTLP tracing")
|
||||||
@@ -130,6 +123,51 @@ struct DeveloperOptionsScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct LogLevelConfigurationView: View {
|
||||||
|
@Binding var logLevel: TracingConfiguration.LogLevel
|
||||||
|
|
||||||
|
@State private var customTracingConfiguration: String
|
||||||
|
|
||||||
|
init(logLevel: Binding<TracingConfiguration.LogLevel>) {
|
||||||
|
_logLevel = logLevel
|
||||||
|
|
||||||
|
if case .custom(let configuration) = logLevel.wrappedValue {
|
||||||
|
customTracingConfiguration = configuration
|
||||||
|
} else {
|
||||||
|
customTracingConfiguration = TracingConfiguration(logLevel: .info).filter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Picker(selection: $logLevel) {
|
||||||
|
ForEach(logLevels, id: \.self) { logLevel in
|
||||||
|
Text(logLevel.title)
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Text("Log level")
|
||||||
|
Text("Requires app reboot")
|
||||||
|
}
|
||||||
|
|
||||||
|
if case .custom = logLevel {
|
||||||
|
TextEditor(text: $customTracingConfiguration)
|
||||||
|
.textInputAutocapitalization(.never)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
.onChange(of: customTracingConfiguration) { newValue in
|
||||||
|
logLevel = .custom(newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows the picker to work with associated values
|
||||||
|
private var logLevels: [TracingConfiguration.LogLevel] {
|
||||||
|
if case let .custom(filter) = logLevel {
|
||||||
|
return [.error, .warn, .info, .debug, .trace, .custom(filter)]
|
||||||
|
} else {
|
||||||
|
return [.error, .warn, .info, .debug, .trace, .custom("")]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
struct DeveloperOptionsScreen_Previews: PreviewProvider {
|
struct DeveloperOptionsScreen_Previews: PreviewProvider {
|
||||||
|
|||||||
@@ -20,17 +20,13 @@ import XCTest
|
|||||||
|
|
||||||
class TracingConfigurationTests: XCTestCase {
|
class TracingConfigurationTests: XCTestCase {
|
||||||
func testConfiguration() {
|
func testConfiguration() {
|
||||||
let configuration = TracingConfiguration(overrides: [.common: .trace,
|
let configuration = TracingConfiguration(logLevel: .trace)
|
||||||
.matrix_sdk_base_sliding_sync: .error,
|
|
||||||
.matrix_sdk_http_client: .warn,
|
|
||||||
.matrix_sdk_crypto: .info,
|
|
||||||
.hyper: .debug])
|
|
||||||
|
|
||||||
let filterComponents = configuration.filter.components(separatedBy: ",")
|
let filterComponents = configuration.filter.components(separatedBy: ",")
|
||||||
XCTAssertEqual(filterComponents.first, "trace")
|
XCTAssertEqual(filterComponents.first, "info")
|
||||||
XCTAssertTrue(filterComponents.contains("matrix_sdk_base::sliding_sync=error"))
|
XCTAssertTrue(filterComponents.contains("matrix_sdk_base::sliding_sync=trace"))
|
||||||
XCTAssertTrue(filterComponents.contains("matrix_sdk::http_client=warn"))
|
XCTAssertTrue(filterComponents.contains("matrix_sdk::http_client=trace"))
|
||||||
XCTAssertTrue(filterComponents.contains("matrix_sdk_crypto=info"))
|
XCTAssertTrue(filterComponents.contains("matrix_sdk_crypto=trace"))
|
||||||
XCTAssertTrue(filterComponents.contains("hyper=debug"))
|
XCTAssertTrue(filterComponents.contains("hyper=warn"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user