123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- //
- // SwiftyBeaver.swift
- // SwiftyBeaver
- //
- // Created by Sebastian Kreutzberger (Twitter @skreutzb) on 28.11.15.
- // Copyright © 2015 Sebastian Kreutzberger
- // Some rights reserved: http://opensource.org/licenses/MIT
- //
- import Foundation
- open class SwiftyBeaver {
- /// version string of framework
- public static let version = "1.7.0" // UPDATE ON RELEASE!
- /// build number of framework
- public static let build = 1700 // version 1.6.2 -> 1620, UPDATE ON RELEASE!
- public enum Level: Int {
- case verbose = 0
- case debug = 1
- case info = 2
- case warning = 3
- case error = 4
- }
- // a set of active destinations
- public private(set) static var destinations = Set<BaseDestination>()
- // MARK: Destination Handling
- /// returns boolean about success
- @discardableResult
- open class func addDestination(_ destination: BaseDestination) -> Bool {
- if destinations.contains(destination) {
- return false
- }
- destinations.insert(destination)
- return true
- }
- /// returns boolean about success
- @discardableResult
- open class func removeDestination(_ destination: BaseDestination) -> Bool {
- if destinations.contains(destination) == false {
- return false
- }
- destinations.remove(destination)
- return true
- }
- /// if you need to start fresh
- open class func removeAllDestinations() {
- destinations.removeAll()
- }
- /// returns the amount of destinations
- open class func countDestinations() -> Int {
- return destinations.count
- }
- /// returns the current thread name
- class func threadName() -> String {
- #if os(Linux)
- // on 9/30/2016 not yet implemented in server-side Swift:
- // > import Foundation
- // > Thread.isMainThread
- return ""
- #else
- if Thread.isMainThread {
- return ""
- } else {
- let threadName = Thread.current.name
- if let threadName = threadName, !threadName.isEmpty {
- return threadName
- } else {
- return String(format: "%p", Thread.current)
- }
- }
- #endif
- }
- // MARK: Levels
- /// log something generally unimportant (lowest priority)
- open class func verbose(_ message: @autoclosure () -> Any, _
- file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
- #if swift(>=5)
- custom(level: .verbose, message: message(), file: file, function: function, line: line, context: context)
- #else
- custom(level: .verbose, message: message, file: file, function: function, line: line, context: context)
- #endif
- }
- /// log something which help during debugging (low priority)
- open class func debug(_ message: @autoclosure () -> Any, _
- file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
- #if swift(>=5)
- custom(level: .debug, message: message(), file: file, function: function, line: line, context: context)
- #else
- custom(level: .debug, message: message, file: file, function: function, line: line, context: context)
- #endif
- }
- /// log something which you are really interested but which is not an issue or error (normal priority)
- open class func info(_ message: @autoclosure () -> Any, _
- file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
- #if swift(>=5)
- custom(level: .info, message: message(), file: file, function: function, line: line, context: context)
- #else
- custom(level: .info, message: message, file: file, function: function, line: line, context: context)
- #endif
- }
- /// log something which may cause big trouble soon (high priority)
- open class func warning(_ message: @autoclosure () -> Any, _
- file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
- #if swift(>=5)
- custom(level: .warning, message: message(), file: file, function: function, line: line, context: context)
- #else
- custom(level: .warning, message: message, file: file, function: function, line: line, context: context)
- #endif
- }
- /// log something which will keep you awake at night (highest priority)
- open class func error(_ message: @autoclosure () -> Any, _
- file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
- #if swift(>=5)
- custom(level: .error, message: message(), file: file, function: function, line: line, context: context)
- #else
- custom(level: .error, message: message, file: file, function: function, line: line, context: context)
- #endif
- }
- /// custom logging to manually adjust values, should just be used by other frameworks
- public class func custom(level: SwiftyBeaver.Level, message: @autoclosure () -> Any,
- file: String = #file, function: String = #function, line: Int = #line, context: Any? = nil) {
- #if swift(>=5)
- dispatch_send(level: level, message: message(), thread: threadName(),
- file: file, function: function, line: line, context: context)
- #else
- dispatch_send(level: level, message: message, thread: threadName(),
- file: file, function: function, line: line, context: context)
- #endif
- }
- /// internal helper which dispatches send to dedicated queue if minLevel is ok
- class func dispatch_send(level: SwiftyBeaver.Level, message: @autoclosure () -> Any,
- thread: String, file: String, function: String, line: Int, context: Any?) {
- var resolvedMessage: String?
- for dest in destinations {
- guard let queue = dest.queue else {
- continue
- }
- resolvedMessage = resolvedMessage == nil && dest.hasMessageFilters() ? "\(message())" : resolvedMessage
- if dest.shouldLevelBeLogged(level, path: file, function: function, message: resolvedMessage) {
- // try to convert msg object to String and put it on queue
- let msgStr = resolvedMessage == nil ? "\(message())" : resolvedMessage!
- let f = stripParams(function: function)
- if dest.asynchronously {
- queue.async {
- _ = dest.send(level, msg: msgStr, thread: thread, file: file, function: f, line: line, context: context)
- }
- } else {
- queue.sync {
- _ = dest.send(level, msg: msgStr, thread: thread, file: file, function: f, line: line, context: context)
- }
- }
- }
- }
- }
- /**
- DEPRECATED & NEEDS COMPLETE REWRITE DUE TO SWIFT 3 AND GENERAL INCORRECT LOGIC
- Flush all destinations to make sure all logging messages have been written out
- Returns after all messages flushed or timeout seconds
- - returns: true if all messages flushed, false if timeout or error occurred
- */
- public class func flush(secondTimeout: Int64) -> Bool {
- /*
- guard let grp = dispatch_group_create() else { return false }
- for dest in destinations {
- if let queue = dest.queue {
- dispatch_group_enter(grp)
- queue.asynchronously(execute: {
- dest.flush()
- grp.leave()
- })
- }
- }
- let waitUntil = DispatchTime.now(dispatch_time_t(DISPATCH_TIME_NOW), secondTimeout * 1000000000)
- return dispatch_group_wait(grp, waitUntil) == 0
- */
- return true
- }
- /// removes the parameters from a function because it looks weird with a single param
- class func stripParams(function: String) -> String {
- var f = function
- if let indexOfBrace = f.find("(") {
- #if swift(>=4.0)
- f = String(f[..<indexOfBrace])
- #else
- f = f.substring(to: indexOfBrace)
- #endif
- }
- f += "()"
- return f
- }
- }
|