Skip to content

Instantly share code, notes, and snippets.

@wata
Last active June 13, 2024 02:00
Show Gist options
  • Save wata/00b243a57590e95e81f7d21c0004a9c1 to your computer and use it in GitHub Desktop.
Save wata/00b243a57590e95e81f7d21c0004a9c1 to your computer and use it in GitHub Desktop.
os_log と Crashlytics を使ったロガークラス
import Foundation
import os.log
import FirebaseCrashlytics
extension OSLogType: CustomStringConvertible {
public var description: String {
switch self {
case OSLogType.debug: return "🔹🔹🔹"
case OSLogType.info: return "ℹ️ℹ️ℹ️"
case OSLogType.error: return "‼️‼️‼️"
case OSLogType.fault: return "😱😱😱"
default: return "DEFAULT"
}
}
}
// https://github.com/mono0926/mono-kit/blob/master/Lib/Logger.swift
// https://gist.github.com/yoichitgy/8806a7da3a52d8e6f5207e6a1a11b5a8
// https://developer.apple.com/reference/os/logging
struct Logger {
private static let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "default")
fileprivate init() {}
/// Log something at the Debug log level for debug info.
/// ✅ Console
/// ❌ CLSLogv
/// ❌ recordError
/// ❌ assertionFailure
func debug(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible = #function,
fileName: CustomStringConvertible = #file,
lineNumber: Int = #line) {
doLog(message(), logType: .debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
}
/// Log something at the Info log level for trace info.
/// ✅ Console
/// ✅ CLSLogv
/// ❌ recordError
/// ❌ assertionFailure
func info(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible = #function,
fileName: CustomStringConvertible = #file,
lineNumber: Int = #line) {
doLog(message(), logType: .info, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
doCLSLog(message(), logType: .info, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
}
/// Log something at the Error log level for handleable error.
/// ✅ Console
/// ✅ CLSLogv
/// ❌ recordError
/// ❌ assertionFailure
func error(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible = #function,
fileName: CustomStringConvertible = #file,
lineNumber: Int = #line) {
doLog(message(), logType: .error, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
doCLSLog(message(), logType: .info, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
}
/// Log something at the Fault log level for unexpected error.
/// ✅ Console
/// ❌ CLSLogv
/// ✅ recordError
/// ✅ assertionFailure
func fault(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible = #function,
fileName: CustomStringConvertible = #file,
lineNumber: Int = #line) {
doLog(message(), logType: .fault, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
doCLSRecordError(message(), functionName: functionName, fileName: fileName, lineNumber: lineNumber)
doAssertionFailure(message())
}
func `default`(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible = #function,
fileName: CustomStringConvertible = #file,
lineNumber: Int = #line) {
doLog(message(), logType: .default, functionName: functionName, fileName: fileName, lineNumber: lineNumber)
}
fileprivate func doLog(_ message: @autoclosure () -> Any?,
logType: OSLogType,
functionName: CustomStringConvertible,
fileName: CustomStringConvertible,
lineNumber: Int) {
let staticSelf = type(of: self)
let log = staticSelf.log
guard log.isEnabled(type: logType) else { return }
guard let output = staticSelf.buildOutput(message(),
logType: logType,
functionName: functionName,
fileName: fileName,
lineNumber: lineNumber) else { return }
os_log("%@", log: log, type: logType, output)
}
fileprivate func doCLSLog(_ message: @autoclosure () -> Any?,
logType: OSLogType,
functionName: CustomStringConvertible,
fileName: CustomStringConvertible,
lineNumber: Int) {
let staticSelf = type(of: self)
guard let output = staticSelf.buildOutput(message(),
logType: logType,
functionName: functionName,
fileName: fileName,
lineNumber: lineNumber) else { return }
Crashlytics.crashlytics().log(output)
}
fileprivate func doCLSRecordError(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible,
fileName: CustomStringConvertible,
lineNumber: Int) {
let staticSelf = type(of: self)
guard let error = staticSelf.buildError(message(),
functionName: functionName,
fileName: fileName,
lineNumber: lineNumber) else { return }
Crashlytics.crashlytics().record(error: error)
}
fileprivate func doAssertionFailure(_ message: @autoclosure () -> Any?) {
guard let message = message() else { return }
assertionFailure(String(describing: message))
}
static func buildOutput(_ message: @autoclosure () -> Any?,
logType: OSLogType,
functionName: CustomStringConvertible,
fileName: CustomStringConvertible,
lineNumber: Int) -> String? {
guard let message = message() else { return nil }
return "[\(logType)] [\(threadName)] [\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber)] \(functionName) > \(message)"
}
static func buildError(_ message: @autoclosure () -> Any?,
functionName: CustomStringConvertible,
fileName: CustomStringConvertible,
lineNumber: Int) -> Error? {
guard let message = message() else { return nil }
return NSError(domain: "\(fileName):\(functionName)", code: lineNumber, userInfo: ["message": message])
}
private static var threadName: String {
if Thread.isMainThread {
return "main"
}
if let threadName = Thread.current.name, !threadName.isEmpty {
return threadName
}
if let queueName = DispatchQueue.currentQueueLabel, !queueName.isEmpty {
return queueName
}
return String(format: "[%p] ", Thread.current)
}
}
extension DispatchQueue {
static var currentQueueLabel: String? {
return String(validatingUTF8: __dispatch_queue_get_label(nil))
}
}
let log = Logger()
@wata
Copy link
Author

wata commented Apr 23, 2018

Level Console CLSLogv (Crashlytics) recordError (Crashlytics) assertionFailure Use
.debug o x x x Debug Info
.info o o x x Trace Info
.error o o x x Handleable Error
.fault o x o o Unexpected Error

@wata
Copy link
Author

wata commented May 6, 2020

updated: 2020-05-07
Fabric SDK => Firebase Crashlytics SDK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment