Skip to content

Commit

Permalink
Add BBLogFormat to customize text output (#43)
Browse files Browse the repository at this point in the history
* Add console output string formatter property

* Added log level icon

* Fixed unit tests

* Replaced var with let

* Removed stringFormatter from event class, passed it to loggers through init

* Renaming BBConsoleStringFormatter to BBLogFormat

* Removed unused consoleFormatter property from BB

* Revert "Fixed unit tests", renaming OSlogger init arg

This reverts commit 095c51e.

* Maked default BBLogFormat unmutable

* BBlogFormat removed from namespace BlackBox

* Added tests checked applying BBlogFormat in OSLogger

* Added BBLogFormat.swift to carthage source files

* Added tvOS and watchOS to @available attribute in test

---------

Co-authored-by: Alexander Fomin <A.Fomin@buzzolls.ruA.Fomin@buzzolls.ruA.Fomin@buzzolls.ru>
Co-authored-by: Alexander Fomin <a.fomin@buzzolls.ru>
  • Loading branch information
3 people authored Dec 21, 2023
1 parent 0cf140c commit 69fafe2
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 16 deletions.
10 changes: 10 additions & 0 deletions BlackBox-Carthage/BlackBox-Carthage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
15C3EC6F2B3028A200A79B8B /* BBLogFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C3EC6E2B3028A200A79B8B /* BBLogFormat.swift */; };
15C3EC702B3028A200A79B8B /* BBLogFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C3EC6E2B3028A200A79B8B /* BBLogFormat.swift */; };
15C3EC712B3028A200A79B8B /* BBLogFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C3EC6E2B3028A200A79B8B /* BBLogFormat.swift */; };
15C3EC722B3028A200A79B8B /* BBLogFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C3EC6E2B3028A200A79B8B /* BBLogFormat.swift */; };
1E4AC26B27A7F221009F0981 /* BBLogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4AC25D27A7F221009F0981 /* BBLogLevel.swift */; };
1E4AC26C27A7F221009F0981 /* FSLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4AC25F27A7F221009F0981 /* FSLogger.swift */; };
1E4AC26D27A7F221009F0981 /* BBLoggerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4AC26027A7F221009F0981 /* BBLoggerProtocol.swift */; };
Expand Down Expand Up @@ -46,6 +50,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
15C3EC6E2B3028A200A79B8B /* BBLogFormat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BBLogFormat.swift; sourceTree = "<group>"; };
1E4AC25D27A7F221009F0981 /* BBLogLevel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BBLogLevel.swift; sourceTree = "<group>"; };
1E4AC25F27A7F221009F0981 /* FSLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FSLogger.swift; sourceTree = "<group>"; };
1E4AC26027A7F221009F0981 /* BBLoggerProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BBLoggerProtocol.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -105,6 +110,7 @@
1E4AC25C27A7F221009F0981 /* BlackBox */ = {
isa = PBXGroup;
children = (
15C3EC6E2B3028A200A79B8B /* BBLogFormat.swift */,
1E4AC25D27A7F221009F0981 /* BBLogLevel.swift */,
1E4AC28F27A7FE52009F0981 /* BlackBox.h */,
1E4AC26027A7F221009F0981 /* BBLoggerProtocol.swift */,
Expand Down Expand Up @@ -338,6 +344,7 @@
1E4AC27327A7F221009F0981 /* BBHelpers.swift in Sources */,
1E4AC26D27A7F221009F0981 /* BBLoggerProtocol.swift in Sources */,
1E4AC27127A7F221009F0981 /* BlackBoxEvents.swift in Sources */,
15C3EC6F2B3028A200A79B8B /* BBLogFormat.swift in Sources */,
1E4AC26F27A7F221009F0981 /* OSLogger.swift in Sources */,
1E4AC27427A7F221009F0981 /* BlackBox.swift in Sources */,
1E4AC26E27A7F221009F0981 /* OSSignpostLogger.swift in Sources */,
Expand All @@ -353,6 +360,7 @@
9C0C4DE528FDC6B40062AF73 /* BBHelpers.swift in Sources */,
9C0C4DE628FDC6B40062AF73 /* BBLoggerProtocol.swift in Sources */,
9C0C4DE728FDC6B40062AF73 /* BlackBoxEvents.swift in Sources */,
15C3EC702B3028A200A79B8B /* BBLogFormat.swift in Sources */,
9C0C4DE828FDC6B40062AF73 /* OSLogger.swift in Sources */,
9C0C4DE928FDC6B40062AF73 /* BlackBox.swift in Sources */,
9C0C4DEA28FDC6B40062AF73 /* OSSignpostLogger.swift in Sources */,
Expand All @@ -368,6 +376,7 @@
9C0C4DF728FE43380062AF73 /* BBHelpers.swift in Sources */,
9C0C4DF828FE43380062AF73 /* BBLoggerProtocol.swift in Sources */,
9C0C4DF928FE43380062AF73 /* BlackBoxEvents.swift in Sources */,
15C3EC712B3028A200A79B8B /* BBLogFormat.swift in Sources */,
9C0C4DFA28FE43380062AF73 /* OSLogger.swift in Sources */,
9C0C4DFB28FE43380062AF73 /* BlackBox.swift in Sources */,
9C0C4DFC28FE43380062AF73 /* OSSignpostLogger.swift in Sources */,
Expand All @@ -383,6 +392,7 @@
9C0C4E0928FE436E0062AF73 /* BBHelpers.swift in Sources */,
9C0C4E0A28FE436E0062AF73 /* BBLoggerProtocol.swift in Sources */,
9C0C4E0B28FE436E0062AF73 /* BlackBoxEvents.swift in Sources */,
15C3EC722B3028A200A79B8B /* BBLogFormat.swift in Sources */,
9C0C4E0C28FE436E0062AF73 /* OSLogger.swift in Sources */,
9C0C4E0D28FE436E0062AF73 /* BlackBox.swift in Sources */,
9C0C4E0E28FE436E0062AF73 /* OSSignpostLogger.swift in Sources */,
Expand Down
26 changes: 26 additions & 0 deletions Sources/BlackBox/BBLogFormat.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

public struct BBLogFormat {
let userInfoFormatOptions: JSONSerialization.WritingOptions
let sourceSectionInline: Bool
let showLevelIcon: Bool

/// Creates `BBLogFormat` instance
/// - Parameters:
/// - userInfoFormatOptions:Options for output JSON data.
/// - sourceSectionInline: Print `Source` section in console inline
/// - showLevelIcon: Boolean value defines showing log level icon in console
public init(
userInfoFormatOptions: JSONSerialization.WritingOptions,
sourceSectionInline: Bool,
showLevelIcon: Bool
) {
self.userInfoFormatOptions = userInfoFormatOptions
self.sourceSectionInline = sourceSectionInline
self.showLevelIcon = showLevelIcon
}

public static let `default` = BBLogFormat(userInfoFormatOptions: .prettyPrinted,
sourceSectionInline: false,
showLevelIcon: false)
}
2 changes: 1 addition & 1 deletion Sources/BlackBox/BlackBox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ extension BlackBox {

public static var defaultLoggers: [BBLoggerProtocol] {
[
OSLogger(levels: .allCases),
OSLogger(levels: .allCases, logFormat: .default),
OSSignpostLogger(levels: .allCases)
]
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/BlackBox/BlackBoxEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extension BlackBox {
public let parentEvent: GenericEvent?
/// From where log originated
public let source: Source

public init(
id: UUID = .init(),
timestamp: Date = .init(),
Expand Down
4 changes: 2 additions & 2 deletions Sources/BlackBox/Helpers/BBHelpers.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Foundation

extension Dictionary where Key == String, Value == Any {
var bbLogDescription: String {
func bbLogDescription(with options: JSONSerialization.WritingOptions?) -> String {
guard JSONSerialization.isValidJSONObject(self),
let jsonData = try? JSONSerialization.data(withJSONObject: self,
options: .prettyPrinted),
options: options ?? []),
let jsonString = String(data: jsonData, encoding: .utf8)
else { return String(describing: self) }

Expand Down
7 changes: 5 additions & 2 deletions Sources/BlackBox/Loggers/FSLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public class FSLogger: BBLoggerProtocol {
private let fullpath: URL
private let levels: [BBLogLevel]
private let queue: DispatchQueue
private let logFormat: BBLogFormat

/// Creates FS logger
/// - Parameters:
Expand All @@ -17,11 +18,13 @@ public class FSLogger: BBLoggerProtocol {
path: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!,
name: String = "BlackBox_FSLogger",
levels: [BBLogLevel],
queue: DispatchQueue = DispatchQueue(label: String(describing: FSLogger.self))
queue: DispatchQueue = DispatchQueue(label: String(describing: FSLogger.self)),
logFormat: BBLogFormat
) {
self.fullpath = path.appendingPathComponent(name)
self.levels = levels
self.queue = queue
self.logFormat = logFormat
}

public func log(_ event: BlackBox.GenericEvent) {
Expand Down Expand Up @@ -51,7 +54,7 @@ extension FSLogger {
private func fsLog(_ event: BlackBox.GenericEvent) {
guard levels.contains(event.level) else { return }

let userInfo = event.userInfo?.bbLogDescription ?? "nil"
let userInfo = event.userInfo?.bbLogDescription(with: logFormat.userInfoFormatOptions) ?? "nil"

let title = event.level.icon + " " + String(describing: Date())
let subtitle = event.source.filename + ", " + event.source.function.description
Expand Down
20 changes: 12 additions & 8 deletions Sources/BlackBox/Loggers/OSLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import os
/// Redirects logs to Console.app and to Xcode console
public class OSLogger: BBLoggerProtocol {
let levels: [BBLogLevel]
let logFormat: BBLogFormat

public init(
levels: [BBLogLevel]
levels: [BBLogLevel],
logFormat: BBLogFormat
){
self.levels = levels
self.logFormat = logFormat
}

public func log(_ event: BlackBox.GenericEvent) {
Expand All @@ -30,7 +33,7 @@ public class OSLogger: BBLoggerProtocol {
private func osLog(event: BlackBox.GenericEvent) {
guard levels.contains(event.level) else { return }

let data = LogData(from: event)
let data = LogData(from: event, logFormat: logFormat)

osLog(data)
}
Expand Down Expand Up @@ -68,40 +71,41 @@ extension OSLogger {
self.message = message
}

init(from event: BlackBox.GenericEvent) {
init(from event: BlackBox.GenericEvent, logFormat: BBLogFormat) {
let subsystem = event.source.module
let category = event.category ?? ""

self.init(
logType: OSLogType(event.level),
subsystem: subsystem,
category: category,
message: Self.message(from: event)
message: Self.message(from: event, logFormat: logFormat)
)
}

private static func message(from event: BlackBox.GenericEvent) -> String {
private static func message(from event: BlackBox.GenericEvent, logFormat: BBLogFormat) -> String {
func source(from event: BlackBox.GenericEvent) -> String {
let fileWithLine = [event.source.filename, String(event.source.line)].joined(separator: ":")

return [
"[Source]",
fileWithLine,
event.source.function.description
].joined(separator: "\n")
].joined(separator: logFormat.sourceSectionInline ? " " : "\n")
}

func userInfo(from event: BlackBox.GenericEvent) -> String? {
guard let userInfo = event.userInfo else { return nil }

return [
"[User Info]",
userInfo.bbLogDescription
userInfo.bbLogDescription(with: logFormat.userInfoFormatOptions)
].joined(separator: "\n")
}

// newline at the beginning increments readability in Xcode's console while not decrementing reading in Console.app
let message = "\n" + event.formattedMessage
let prefixString = logFormat.showLevelIcon ? "\n\(event.level.icon) " : "\n"
let message = prefixString + event.formattedMessage

return [
message,
Expand Down
68 changes: 66 additions & 2 deletions Tests/BlackBoxTests/OSLoggerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class OSLoggerTests: BlackBoxTestCase {
try super.tearDownWithError()
}

private func createOSLogger(levels: [BBLogLevel]) {
osLogger = .init(levels: levels)
private func createOSLogger(levels: [BBLogLevel], logFormat: BBLogFormat = .default) {
osLogger = .init(levels: levels, logFormat: logFormat)
BlackBox.instance = .init(loggers: [osLogger])

logger = osLogger
Expand Down Expand Up @@ -219,3 +219,67 @@ class OSLoggerMock: OSLogger, TestableLoggerProtocol {
super.osLog(data)
}
}


// MARK: - BBLogFormat
extension OSLoggerTests {
func test_whenLogFormatApplied_showingLevelIcon() {
let customLogFormat = BBLogFormat(userInfoFormatOptions: [], sourceSectionInline: false, showLevelIcon: true)
createOSLogger(levels: .allCases, logFormat: customLogFormat)

waitForLog { BlackBox.log("Hello there") }

let expectedResult = """
🛠 Hello there
[Source]
OSLoggerTests:230
test_whenLogFormatApplied_showingLevelIcon()
"""
XCTAssertEqual(osLogger.data?.message, expectedResult)

}

func test_whenLogFormatApplied_outputSourceSectionInline() {
let customLogFormat = BBLogFormat(userInfoFormatOptions: [], sourceSectionInline: true, showLevelIcon: false)
createOSLogger(levels: .allCases, logFormat: customLogFormat)

waitForLog { BlackBox.log("Hello there") }

let expectedResult = """
Hello there
[Source] OSLoggerTests:248 test_whenLogFormatApplied_outputSourceSectionInline()
"""
XCTAssertEqual(osLogger.data?.message, expectedResult)

}

@available(iOS 13.0, tvOS 13.0, watchOS 13.0, *)
func test_whenLogFormatApplied_userInfoFormatted() {
let customLogFormat = BBLogFormat(userInfoFormatOptions: [.prettyPrinted, .withoutEscapingSlashes],
sourceSectionInline: false,
showLevelIcon: false)
createOSLogger(levels: .allCases, logFormat: customLogFormat)

waitForLog { BlackBox.log("Hello there", userInfo: ["path": "/api/v1/getData"]) }

let expectedResult = """
Hello there
[Source]
OSLoggerTests:267
test_whenLogFormatApplied_userInfoFormatted()
[User Info]
{
\"path\" : \"/api/v1/getData\"
}
"""
XCTAssertEqual(osLogger.data?.message, expectedResult)

}
}

0 comments on commit 69fafe2

Please sign in to comment.