Skip to content
Snippets Groups Projects
LogMessage.swift 1.52 KiB
Newer Older
Dariusz Rybicki's avatar
Dariusz Rybicki committed
import Foundation
import Logging

public struct LogMessage: Equatable {
  public init(level: Logger.Level, text: String) {
    self.level = level
    self.text = text
  }

  public var level: Logger.Level
  public var text: String
Dariusz Rybicki's avatar
Dariusz Rybicki committed
}

extension LogMessage {
  public static func parse(_ string: String) -> LogMessage {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    let level: Logger.Level
    let text: String
    let pattern = #"^([A-Z]+)( \d{4}/\d{2}/\d{2})?( \d{1,2}:\d{2}:\d{2}\.\d+)? (.*)$"#
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    let regex = try! NSRegularExpression(pattern: pattern)
    let stringRange = NSRange(location: 0, length: string.utf16.count)
    if let match = regex.firstMatch(in: string, range: stringRange) {
      var groups: [Int: String] = [:]
      for rangeIndex in 1..<match.numberOfRanges {
        let nsRange = match.range(at: rangeIndex)
        if !NSEqualRanges(nsRange, NSMakeRange(NSNotFound, 0)) {
          let group = (string as NSString).substring(with: nsRange)
          groups[rangeIndex] = group
        }
      }
      level = .fromString(groups[1])
      text = groups[4] ?? string
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    } else {
      level = .notice
      text = string
    }
    return LogMessage(level: level, text: text)
  }
}

private extension Logger.Level {
  static func fromString(_ string: String?) -> Logger.Level {
    switch string {
    case "TRACE": return .trace
    case "DEBUG": return .debug
    case "INFO": return .info
    case "WARN": return .warning
    case "ERROR": return .error
    case "CRITICAL": return .critical
    case "FATAL": return .critical
    default: return .notice
    }
  }
}