Skip to content

Commit d88fe5a

Browse files
authored
Merge pull request #9437 from nextcloud/i2h3/feature/extended-debug-logging
Added file, function and line information to logging in debug builds.
2 parents 78b2b67 + a31b12f commit d88fe5a

File tree

5 files changed

+101
-29
lines changed

5 files changed

+101
-29
lines changed

shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Log/FileProviderLog.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,18 @@ public actor FileProviderLog: FileProviderLogging {
153153
let newFile = logsDirectory.appendingPathComponent(name, isDirectory: false)
154154

155155
if fileManager.createFile(atPath: newFile.path, contents: nil) == false {
156-
logger.error("Failed to create new log file at: \"\(newFile.path)\".")
156+
logger.error("Failed to create new log file at: \"\(newFile.path, privacy: .public)\".")
157157
return
158158
} else {
159-
logger.debug("Created new log file at: \"\(newFile.path)\".")
159+
logger.debug("Created new log file at: \"\(newFile.path, privacy: .public)\".")
160160
}
161161

162162
do {
163163
file = newFile
164164
handle = try FileHandle(forWritingTo: newFile)
165-
logger.debug("Opened new log file for writing at: \"\(newFile.path)\".")
165+
logger.debug("Opened new log file for writing at: \"\(newFile.path, privacy: .public)\".")
166166
} catch {
167-
logger.error("Failed to open new log file at \"\(newFile.path)\" for writing: \(error.localizedDescription, privacy: .public)")
167+
logger.error("Failed to open new log file at \"\(newFile.path, privacy: .public)\" for writing: \(error.localizedDescription, privacy: .public)")
168168
}
169169

170170
// Clean up old log files (older than 24 hours)
@@ -212,9 +212,9 @@ public actor FileProviderLog: FileProviderLogging {
212212
}
213213
}
214214

215-
private func writeToUnifiedLoggingSystem(level: OSLogType, message: String, details: [FileProviderLogDetailKey: (any Sendable)?]) {
215+
private func writeToUnifiedLoggingSystem(level: OSLogType, message: String, details: [FileProviderLogDetailKey: (any Sendable)?], file: StaticString, function: StaticString, line: UInt) {
216216
if details.isEmpty {
217-
logger.log(level: level, "\(message, privacy: .public)")
217+
logger.log(level: level, "\(message, privacy: .public)\n\n\(file, privacy: .public):\(line, privacy: .public) \(function, privacy: .public)")
218218
return
219219
}
220220

@@ -249,13 +249,13 @@ public actor FileProviderLog: FileProviderLogging {
249249
return "- \(key.rawValue): \(valueDescription)"
250250
}
251251

252-
logger.log(level: level, "\(message, privacy: .public)\n\n\(detailDescriptions.joined(separator: "\n"), privacy: .public)")
252+
logger.log(level: level, "\(message, privacy: .public)\n\n\(detailDescriptions.joined(separator: "\n"), privacy: .public)\n\n\(file, privacy: .public):\(line, privacy: .public) \(function, privacy: .public)")
253253
}
254254

255-
public func write(category: String, level: OSLogType, message: String, details: [FileProviderLogDetailKey: (any Sendable)?]) {
255+
public func write(category: String, level: OSLogType, message: String, details: [FileProviderLogDetailKey: (any Sendable)?], file: StaticString, function: StaticString, line: UInt) {
256256
#if DEBUG
257257

258-
writeToUnifiedLoggingSystem(level: level, message: message, details: details)
258+
writeToUnifiedLoggingSystem(level: level, message: message, details: details, file: file, function: function, line: line)
259259

260260
#else
261261

@@ -288,7 +288,7 @@ public actor FileProviderLog: FileProviderLogging {
288288

289289
let date = Date()
290290
let formattedDate = messageDateFormatter.string(from: date)
291-
let entry = FileProviderLogMessage(category: category, date: formattedDate, details: details, level: levelDescription, message: message)
291+
let entry = FileProviderLogMessage(category: category, date: formattedDate, details: details, level: levelDescription, message: message, file: file, function: function, line: line)
292292

293293
do {
294294
let object = try encoder.encode(entry)

shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Log/FileProviderLogMessage.swift

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ import Foundation
77
/// A data model for the rich JSON object to be written into the JSON lines log files.
88
///
99
public struct FileProviderLogMessage: Encodable {
10+
enum CodingKeys: CodingKey {
11+
case category
12+
case date
13+
case details
14+
case file
15+
case function
16+
case level
17+
case line
18+
case message
19+
}
20+
1021
///
1122
/// As used with `Logger` of the `os` framework.
1223
///
@@ -25,11 +36,26 @@ public struct FileProviderLogMessage: Encodable {
2536
///
2637
public let details: [String: FileProviderLogDetail?]
2738

39+
///
40+
/// The source code file which generates the log message.
41+
///
42+
public let file: String?
43+
44+
///
45+
/// The calling function generating this message.
46+
///
47+
public let function: String?
48+
2849
///
2950
/// Textual representation of the associated `OSLogType`.
3051
///
3152
public let level: String
3253

54+
///
55+
/// The line in the source code file which generates this message.
56+
///
57+
public let line: UInt?
58+
3359
///
3460
/// The actual text for the entry.
3561
///
@@ -38,7 +64,7 @@ public struct FileProviderLogMessage: Encodable {
3864
///
3965
/// Custom initializer to support arbitrary types as detail values.
4066
///
41-
init(category: String, date: String, details: [FileProviderLogDetailKey: Any?], level: String, message: String) {
67+
init(category: String, date: String, details: [FileProviderLogDetailKey: Any?], level: String, message: String, file: StaticString, function: StaticString, line: UInt) {
4268
self.category = category
4369
self.date = date
4470

@@ -51,5 +77,30 @@ public struct FileProviderLogMessage: Encodable {
5177
self.details = transformedDetails
5278
self.level = level
5379
self.message = message
80+
81+
#if DEBUG
82+
self.file = String("\(file)")
83+
self.function = String("\(function)")
84+
self.line = line
85+
#else
86+
self.file = nil
87+
self.function = nil
88+
self.line = nil
89+
#endif
90+
}
91+
92+
public func encode(to encoder: any Encoder) throws {
93+
var container = encoder.container(keyedBy: CodingKeys.self)
94+
try container.encode(category, forKey: .category)
95+
try container.encode(date, forKey: .date)
96+
try container.encode(details, forKey: .details)
97+
try container.encode(level, forKey: .level)
98+
try container.encode(message, forKey: .message)
99+
100+
#if DEBUG
101+
try container.encode(file, forKey: .file)
102+
try container.encode(function, forKey: .function)
103+
try container.encode(line, forKey: .line)
104+
#endif
54105
}
55106
}

shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Log/FileProviderLogger.swift

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,51 +37,63 @@ public struct FileProviderLogger: Sendable {
3737
/// Dispatch a task to write a message with the level `OSLogType.debug`.
3838
///
3939
/// - Parameters:
40-
/// - message: The main text message of the entry in the logs.
41-
/// - details: Additional contextual data.
40+
/// - message: A human-readable message, preferably generic and without interpolations. The `details` argument is for arguments.
41+
/// - details: Structured and contextual details about a message.
42+
/// - file: Implementations should have `#filePath` as the default value for this.
43+
/// - function: Implementations should have `#function` as the default value for this.
44+
/// - line: Implementations should have `#line` as the default value for this.
4245
///
43-
public func debug(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:]) {
46+
public func debug(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:], file: StaticString = #filePath, function: StaticString = #function, line: UInt = #line) {
4447
Task {
45-
await log.write(category: category, level: .debug, message: message, details: details)
48+
await log.write(category: category, level: .debug, message: message, details: details, file: file, function: function, line: line)
4649
}
4750
}
4851

4952
///
5053
/// Dispatch a task to write a message with the level `OSLogType.info`.
5154
///
5255
/// - Parameters:
53-
/// - message: The main text message of the entry in the logs.
54-
/// - details: Additional contextual data.
56+
/// - message: A human-readable message, preferably generic and without interpolations. The `details` argument is for arguments.
57+
/// - details: Structured and contextual details about a message.
58+
/// - file: Implementations should have `#filePath` as the default value for this.
59+
/// - function: Implementations should have `#function` as the default value for this.
60+
/// - line: Implementations should have `#line` as the default value for this.
5561
///
56-
public func info(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:]) {
62+
public func info(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:], file: StaticString = #filePath, function: StaticString = #function, line: UInt = #line) {
5763
Task {
58-
await log.write(category: category, level: .info, message: message, details: details)
64+
await log.write(category: category, level: .info, message: message, details: details, file: file, function: function, line: line)
5965
}
6066
}
6167

6268
///
6369
/// Dispatch a task to write a message with the level `OSLogType.error`.
6470
///
6571
/// - Parameters:
66-
/// - message: The main text message of the entry in the logs.
67-
/// - details: Additional contextual data.
72+
/// - message: A human-readable message, preferably generic and without interpolations. The `details` argument is for arguments.
73+
/// - details: Structured and contextual details about a message.
74+
/// - file: Implementations should have `#filePath` as the default value for this.
75+
/// - function: Implementations should have `#function` as the default value for this.
76+
/// - line: Implementations should have `#line` as the default value for this.
6877
///
69-
public func error(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:]) {
78+
public func error(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:], file: StaticString = #filePath, function: StaticString = #function, line: UInt = #line) {
7079
Task {
71-
await log.write(category: category, level: .error, message: message, details: details)
80+
await log.write(category: category, level: .error, message: message, details: details, file: file, function: function, line: line)
7281
}
7382
}
7483

7584
///
7685
/// Dispatch a task to write a message with the level `OSLogType.fault`.
7786
///
7887
/// - Parameters:
79-
/// - message: The main text message of the entry in the logs.
80-
/// - details: Additional contextual data.
88+
/// - message: A human-readable message, preferably generic and without interpolations. The `details` argument is for arguments.
89+
/// - details: Structured and contextual details about a message.
90+
/// - file: Implementations should have `#filePath` as the default value for this.
91+
/// - function: Implementations should have `#function` as the default value for this.
92+
/// - line: Implementations should have `#line` as the default value for this.
8193
///
82-
public func fault(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:]) {
94+
public func fault(_ message: String, _ details: [FileProviderLogDetailKey: (any Sendable)?] = [:], file: StaticString = #filePath, function: StaticString = #function, line: UInt = #line) {
8395
Task {
84-
await log.write(category: category, level: .fault, message: message, details: details)
96+
await log.write(category: category, level: .fault, message: message, details: details, file: file, function: function, line: line)
8597
}
8698
}
8799
}

shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Log/FileProviderLogging.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,14 @@ public protocol FileProviderLogging: Actor {
1212
///
1313
/// Usually, you do not need or want to use this but the methods provided by ``FileProviderLogger`` instead.
1414
///
15-
func write(category: String, level: OSLogType, message: String, details: [FileProviderLogDetailKey: (any Sendable)?])
15+
/// - Parameters:
16+
/// - category: The unified logging category to use. Usually, this is the logging type.
17+
/// - level: The severity of the message.
18+
/// - message: A human-readable message, preferably generic and without interpolations. The `details` argument is for arguments.
19+
/// - details: Structured and contextual details about a message.
20+
/// - file: Implementations should have `#filePath` as the default value for this.
21+
/// - function: Implementations should have `#function` as the default value for this.
22+
/// - line: Implementations should have `#line` as the default value for this.
23+
///
24+
func write(category: String, level: OSLogType, message: String, details: [FileProviderLogDetailKey: (any Sendable)?], file: StaticString, function: StaticString, line: UInt)
1625
}

shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKitMocks/FileProviderLogMock.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public actor FileProviderLogMock: FileProviderLogging {
1212
logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "FileProviderLogMock")
1313
}
1414

15-
public func write(category _: String, level _: OSLogType, message: String, details _: [FileProviderLogDetailKey: (any Sendable)?]) {
15+
public func write(category _: String, level _: OSLogType, message: String, details _: [FileProviderLogDetailKey: (any Sendable)?], file _: StaticString, function _: StaticString, line _: UInt) {
1616
logger.debug("\(message, privacy: .public)")
1717
}
1818
}

0 commit comments

Comments
 (0)