├── .gitignore ├── .jazzy.yaml ├── .travis.yml ├── Package.resolved ├── Package.swift ├── README.md ├── Sources └── LoggingFormatAndPipe │ ├── BasicFormatter.swift │ ├── Formatter.swift │ ├── Handler.swift │ ├── LoggerTextOutputStreamPipe.swift │ └── Pipe.swift ├── Tests ├── LinuxMain.swift └── LoggingFormatAndPipeTests │ ├── FormatterTests.swift │ ├── HandlerTests.swift │ ├── LoggerTextOutputStreamPipeTests.swift │ ├── TestLogging.swift │ └── XCTestManifests.swift ├── docs ├── Enums.html ├── Enums │ └── LogComponent.html ├── Protocols.html ├── Protocols │ ├── Formatter.html │ └── Pipe.html ├── Structs.html ├── Structs │ ├── BasicFormatter.html │ ├── Handler.html │ ├── LoggerTextOutputStreamPipe.html │ └── StdioOutputStream.html ├── badge.svg ├── css │ ├── highlight.css │ └── jazzy.css ├── docsets │ ├── LoggingFormatAndPipe.docset │ │ └── Contents │ │ │ ├── Info.plist │ │ │ └── Resources │ │ │ ├── Documents │ │ │ ├── Enums.html │ │ │ ├── Enums │ │ │ │ └── LogComponent.html │ │ │ ├── Protocols.html │ │ │ ├── Protocols │ │ │ │ ├── Formatter.html │ │ │ │ └── Pipe.html │ │ │ ├── Structs.html │ │ │ ├── Structs │ │ │ │ ├── BasicFormatter.html │ │ │ │ ├── Handler.html │ │ │ │ ├── LoggerTextOutputStreamPipe.html │ │ │ │ └── StdioOutputStream.html │ │ │ ├── css │ │ │ │ ├── highlight.css │ │ │ │ └── jazzy.css │ │ │ ├── img │ │ │ │ ├── carat.png │ │ │ │ ├── dash.png │ │ │ │ ├── gh.png │ │ │ │ └── spinner.gif │ │ │ ├── index.html │ │ │ ├── js │ │ │ │ ├── jazzy.js │ │ │ │ ├── jazzy.search.js │ │ │ │ ├── jquery.min.js │ │ │ │ ├── lunr.min.js │ │ │ │ └── typeahead.jquery.js │ │ │ └── search.json │ │ │ └── docSet.dsidx │ └── LoggingFormatAndPipe.tgz ├── img │ ├── carat.png │ ├── dash.png │ ├── gh.png │ └── spinner.gif ├── index.html ├── js │ ├── jazzy.js │ ├── jazzy.search.js │ ├── jquery.min.js │ ├── lunr.min.js │ └── typeahead.jquery.js ├── search.json └── undocumented.json └── updateDocs.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata 5 | *.xcodeproj 6 | -------------------------------------------------------------------------------- /.jazzy.yaml: -------------------------------------------------------------------------------- 1 | author: "Adorkable" 2 | author_url: "https://adorkable.io" 3 | github_url: "https://github.com/Adorkable/swift-log-format-and-pipe" 4 | github_file_prefix: "https://github.com/Adorkable/swift-log-format-and-pipe/tree/0.1.2" 5 | readme: "README.md" 6 | copyright: "CC 2019 Adorkable" 7 | theme: fullwidth 8 | module: LoggingFormatAndPipe 9 | use_safe_filenames: true 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - osx 3 | language: generic 4 | sudo: required 5 | dist: trusty 6 | osx_image: xcode10.2 7 | script: 8 | - swift build 9 | - swift test 10 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "swift-log", 6 | "repositoryURL": "https://github.com/apple/swift-log.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "f4240bf022a69815241a883c03645444b58ac553", 10 | "version": "1.1.0" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "swift-log-format-and-pipe", 6 | products: [ 7 | .library( 8 | name: "LoggingFormatAndPipe", 9 | targets: ["LoggingFormatAndPipe"]), 10 | ], 11 | dependencies: [ 12 | .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"), 13 | ], 14 | targets: [ 15 | .target( 16 | name: "LoggingFormatAndPipe", 17 | dependencies: ["Logging"]), 18 | .testTarget( 19 | name: "LoggingFormatAndPipeTests", 20 | dependencies: ["LoggingFormatAndPipe", "Logging"]), 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LoggingFormatAndPipe 2 | **LoggingFormatAndPipe** provides a [Swift Logging API](https://github.com/apple/swift-log) Handler which allows you to customized both your log messages' formats as well as their destinations. 3 | 4 | If you don't like the default log format change it to one you would like. If you want one destination to be formatted differently than your other destination you can with ease. Or send the same format to multiple destinations! 5 | 6 |

7 | Installation | Getting Started | Documentation 8 |

9 | 10 | ## Installation 11 | 12 | ### SwiftPM 13 | 14 | To use the **LoggingFormatAndPipe** library in your project add the following in your `Package.swift`: 15 | 16 | ```swift 17 | .package(url: "https://github.com/adorkable/swift-log-format-and-pipe.git", .from("0.1.2")), 18 | ``` 19 | 20 | 21 | ## Getting Started 22 | 23 | `LoggingFormatAndPipe.Handler` expects both a `Formatter` and a `Pipe` 24 | 25 | ```swift 26 | let logger = Logger(label: "example") { _ in 27 | return LoggingFormatAndPipe.Handler( 28 | formatter: ..., 29 | pipe: ... 30 | ) 31 | } 32 | ``` 33 | 34 | *Example:* 35 | 36 | ```swift 37 | let logger = Logger(label: "example") { _ in 38 | return LoggingFormatAndPipe.Handler( 39 | formatter: BasicFormatter.adorkable, 40 | pipe: LoggerTextOutputStreamPipe.standardOutput 41 | ) 42 | } 43 | ``` 44 | 45 | ## Formatting 46 | There are a number of ways of customizing the format but are generally composed of a combination of `LogComponents`: 47 | 48 | * `.timestamp` - Timestamp of log 49 | * `.level` - Log level 50 | * `.message` - The actual message 51 | * `.metadata` - Log metadata 52 | * `.file` - The log's originating file 53 | * `.line` - The log's originating line number in the file 54 | * `.function` - The log's originating function 55 | * `.text(String)` - Static text 56 | * `.group([LogComponents])` - Formatters may separate specified `LogComponents` in various ways as per their format, `.group` tells the Formatter to combine the `LogComponents` without using its separation 57 | 58 | ### BasicFormatter 59 | `BasicFormatter` allows you to specify a sequence of `LogComponents` and a separator string and automatically processes them into a single line for each new log message. 60 | 61 | It includes already setup static instances: 62 | 63 | * `.apple` - [apple/swift-log](https://github.com/apple/swift-log) format 64 | 65 | `{timestamp} {level}: {message}` 66 | 67 | *Example:* 68 | 69 | `2019-07-30T13:49:07-0400 error: Test error message` 70 | * `.adorkable` - Adorkable's standard format 😘 71 | 72 | `{timestamp} ▶ {level} ▶ {file}:{line} ▶ {function} ▶ {message} ▶ {metadata}` 73 | 74 | *Example:* 75 | 76 | `2019-07-30T13:49:07-0400 ▶ error ▶ /asdf/swift-log-format-and-pipe/Tests/LoggingFormatAndPipeTests/FormatterTests.swift:25 ▶ testFormatter(_:) ▶ Test error message` 77 | 78 | #### Customizing a BasicFormatter 79 | If none of these work you can customize your own instance! 80 | 81 | Suppose you want a special short log format with a timestamp, the level, the file it originated in, and the message itself: 82 | 83 | ```swift 84 | let myFormat = BasicFormatter( 85 | [ 86 | .timestamp, 87 | .level, 88 | .file, 89 | .message 90 | ] 91 | ) 92 | ``` 93 | 94 | To change the separator from a single space specify the separator parameter: 95 | 96 | ```swift 97 | let myFormat = BasicFormatter( 98 | ..., 99 | separator: "|" 100 | ) 101 | ``` 102 | 103 | Note that `BasicFormatter` will not add an empty string and separator for a `nil` metadata. 104 | 105 | To change the timestamp from the default: 106 | 107 | ```swift 108 | let myDateFormat = DateFormatter() 109 | myDateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" 110 | let myFormat = BasicFormatter( 111 | ..., 112 | timestampFormatter: myDateFormat 113 | ) 114 | ``` 115 | 116 | ### Implementing Formatter 117 | You can also create your own `Formatter` conforming object by implementing: 118 | 119 | * `var timestampFormatter: DateFormatter { get }` 120 | * `func processLog(level: Logger.Level, 121 | message: Logger.Message, 122 | prettyMetadata: String?, 123 | file: String, function: String, line: UInt) -> String` 124 | 125 | More formatters to come! 126 | 127 | ## Piping 128 | Pipes specify where your formatted log lines end up going to. Included already are: 129 | 130 | * `LoggerTextOutputStreamPipe.standardOutput` - log lines to `stdout` 131 | * `LoggerTextOutputStreamPipe.standardError` - log lines to `stderr` 132 | 133 | More pipes to come! 134 | 135 | ### Implementing Pipe 136 | You can also create your own `Pipe` conforming object by implementing: 137 | 138 | * `func handle(_ formattedLogLine: String)` 139 | 140 | Easy! 141 | 142 | Now you've got your use-case formatted log lines traveling this way and then, what a charm 🖤 143 | 144 | ## API Documentation 145 | For more insight into the library API documentation is found in the repo [here](http://adorkable.github.io/swift-log-format-and-pipe/) 146 | -------------------------------------------------------------------------------- /Sources/LoggingFormatAndPipe/BasicFormatter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicFormatter.swift 3 | // LoggingFormatAndPipe 4 | // 5 | // Created by Ian Grossberg on 7/26/19. 6 | // 7 | 8 | import Logging 9 | import Foundation 10 | 11 | /// Your basic, customizable log formatter 12 | /// `BasicFormatter` does not need any setup and will automatically include all log components 13 | /// It can also be given a linear sequence of log components and it will build formatted logs in that order 14 | public struct BasicFormatter: Formatter { 15 | /// Log format sequential specification 16 | public let format: [LogComponent] 17 | /// Log component separator 18 | public let separator: String? 19 | /// Log timestamp component formatter 20 | public let timestampFormatter: DateFormatter 21 | 22 | /// Default timestamp component formatter 23 | static public var timestampFormatter: DateFormatter { 24 | let result = DateFormatter() 25 | result.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" 26 | return result 27 | } 28 | 29 | /// Default init 30 | /// - Parameters: 31 | /// - _: Log format specification(default: `LogComponent.allNonmetaComponents`) 32 | /// - separator: Log component separator (default: " ") 33 | /// - timestampFormatter: Log timestamp component formatter (default: `BasicFormatter.timestampFormatter`) 34 | public init(_ format: [LogComponent] = LogComponent.allNonmetaComponents, separator: String = " ", timestampFormatter: DateFormatter = BasicFormatter.timestampFormatter) { 35 | self.format = format 36 | self.separator = separator 37 | self.timestampFormatter = timestampFormatter 38 | } 39 | 40 | /// Our main log formatting method 41 | /// - Parameters: 42 | /// - level: log level 43 | /// - message: actual message 44 | /// - prettyMetadata: optional metadata that has already been "prettified" 45 | /// - file: log's originating file 46 | /// - function: log's originating function 47 | /// - line: log's originating line 48 | /// - Returns: Result of formatting the log 49 | public func processLog(level: Logger.Level, 50 | message: Logger.Message, 51 | prettyMetadata: String?, 52 | file: String, function: String, line: UInt) -> String { 53 | let now = Date() 54 | 55 | return self.format.map({ (component) -> String in 56 | return self.processComponent(component, now: now, level: level, message: message, prettyMetadata: prettyMetadata, file: file, function: function, line: line) 57 | }).filter({ (string) -> Bool in 58 | return string.count > 0 59 | }).joined(separator: self.separator ?? "") 60 | } 61 | 62 | /// [apple/swift-log](https://github.com/apple/swift-log)'s log format 63 | /// 64 | /// `{timestamp} {level}: {message}` 65 | /// 66 | /// *Example:* 67 | /// 68 | /// `2019-07-30T13:49:07-0400 error: Test error message` 69 | public static let apple = BasicFormatter( 70 | [ 71 | .timestamp, 72 | .group([ 73 | .level, 74 | .text(":"), 75 | ]), 76 | .message 77 | ] 78 | ) 79 | 80 | /// Adorkable's go-to log format 😘 81 | /// 82 | /// `{timestamp} ▶ {level} ▶ {file}:{line} ▶ {function} ▶ {message} ▶ {metadata}` 83 | /// 84 | /// *Example:* 85 | /// 86 | /// `2019-07-30T13:49:07-0400 ▶ error ▶ /asdf/swift-log-format-and-pipe/Tests/LoggingFormatAndPipeTests/FormatterTests.swift:25 ▶ testFormatter(_:) ▶ Test error message` 87 | public static let adorkable = BasicFormatter( 88 | [ 89 | .timestamp, 90 | .level, 91 | .group([ 92 | .file, 93 | .text(":"), 94 | .line 95 | ]), 96 | .function, 97 | .message, 98 | .metadata 99 | ], 100 | separator: " ▶ " 101 | ) 102 | } 103 | -------------------------------------------------------------------------------- /Sources/LoggingFormatAndPipe/Formatter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Formatter.swift 3 | // LoggingFormatAndPipe 4 | // 5 | // Created by Ian Grossberg on 7/22/19. 6 | // 7 | 8 | import Logging 9 | import Foundation 10 | 11 | /// Possible log format components 12 | public enum LogComponent { 13 | /// Timestamp of log 14 | /// Specifying your timestamp format can be done by providing a DateFormatter through `Formatter.timestampFormatter` 15 | case timestamp 16 | 17 | /// Log level 18 | case level 19 | /// The actual message 20 | case message 21 | /// Log metadata 22 | case metadata 23 | /// The log's originating file 24 | case file 25 | /// The log's originating function 26 | case function 27 | /// The log's originating line number 28 | case line 29 | 30 | /// Literal text 31 | case text(String) 32 | /// A group of `LogComponents`, not using the specified `separator` 33 | case group([LogComponent]) 34 | 35 | /// All basic log format component types 36 | public static var allNonmetaComponents: [LogComponent] { 37 | return [ 38 | .timestamp, 39 | .level, 40 | .message, 41 | .metadata, 42 | .file, 43 | .function, 44 | .line 45 | ] 46 | } 47 | } 48 | 49 | /// Log Formatter 50 | public protocol Formatter { 51 | /// Timestamp formatter 52 | var timestampFormatter: DateFormatter { get } 53 | 54 | /// Formatter's chance to format the log 55 | /// - Parameter level: log level 56 | /// - Parameter message: actual message 57 | /// - Parameter prettyMetadata: optional metadata that has already been "prettified" 58 | /// - Parameter file: log's originating file 59 | /// - Parameter function: log's originating function 60 | /// - Parameter line: log's originating line 61 | /// - Returns: Result of formatting the log 62 | func processLog(level: Logger.Level, 63 | message: Logger.Message, 64 | prettyMetadata: String?, 65 | file: String, function: String, line: UInt) -> String 66 | 67 | } 68 | 69 | extension Formatter { 70 | /// Common usage component formatter 71 | /// - Parameter _: component to format 72 | /// - Parameter now: log's Date 73 | /// - Parameter level: log level 74 | /// - Parameter message: actual message 75 | /// - Parameter prettyMetadata: optional metadata that has already been "prettified" 76 | /// - Parameter file: log's originating file 77 | /// - Parameter function: log's originating function 78 | /// - Parameter line: log's originating line 79 | /// - Returns: Result of formatting the component 80 | public func processComponent(_ component: LogComponent, now: Date, level: Logger.Level, 81 | message: Logger.Message, 82 | prettyMetadata: String?, 83 | file: String, function: String, line: UInt) -> String { 84 | switch component { 85 | case .timestamp: 86 | return self.timestampFormatter.string(from: now) 87 | case .level: 88 | return "\(level)" 89 | case .message: 90 | return "\(message)" 91 | case .metadata: 92 | return "\(prettyMetadata.map { "\($0)" } ?? "")" 93 | case .file: 94 | return "\(file)" 95 | case .function: 96 | return "\(function)" 97 | case .line: 98 | return "\(line)" 99 | case .text(let string): 100 | return string 101 | case .group(let logComponents): 102 | return logComponents.map({ (component) -> String in 103 | self.processComponent(component, now: now, level: level, message: message, prettyMetadata: prettyMetadata, file: file, function: function, line: line) 104 | }).joined() 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Sources/LoggingFormatAndPipe/Handler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogFormatAndPipeHandler.swift 3 | // LoggingFormatAndPipe 4 | // 5 | // Created by Ian Grossberg on 7/22/19. 6 | // 7 | import Logging 8 | 9 | /// Logging Format and Pipe's Logging Backend 10 | public struct Handler: LogHandler { 11 | 12 | /// Default init 13 | /// - parameters: 14 | /// - formatter: Formatter to format with 15 | /// - pipe: PIpe to pipe to 16 | public init(formatter: Formatter, pipe: Pipe) { 17 | self.formatter = formatter 18 | self.pipe = pipe 19 | } 20 | 21 | /// Formatter we're formatting with 22 | public let formatter: Formatter 23 | 24 | /// PIpe we're piping to 25 | public let pipe: Pipe 26 | 27 | /// Log level specification, used by Logger to filter all log levels less severe then the specified 28 | public var logLevel: Logger.Level = .info 29 | 30 | /// Our main Logging Backend method 31 | public func log(level: Logger.Level, 32 | message: Logger.Message, 33 | metadata: Logger.Metadata?, 34 | file: String, function: String, line: UInt) { 35 | let prettyMetadata = metadata?.isEmpty ?? true 36 | ? self.prettyMetadata 37 | : self.prettify(self.metadata.merging(metadata!, uniquingKeysWith: { _, new in new })) 38 | 39 | let formattedMessage = self.formatter.processLog(level: level, message: message, prettyMetadata: prettyMetadata, file: file, function: function, line: line) 40 | self.pipe.handle(formattedMessage) 41 | } 42 | 43 | private var prettyMetadata: String? 44 | /// Our Logging Backend metadata 45 | public var metadata = Logger.Metadata() { 46 | didSet { 47 | self.prettyMetadata = self.prettify(self.metadata) 48 | } 49 | } 50 | 51 | /// Add, remove, or change the logging metadata. 52 | /// - parameters: 53 | /// - metadataKey: The key for the metadata item 54 | public subscript(metadataKey metadataKey: String) -> Logger.Metadata.Value? { 55 | get { 56 | return self.metadata[metadataKey] 57 | } 58 | set { 59 | self.metadata[metadataKey] = newValue 60 | } 61 | } 62 | 63 | private func prettify(_ metadata: Logger.Metadata) -> String? { 64 | return !metadata.isEmpty ? metadata.map { "\($0)=\($1)" }.joined(separator: " ") : nil 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/LoggingFormatAndPipe/LoggerTextOutputStreamPipe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoggerTextOutputStreamPipe.swift 3 | // LoggingFormatAndPipe 4 | // 5 | // Created by Ian Grossberg on 7/22/19. 6 | // 7 | 8 | #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) 9 | import Darwin 10 | #else 11 | import Glibc 12 | #endif 13 | 14 | import Logging 15 | 16 | /// A pipe for sending logs to a `TextOutputStream` 17 | public struct LoggerTextOutputStreamPipe: Pipe { 18 | private let stream: TextOutputStream 19 | 20 | /// Default init 21 | /// - Parameter _: Our stream to pipe to 22 | public init(_ stream: TextOutputStream) { 23 | self.stream = stream 24 | } 25 | 26 | /// Our main log handling pipe method 27 | /// - Parameters: 28 | /// - _: The formatted log to handle 29 | public func handle(_ formattedLogLine: String) { 30 | var stream = self.stream 31 | stream.write("\(formattedLogLine)\n") 32 | } 33 | } 34 | 35 | extension LoggerTextOutputStreamPipe { 36 | /// Pipe logs to Standard Output (stdout) 37 | public static var standardOutput: LoggerTextOutputStreamPipe { 38 | return LoggerTextOutputStreamPipe(StdioOutputStream.stdout) 39 | } 40 | 41 | /// Pipe logs to Standard Error (stderr) 42 | public static var standardError: LoggerTextOutputStreamPipe { 43 | return LoggerTextOutputStreamPipe(StdioOutputStream.stderr) 44 | } 45 | 46 | } 47 | 48 | /// Copied from swift-log:Logging.swift until it is made public 49 | /// A wrapper to facilitate `print`-ing to stderr and stdio that 50 | /// ensures access to the underlying `FILE` is locked to prevent 51 | /// cross-thread interleaving of output. 52 | public struct StdioOutputStream: TextOutputStream { 53 | /// File handler we're writing to 54 | public let file: UnsafeMutablePointer 55 | 56 | /// Write to file 57 | public func write(_ string: String) { 58 | string.withCString { ptr in 59 | flockfile(file) 60 | defer { 61 | funlockfile(file) 62 | } 63 | _ = fputs(ptr, file) 64 | } 65 | } 66 | 67 | internal static let stderr = StdioOutputStream(file: systemStderr) 68 | internal static let stdout = StdioOutputStream(file: systemStdout) 69 | } 70 | 71 | // Prevent name clashes 72 | #if os(macOS) || os(tvOS) || os(iOS) || os(watchOS) 73 | let systemStderr = Darwin.stderr 74 | let systemStdout = Darwin.stdout 75 | #else 76 | let systemStderr = Glibc.stderr! 77 | let systemStdout = Glibc.stdout! 78 | #endif 79 | -------------------------------------------------------------------------------- /Sources/LoggingFormatAndPipe/Pipe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Pipe.swift 3 | // LoggingFormatAndPipe 4 | // 5 | // Created by Ian Grossberg on 7/22/19. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Log PIpe 11 | public protocol Pipe { 12 | /// Pipe's chance to send a formatted line where it deems 13 | /// - Parameter _: The formatted log to handle 14 | func handle(_ formattedLogLine: String) 15 | } 16 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import swift_log_format_and_pipeTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += swift_log_format_and_pipeTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /Tests/LoggingFormatAndPipeTests/FormatterTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FormatterTests.swift 3 | // LoggingFormatAndPipeTests 4 | // 5 | // Created by Ian Grossberg on 7/23/19. 6 | // 7 | 8 | import XCTest 9 | import Logging 10 | import LoggingFormatAndPipe 11 | 12 | final class FormatterTests: XCTestCase { 13 | func testFormatter(_ formatter: LoggingFormatAndPipe.Formatter) { 14 | let pipe = HistoryPipe() 15 | 16 | let logger = Logger(label: "test\(type(of: formatter))") { _ in 17 | return LoggingFormatAndPipe.Handler( 18 | formatter: formatter, 19 | pipe: pipe 20 | ) 21 | } 22 | 23 | // TODO: fill in testing each case and combination :P 24 | 25 | logger.error("Test error message") 26 | XCTAssertEqual(pipe.formattedLogLine.count, 1) 27 | 28 | logger.info("Test info message") 29 | XCTAssertEqual(pipe.formattedLogLine.count, 2) 30 | } 31 | 32 | func testBasicFormatter() { 33 | self.testFormatter(BasicFormatter()) 34 | } 35 | 36 | func testAppleFormatter() { 37 | self.testFormatter(BasicFormatter.apple) 38 | } 39 | 40 | func testAdorkableFormatter() { 41 | self.testFormatter(BasicFormatter.adorkable) 42 | } 43 | 44 | // TODO: test all formatters 45 | 46 | static var allTests = [ 47 | ("testBasicFormatter", testBasicFormatter), 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /Tests/LoggingFormatAndPipeTests/HandlerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandlerTests.swift 3 | // LoggingFormatAndPipeTests 4 | // 5 | // Created by Ian Grossberg on 7/23/19. 6 | // 7 | 8 | import XCTest 9 | import Logging 10 | import LoggingFormatAndPipe 11 | 12 | final class HandlerTests: XCTestCase { 13 | func testPiping() { 14 | let pipe = HistoryPipe() 15 | let logger = Logger(label: "testPiping") { _ in 16 | return LoggingFormatAndPipe.Handler( 17 | formatter: BasicFormatter(), 18 | pipe: pipe 19 | ) 20 | } 21 | 22 | logger.error("Test error message") 23 | XCTAssertEqual(pipe.formattedLogLine.count, 1) 24 | 25 | logger.info("Test info message") 26 | XCTAssertEqual(pipe.formattedLogLine.count, 2) 27 | } 28 | 29 | static var allTests = [ 30 | ("testPiping", testPiping), 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /Tests/LoggingFormatAndPipeTests/LoggerTextOutputStreamPipeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoggerTextOutputStreamPipeTests.swift 3 | // LoggingFormatAndPipeTests 4 | // 5 | // Created by Ian Grossberg on 7/23/19. 6 | // 7 | 8 | import XCTest 9 | import Logging 10 | import LoggingFormatAndPipe 11 | 12 | final class LoggerTextOutputStreamPipeTests: XCTestCase { 13 | func testStdout() { 14 | let logger = Logger(label: "testStdout") { _ in 15 | return LoggingFormatAndPipe.Handler( 16 | formatter: BasicFormatter(), 17 | pipe: LoggerTextOutputStreamPipe.standardOutput 18 | ) 19 | } 20 | 21 | logger.error("Test error message") 22 | 23 | logger.info("Test info message") 24 | 25 | // Check the logs! 26 | } 27 | 28 | func testStderr() { 29 | let logger = Logger(label: "testStderr") { _ in 30 | return LoggingFormatAndPipe.Handler( 31 | formatter: BasicFormatter(), 32 | pipe: LoggerTextOutputStreamPipe.standardError 33 | ) 34 | } 35 | 36 | logger.error("Test error message") 37 | 38 | logger.info("Test info message") 39 | 40 | // Check the logs! 41 | } 42 | 43 | static var allTests = [ 44 | ("testStdout", testStdout), 45 | ("testStderr", testStderr) 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /Tests/LoggingFormatAndPipeTests/TestLogging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestLogging.swift 3 | // LoggingFormatAndPipeTests 4 | // 5 | // Created by Ian Grossberg on 7/22/19. 6 | // 7 | 8 | import Foundation 9 | import LoggingFormatAndPipe 10 | import XCTest 11 | 12 | internal class HistoryPipe: LoggingFormatAndPipe.Pipe { 13 | var formattedLogLine = [String]() 14 | 15 | func handle(_ formattedLogLine: String) { 16 | self.formattedLogLine.append(formattedLogLine) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Tests/LoggingFormatAndPipeTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(HandlerTests.allTests), 7 | testCase(FormatterTests.allTests), 8 | testCase(LoggerTextOutputStreamPipeTests.allTests), 9 | ] 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /docs/Enums.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Enumerations Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Enumerations

96 |

The following enumerations are available globally.

97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 |
    105 |
  • 106 |
    107 | 108 | 109 | 110 | LogComponent 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Possible log format components

    119 | 120 | See more 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public enum LogComponent
    127 | 128 |
    129 |
    130 |
    131 | Show on GitHub 132 |
    133 |
    134 |
    135 |
  • 136 |
137 |
138 |
139 |
140 | 141 |
142 |
143 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /docs/Protocols.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Protocols Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Protocols

96 |

The following protocols are available globally.

97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 |
    105 |
  • 106 |
    107 | 108 | 109 | 110 | Formatter 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Log Formatter

    119 | 120 | See more 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public protocol Formatter
    127 | 128 |
    129 |
    130 |
    131 | Show on GitHub 132 |
    133 |
    134 |
    135 |
  • 136 |
137 |
138 |
139 |
    140 |
  • 141 |
    142 | 143 | 144 | 145 | Pipe 146 | 147 |
    148 |
    149 |
    150 |
    151 |
    152 |
    153 |

    Log PIpe

    154 | 155 | See more 156 |
    157 |
    158 |

    Declaration

    159 |
    160 |

    Swift

    161 |
    public protocol Pipe
    162 | 163 |
    164 |
    165 |
    166 | Show on GitHub 167 |
    168 |
    169 |
    170 |
  • 171 |
172 |
173 |
174 |
175 | 176 |
177 |
178 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /docs/Protocols/Pipe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pipe Protocol Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Pipe

96 |
97 |
98 |
public protocol Pipe
99 | 100 |
101 |
102 |

Log PIpe

103 | 104 |
105 |
106 | 107 |
108 |
109 |
110 |
    111 |
  • 112 |
    113 | 114 | 115 | 116 | handle(_:) 117 | 118 |
    119 |
    120 |
    121 |
    122 |
    123 |
    124 |

    Pipe’s chance to send a formatted line where it deems

    125 | 126 |
    127 |
    128 |

    Declaration

    129 |
    130 |

    Swift

    131 |
    func handle(_ formattedLogLine: String)
    132 | 133 |
    134 |
    135 |
    136 |

    Parameters

    137 | 138 | 139 | 140 | 145 | 150 | 151 | 152 |
    141 | 142 | _ 143 | 144 | 146 |
    147 |

    The formatted log to handle

    148 |
    149 |
    153 |
    154 |
    155 | Show on GitHub 156 |
    157 |
    158 |
    159 |
  • 160 |
161 |
162 |
163 |
164 | 165 |
166 |
167 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /docs/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structures Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Structures

96 |

The following structures are available globally.

97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 |
    105 |
  • 106 |
    107 | 108 | 109 | 110 | BasicFormatter 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Your basic, customizable log formatter 119 | BasicFormatter does not need any setup and will automatically include all log components 120 | It can also be given a linear sequence of log components and it will build formatted logs in that order

    121 | 122 | See more 123 |
    124 |
    125 |

    Declaration

    126 |
    127 |

    Swift

    128 |
    public struct BasicFormatter : Formatter
    129 | 130 |
    131 |
    132 |
    133 | Show on GitHub 134 |
    135 |
    136 |
    137 |
  • 138 |
139 |
140 |
141 |
    142 |
  • 143 |
    144 | 145 | 146 | 147 | Handler 148 | 149 |
    150 |
    151 |
    152 |
    153 |
    154 |
    155 |

    Logging Format and Pipe’s Logging Backend

    156 | 157 | See more 158 |
    159 |
    160 |

    Declaration

    161 |
    162 |

    Swift

    163 |
    public struct Handler : LogHandler
    164 | 165 |
    166 |
    167 |
    168 | Show on GitHub 169 |
    170 |
    171 |
    172 |
  • 173 |
174 |
175 |
176 |
    177 |
  • 178 |
    179 | 180 | 181 | 182 | LoggerTextOutputStreamPipe 183 | 184 |
    185 |
    186 |
    187 |
    188 |
    189 |
    190 |

    A pipe for sending logs to a TextOutputStream

    191 | 192 | See more 193 |
    194 |
    195 |

    Declaration

    196 |
    197 |

    Swift

    198 |
    public struct LoggerTextOutputStreamPipe : Pipe
    199 | 200 |
    201 |
    202 |
    203 | Show on GitHub 204 |
    205 |
    206 |
    207 |
  • 208 |
  • 209 |
    210 | 211 | 212 | 213 | StdioOutputStream 214 | 215 |
    216 |
    217 |
    218 |
    219 |
    220 |
    221 |

    Copied from swift-log:Logging.swift until it is made public 222 | A wrapper to facilitate print-ing to stderr and stdio that 223 | ensures access to the underlying FILE is locked to prevent 224 | cross-thread interleaving of output.

    225 | 226 | See more 227 |
    228 |
    229 |

    Declaration

    230 |
    231 |

    Swift

    232 |
    public struct StdioOutputStream : TextOutputStream
    233 | 234 |
    235 |
    236 |
    237 | Show on GitHub 238 |
    239 |
    240 |
    241 |
  • 242 |
243 |
244 |
245 |
246 | 247 |
248 |
249 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /docs/Structs/LoggerTextOutputStreamPipe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LoggerTextOutputStreamPipe Structure Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

LoggerTextOutputStreamPipe

96 |
97 |
98 |
public struct LoggerTextOutputStreamPipe : Pipe
99 | 100 |
101 |
102 |

A pipe for sending logs to a TextOutputStream

103 | 104 |
105 |
106 | 107 |
108 |
109 |
110 |
    111 |
  • 112 |
    113 | 114 | 115 | 116 | init(_:) 117 | 118 |
    119 |
    120 |
    121 |
    122 |
    123 |
    124 |

    Default init

    125 | 126 |
    127 |
    128 |

    Declaration

    129 |
    130 |

    Swift

    131 |
    public init(_ stream: TextOutputStream)
    132 | 133 |
    134 |
    135 |
    136 |

    Parameters

    137 | 138 | 139 | 140 | 145 | 150 | 151 | 152 |
    141 | 142 | _ 143 | 144 | 146 |
    147 |

    Our stream to pipe to

    148 |
    149 |
    153 |
    154 |
    155 | Show on GitHub 156 |
    157 |
    158 |
    159 |
  • 160 |
  • 161 |
    162 | 163 | 164 | 165 | handle(_:) 166 | 167 |
    168 |
    169 |
    170 |
    171 |
    172 |
    173 |

    Our main log handling pipe method

    174 | 175 |
    176 |
    177 |

    Declaration

    178 |
    179 |

    Swift

    180 |
    public func handle(_ formattedLogLine: String)
    181 | 182 |
    183 |
    184 |
    185 |

    Parameters

    186 | 187 | 188 | 189 | 194 | 199 | 200 | 201 |
    190 | 191 | _ 192 | 193 | 195 |
    196 |

    The formatted log to handle

    197 |
    198 |
    202 |
    203 |
    204 | Show on GitHub 205 |
    206 |
    207 |
    208 |
  • 209 |
210 |
211 |
212 |
    213 |
  • 214 |
    215 | 216 | 217 | 218 | standardOutput 219 | 220 |
    221 |
    222 |
    223 |
    224 |
    225 |
    226 |

    Pipe logs to Standard Output (stdout)

    227 | 228 |
    229 |
    230 |

    Declaration

    231 |
    232 |

    Swift

    233 |
    public static var standardOutput: LoggerTextOutputStreamPipe { get }
    234 | 235 |
    236 |
    237 |
    238 | Show on GitHub 239 |
    240 |
    241 |
    242 |
  • 243 |
  • 244 |
    245 | 246 | 247 | 248 | standardError 249 | 250 |
    251 |
    252 |
    253 |
    254 |
    255 |
    256 |

    Pipe logs to Standard Error (stderr)

    257 | 258 |
    259 |
    260 |

    Declaration

    261 |
    262 |

    Swift

    263 |
    public static var standardError: LoggerTextOutputStreamPipe { get }
    264 | 265 |
    266 |
    267 |
    268 | Show on GitHub 269 |
    270 |
    271 |
    272 |
  • 273 |
274 |
275 |
276 |
277 | 278 |
279 |
280 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /docs/Structs/StdioOutputStream.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StdioOutputStream Structure Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

StdioOutputStream

96 |
97 |
98 |
public struct StdioOutputStream : TextOutputStream
99 | 100 |
101 |
102 |

Copied from swift-log:Logging.swift until it is made public 103 | A wrapper to facilitate print-ing to stderr and stdio that 104 | ensures access to the underlying FILE is locked to prevent 105 | cross-thread interleaving of output.

106 | 107 |
108 |
109 | 110 |
111 |
112 |
113 |
    114 |
  • 115 |
    116 | 117 | 118 | 119 | file 120 | 121 |
    122 |
    123 |
    124 |
    125 |
    126 |
    127 |

    File handler we’re writing to

    128 | 129 |
    130 |
    131 |

    Declaration

    132 |
    133 |

    Swift

    134 |
    public let file: UnsafeMutablePointer<FILE>
    135 | 136 |
    137 |
    138 |
    139 | Show on GitHub 140 |
    141 |
    142 |
    143 |
  • 144 |
  • 145 |
    146 | 147 | 148 | 149 | write(_:) 150 | 151 |
    152 |
    153 |
    154 |
    155 |
    156 |
    157 |

    Write to file

    158 | 159 |
    160 |
    161 |

    Declaration

    162 |
    163 |

    Swift

    164 |
    public func write(_ string: String)
    165 | 166 |
    167 |
    168 |
    169 | Show on GitHub 170 |
    171 |
    172 |
    173 |
  • 174 |
175 |
176 |
177 |
178 | 179 |
180 |
181 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /docs/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | documentation 17 | 18 | 19 | documentation 20 | 21 | 22 | 100% 23 | 24 | 25 | 100% 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/css/jazzy.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | box-sizing: inherit; } 3 | 4 | body { 5 | margin: 0; 6 | background: #fff; 7 | color: #333; 8 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; 9 | letter-spacing: .2px; 10 | -webkit-font-smoothing: antialiased; 11 | box-sizing: border-box; } 12 | 13 | h1 { 14 | font-size: 2rem; 15 | font-weight: 700; 16 | margin: 1.275em 0 0.6em; } 17 | 18 | h2 { 19 | font-size: 1.75rem; 20 | font-weight: 700; 21 | margin: 1.275em 0 0.3em; } 22 | 23 | h3 { 24 | font-size: 1.5rem; 25 | font-weight: 700; 26 | margin: 1em 0 0.3em; } 27 | 28 | h4 { 29 | font-size: 1.25rem; 30 | font-weight: 700; 31 | margin: 1.275em 0 0.85em; } 32 | 33 | h5 { 34 | font-size: 1rem; 35 | font-weight: 700; 36 | margin: 1.275em 0 0.85em; } 37 | 38 | h6 { 39 | font-size: 1rem; 40 | font-weight: 700; 41 | margin: 1.275em 0 0.85em; 42 | color: #777; } 43 | 44 | p { 45 | margin: 0 0 1em; } 46 | 47 | ul, ol { 48 | padding: 0 0 0 2em; 49 | margin: 0 0 0.85em; } 50 | 51 | blockquote { 52 | margin: 0 0 0.85em; 53 | padding: 0 15px; 54 | color: #858585; 55 | border-left: 4px solid #e5e5e5; } 56 | 57 | img { 58 | max-width: 100%; } 59 | 60 | a { 61 | color: #4183c4; 62 | text-decoration: none; } 63 | a:hover, a:focus { 64 | outline: 0; 65 | text-decoration: underline; } 66 | a.discouraged { 67 | text-decoration: line-through; } 68 | a.discouraged:hover, a.discouraged:focus { 69 | text-decoration: underline line-through; } 70 | 71 | table { 72 | background: #fff; 73 | width: 100%; 74 | border-collapse: collapse; 75 | border-spacing: 0; 76 | overflow: auto; 77 | margin: 0 0 0.85em; } 78 | 79 | tr:nth-child(2n) { 80 | background-color: #fbfbfb; } 81 | 82 | th, td { 83 | padding: 6px 13px; 84 | border: 1px solid #ddd; } 85 | 86 | pre { 87 | margin: 0 0 1.275em; 88 | padding: .85em 1em; 89 | overflow: auto; 90 | background: #f7f7f7; 91 | font-size: .85em; 92 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } 93 | 94 | code { 95 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } 96 | 97 | p > code, li > code { 98 | background: #f7f7f7; 99 | padding: .2em; } 100 | p > code:before, p > code:after, li > code:before, li > code:after { 101 | letter-spacing: -.2em; 102 | content: "\00a0"; } 103 | 104 | pre code { 105 | padding: 0; 106 | white-space: pre; } 107 | 108 | .content-wrapper { 109 | display: flex; 110 | flex-direction: column; } 111 | @media (min-width: 768px) { 112 | .content-wrapper { 113 | flex-direction: row; } } 114 | 115 | .header { 116 | display: flex; 117 | padding: 8px; 118 | font-size: 0.875em; 119 | background: #444; 120 | color: #999; } 121 | 122 | .header-col { 123 | margin: 0; 124 | padding: 0 8px; } 125 | 126 | .header-col--primary { 127 | flex: 1; } 128 | 129 | .header-link { 130 | color: #fff; } 131 | 132 | .header-icon { 133 | padding-right: 6px; 134 | vertical-align: -4px; 135 | height: 16px; } 136 | 137 | .breadcrumbs { 138 | font-size: 0.875em; 139 | padding: 8px 16px; 140 | margin: 0; 141 | background: #fbfbfb; 142 | border-bottom: 1px solid #ddd; } 143 | 144 | .carat { 145 | height: 10px; 146 | margin: 0 5px; } 147 | 148 | .navigation { 149 | order: 2; } 150 | @media (min-width: 768px) { 151 | .navigation { 152 | order: 1; 153 | width: 25%; 154 | max-width: 300px; 155 | padding-bottom: 64px; 156 | overflow: hidden; 157 | word-wrap: normal; 158 | background: #fbfbfb; 159 | border-right: 1px solid #ddd; } } 160 | 161 | .nav-groups { 162 | list-style-type: none; 163 | padding-left: 0; } 164 | 165 | .nav-group-name { 166 | border-bottom: 1px solid #ddd; 167 | padding: 8px 0 8px 16px; } 168 | 169 | .nav-group-name-link { 170 | color: #333; } 171 | 172 | .nav-group-tasks { 173 | margin: 8px 0; 174 | padding: 0 0 0 8px; } 175 | 176 | .nav-group-task { 177 | font-size: 1em; 178 | list-style-type: none; 179 | white-space: nowrap; } 180 | 181 | .nav-group-task-link { 182 | color: #808080; } 183 | 184 | .main-content { 185 | order: 1; } 186 | @media (min-width: 768px) { 187 | .main-content { 188 | order: 2; 189 | flex: 1; 190 | padding-bottom: 60px; } } 191 | 192 | .section { 193 | padding: 0 32px; 194 | border-bottom: 1px solid #ddd; } 195 | 196 | .section-content { 197 | max-width: 834px; 198 | margin: 0 auto; 199 | padding: 16px 0; } 200 | 201 | .section-name { 202 | color: #666; 203 | display: block; } 204 | 205 | .declaration .highlight { 206 | overflow-x: initial; 207 | padding: 8px 0; 208 | margin: 0; 209 | background-color: transparent; 210 | border: none; } 211 | 212 | .task-group-section { 213 | border-top: 1px solid #ddd; } 214 | 215 | .task-group { 216 | padding-top: 0px; } 217 | 218 | .task-name-container a[name]:before { 219 | content: ""; 220 | display: block; } 221 | 222 | .item-container { 223 | padding: 0; } 224 | 225 | .item { 226 | padding-top: 8px; 227 | width: 100%; 228 | list-style-type: none; } 229 | .item a[name]:before { 230 | content: ""; 231 | display: block; } 232 | .item .token, .item .direct-link { 233 | padding-left: 3px; 234 | margin-left: 0px; 235 | font-size: 1rem; } 236 | .item .declaration-note { 237 | font-size: .85em; 238 | color: #808080; 239 | font-style: italic; } 240 | 241 | .pointer-container { 242 | border-bottom: 1px solid #ddd; 243 | left: -23px; 244 | padding-bottom: 13px; 245 | position: relative; 246 | width: 110%; } 247 | 248 | .pointer { 249 | left: 21px; 250 | top: 7px; 251 | display: block; 252 | position: absolute; 253 | width: 12px; 254 | height: 12px; 255 | border-left: 1px solid #ddd; 256 | border-top: 1px solid #ddd; 257 | background: #fff; 258 | transform: rotate(45deg); } 259 | 260 | .height-container { 261 | display: none; 262 | position: relative; 263 | width: 100%; 264 | overflow: hidden; } 265 | .height-container .section { 266 | background: #fff; 267 | border: 1px solid #ddd; 268 | border-top-width: 0; 269 | padding-top: 10px; 270 | padding-bottom: 5px; 271 | padding: 8px 16px; } 272 | 273 | .aside, .language { 274 | padding: 6px 12px; 275 | margin: 12px 0; 276 | border-left: 5px solid #dddddd; 277 | overflow-y: hidden; } 278 | .aside .aside-title, .language .aside-title { 279 | font-size: 9px; 280 | letter-spacing: 2px; 281 | text-transform: uppercase; 282 | padding-bottom: 0; 283 | margin: 0; 284 | color: #aaa; 285 | -webkit-user-select: none; } 286 | .aside p:last-child, .language p:last-child { 287 | margin-bottom: 0; } 288 | 289 | .language { 290 | border-left: 5px solid #cde9f4; } 291 | .language .aside-title { 292 | color: #4183c4; } 293 | 294 | .aside-warning, .aside-deprecated, .aside-unavailable { 295 | border-left: 5px solid #ff6666; } 296 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { 297 | color: #ff0000; } 298 | 299 | .graybox { 300 | border-collapse: collapse; 301 | width: 100%; } 302 | .graybox p { 303 | margin: 0; 304 | word-break: break-word; 305 | min-width: 50px; } 306 | .graybox td { 307 | border: 1px solid #ddd; 308 | padding: 5px 25px 5px 10px; 309 | vertical-align: middle; } 310 | .graybox tr td:first-of-type { 311 | text-align: right; 312 | padding: 7px; 313 | vertical-align: top; 314 | word-break: normal; 315 | width: 40px; } 316 | 317 | .slightly-smaller { 318 | font-size: 0.9em; } 319 | 320 | .footer { 321 | padding: 8px 16px; 322 | background: #444; 323 | color: #ddd; 324 | font-size: 0.8em; } 325 | .footer p { 326 | margin: 8px 0; } 327 | .footer a { 328 | color: #fff; } 329 | 330 | html.dash .header, html.dash .breadcrumbs, html.dash .navigation { 331 | display: none; } 332 | html.dash .height-container { 333 | display: block; } 334 | 335 | form[role=search] input { 336 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; 337 | font-size: 14px; 338 | line-height: 24px; 339 | padding: 0 10px; 340 | margin: 0; 341 | border: none; 342 | border-radius: 1em; } 343 | .loading form[role=search] input { 344 | background: white url(../img/spinner.gif) center right 4px no-repeat; } 345 | form[role=search] .tt-menu { 346 | margin: 0; 347 | min-width: 300px; 348 | background: #fbfbfb; 349 | color: #333; 350 | border: 1px solid #ddd; } 351 | form[role=search] .tt-highlight { 352 | font-weight: bold; } 353 | form[role=search] .tt-suggestion { 354 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; 355 | padding: 0 8px; } 356 | form[role=search] .tt-suggestion span { 357 | display: table-cell; 358 | white-space: nowrap; } 359 | form[role=search] .tt-suggestion .doc-parent-name { 360 | width: 100%; 361 | text-align: right; 362 | font-weight: normal; 363 | font-size: 0.9em; 364 | padding-left: 16px; } 365 | form[role=search] .tt-suggestion:hover, 366 | form[role=search] .tt-suggestion.tt-cursor { 367 | cursor: pointer; 368 | background-color: #4183c4; 369 | color: #fff; } 370 | form[role=search] .tt-suggestion:hover .doc-parent-name, 371 | form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { 372 | color: #fff; } 373 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.jazzy.loggingformatandpipe 7 | CFBundleName 8 | LoggingFormatAndPipe 9 | DocSetPlatformFamily 10 | loggingformatandpipe 11 | isDashDocset 12 | 13 | dashIndexFilePath 14 | index.html 15 | isJavaScriptEnabled 16 | 17 | DashDocSetFamily 18 | dashtoc 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/Enums.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Enumerations Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Enumerations

96 |

The following enumerations are available globally.

97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 |
    105 |
  • 106 |
    107 | 108 | 109 | 110 | LogComponent 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Possible log format components

    119 | 120 | See more 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public enum LogComponent
    127 | 128 |
    129 |
    130 |
    131 | Show on GitHub 132 |
    133 |
    134 |
    135 |
  • 136 |
137 |
138 |
139 |
140 | 141 |
142 |
143 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/Protocols.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Protocols Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Protocols

96 |

The following protocols are available globally.

97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 |
    105 |
  • 106 |
    107 | 108 | 109 | 110 | Formatter 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Log Formatter

    119 | 120 | See more 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public protocol Formatter
    127 | 128 |
    129 |
    130 |
    131 | Show on GitHub 132 |
    133 |
    134 |
    135 |
  • 136 |
137 |
138 |
139 |
    140 |
  • 141 |
    142 | 143 | 144 | 145 | Pipe 146 | 147 |
    148 |
    149 |
    150 |
    151 |
    152 |
    153 |

    Log PIpe

    154 | 155 | See more 156 |
    157 |
    158 |

    Declaration

    159 |
    160 |

    Swift

    161 |
    public protocol Pipe
    162 | 163 |
    164 |
    165 |
    166 | Show on GitHub 167 |
    168 |
    169 |
    170 |
  • 171 |
172 |
173 |
174 |
175 | 176 |
177 |
178 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/Protocols/Pipe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pipe Protocol Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Pipe

96 |
97 |
98 |
public protocol Pipe
99 | 100 |
101 |
102 |

Log PIpe

103 | 104 |
105 |
106 | 107 |
108 |
109 |
110 |
    111 |
  • 112 |
    113 | 114 | 115 | 116 | handle(_:) 117 | 118 |
    119 |
    120 |
    121 |
    122 |
    123 |
    124 |

    Pipe’s chance to send a formatted line where it deems

    125 | 126 |
    127 |
    128 |

    Declaration

    129 |
    130 |

    Swift

    131 |
    func handle(_ formattedLogLine: String)
    132 | 133 |
    134 |
    135 |
    136 |

    Parameters

    137 | 138 | 139 | 140 | 145 | 150 | 151 | 152 |
    141 | 142 | _ 143 | 144 | 146 |
    147 |

    The formatted log to handle

    148 |
    149 |
    153 |
    154 |
    155 | Show on GitHub 156 |
    157 |
    158 |
    159 |
  • 160 |
161 |
162 |
163 |
164 | 165 |
166 |
167 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structures Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

Structures

96 |

The following structures are available globally.

97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 |
    105 |
  • 106 |
    107 | 108 | 109 | 110 | BasicFormatter 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Your basic, customizable log formatter 119 | BasicFormatter does not need any setup and will automatically include all log components 120 | It can also be given a linear sequence of log components and it will build formatted logs in that order

    121 | 122 | See more 123 |
    124 |
    125 |

    Declaration

    126 |
    127 |

    Swift

    128 |
    public struct BasicFormatter : Formatter
    129 | 130 |
    131 |
    132 |
    133 | Show on GitHub 134 |
    135 |
    136 |
    137 |
  • 138 |
139 |
140 |
141 |
    142 |
  • 143 |
    144 | 145 | 146 | 147 | Handler 148 | 149 |
    150 |
    151 |
    152 |
    153 |
    154 |
    155 |

    Logging Format and Pipe’s Logging Backend

    156 | 157 | See more 158 |
    159 |
    160 |

    Declaration

    161 |
    162 |

    Swift

    163 |
    public struct Handler : LogHandler
    164 | 165 |
    166 |
    167 |
    168 | Show on GitHub 169 |
    170 |
    171 |
    172 |
  • 173 |
174 |
175 |
176 |
    177 |
  • 178 |
    179 | 180 | 181 | 182 | LoggerTextOutputStreamPipe 183 | 184 |
    185 |
    186 |
    187 |
    188 |
    189 |
    190 |

    A pipe for sending logs to a TextOutputStream

    191 | 192 | See more 193 |
    194 |
    195 |

    Declaration

    196 |
    197 |

    Swift

    198 |
    public struct LoggerTextOutputStreamPipe : Pipe
    199 | 200 |
    201 |
    202 |
    203 | Show on GitHub 204 |
    205 |
    206 |
    207 |
  • 208 |
  • 209 |
    210 | 211 | 212 | 213 | StdioOutputStream 214 | 215 |
    216 |
    217 |
    218 |
    219 |
    220 |
    221 |

    Copied from swift-log:Logging.swift until it is made public 222 | A wrapper to facilitate print-ing to stderr and stdio that 223 | ensures access to the underlying FILE is locked to prevent 224 | cross-thread interleaving of output.

    225 | 226 | See more 227 |
    228 |
    229 |

    Declaration

    230 |
    231 |

    Swift

    232 |
    public struct StdioOutputStream : TextOutputStream
    233 | 234 |
    235 |
    236 |
    237 | Show on GitHub 238 |
    239 |
    240 |
    241 |
  • 242 |
243 |
244 |
245 |
246 | 247 |
248 |
249 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/Structs/LoggerTextOutputStreamPipe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LoggerTextOutputStreamPipe Structure Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

LoggerTextOutputStreamPipe

96 |
97 |
98 |
public struct LoggerTextOutputStreamPipe : Pipe
99 | 100 |
101 |
102 |

A pipe for sending logs to a TextOutputStream

103 | 104 |
105 |
106 | 107 |
108 |
109 |
110 |
    111 |
  • 112 |
    113 | 114 | 115 | 116 | init(_:) 117 | 118 |
    119 |
    120 |
    121 |
    122 |
    123 |
    124 |

    Default init

    125 | 126 |
    127 |
    128 |

    Declaration

    129 |
    130 |

    Swift

    131 |
    public init(_ stream: TextOutputStream)
    132 | 133 |
    134 |
    135 |
    136 |

    Parameters

    137 | 138 | 139 | 140 | 145 | 150 | 151 | 152 |
    141 | 142 | _ 143 | 144 | 146 |
    147 |

    Our stream to pipe to

    148 |
    149 |
    153 |
    154 |
    155 | Show on GitHub 156 |
    157 |
    158 |
    159 |
  • 160 |
  • 161 |
    162 | 163 | 164 | 165 | handle(_:) 166 | 167 |
    168 |
    169 |
    170 |
    171 |
    172 |
    173 |

    Our main log handling pipe method

    174 | 175 |
    176 |
    177 |

    Declaration

    178 |
    179 |

    Swift

    180 |
    public func handle(_ formattedLogLine: String)
    181 | 182 |
    183 |
    184 |
    185 |

    Parameters

    186 | 187 | 188 | 189 | 194 | 199 | 200 | 201 |
    190 | 191 | _ 192 | 193 | 195 |
    196 |

    The formatted log to handle

    197 |
    198 |
    202 |
    203 |
    204 | Show on GitHub 205 |
    206 |
    207 |
    208 |
  • 209 |
210 |
211 |
212 |
    213 |
  • 214 |
    215 | 216 | 217 | 218 | standardOutput 219 | 220 |
    221 |
    222 |
    223 |
    224 |
    225 |
    226 |

    Pipe logs to Standard Output (stdout)

    227 | 228 |
    229 |
    230 |

    Declaration

    231 |
    232 |

    Swift

    233 |
    public static var standardOutput: LoggerTextOutputStreamPipe { get }
    234 | 235 |
    236 |
    237 |
    238 | Show on GitHub 239 |
    240 |
    241 |
    242 |
  • 243 |
  • 244 |
    245 | 246 | 247 | 248 | standardError 249 | 250 |
    251 |
    252 |
    253 |
    254 |
    255 |
    256 |

    Pipe logs to Standard Error (stderr)

    257 | 258 |
    259 |
    260 |

    Declaration

    261 |
    262 |

    Swift

    263 |
    public static var standardError: LoggerTextOutputStreamPipe { get }
    264 | 265 |
    266 |
    267 |
    268 | Show on GitHub 269 |
    270 |
    271 |
    272 |
  • 273 |
274 |
275 |
276 |
277 | 278 |
279 |
280 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/Structs/StdioOutputStream.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StdioOutputStream Structure Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

23 | 24 | LoggingFormatAndPipe Docs 25 | 26 | (100% documented) 27 |

28 | 29 |

30 |

31 | 32 |
33 |

34 | 35 |

36 | 37 | 38 | View on GitHub 39 | 40 |

41 | 42 |
43 | 44 | 49 | 50 |
51 | 91 |
92 | 93 |
94 |
95 |

StdioOutputStream

96 |
97 |
98 |
public struct StdioOutputStream : TextOutputStream
99 | 100 |
101 |
102 |

Copied from swift-log:Logging.swift until it is made public 103 | A wrapper to facilitate print-ing to stderr and stdio that 104 | ensures access to the underlying FILE is locked to prevent 105 | cross-thread interleaving of output.

106 | 107 |
108 |
109 | 110 |
111 |
112 |
113 |
    114 |
  • 115 |
    116 | 117 | 118 | 119 | file 120 | 121 |
    122 |
    123 |
    124 |
    125 |
    126 |
    127 |

    File handler we’re writing to

    128 | 129 |
    130 |
    131 |

    Declaration

    132 |
    133 |

    Swift

    134 |
    public let file: UnsafeMutablePointer<FILE>
    135 | 136 |
    137 |
    138 |
    139 | Show on GitHub 140 |
    141 |
    142 |
    143 |
  • 144 |
  • 145 |
    146 | 147 | 148 | 149 | write(_:) 150 | 151 |
    152 |
    153 |
    154 |
    155 |
    156 |
    157 |

    Write to file

    158 | 159 |
    160 |
    161 |

    Declaration

    162 |
    163 |

    Swift

    164 |
    public func write(_ string: String)
    165 | 166 |
    167 |
    168 |
    169 | Show on GitHub 170 |
    171 |
    172 |
    173 |
  • 174 |
175 |
176 |
177 |
178 | 179 |
180 |
181 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/css/jazzy.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | box-sizing: inherit; } 3 | 4 | body { 5 | margin: 0; 6 | background: #fff; 7 | color: #333; 8 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; 9 | letter-spacing: .2px; 10 | -webkit-font-smoothing: antialiased; 11 | box-sizing: border-box; } 12 | 13 | h1 { 14 | font-size: 2rem; 15 | font-weight: 700; 16 | margin: 1.275em 0 0.6em; } 17 | 18 | h2 { 19 | font-size: 1.75rem; 20 | font-weight: 700; 21 | margin: 1.275em 0 0.3em; } 22 | 23 | h3 { 24 | font-size: 1.5rem; 25 | font-weight: 700; 26 | margin: 1em 0 0.3em; } 27 | 28 | h4 { 29 | font-size: 1.25rem; 30 | font-weight: 700; 31 | margin: 1.275em 0 0.85em; } 32 | 33 | h5 { 34 | font-size: 1rem; 35 | font-weight: 700; 36 | margin: 1.275em 0 0.85em; } 37 | 38 | h6 { 39 | font-size: 1rem; 40 | font-weight: 700; 41 | margin: 1.275em 0 0.85em; 42 | color: #777; } 43 | 44 | p { 45 | margin: 0 0 1em; } 46 | 47 | ul, ol { 48 | padding: 0 0 0 2em; 49 | margin: 0 0 0.85em; } 50 | 51 | blockquote { 52 | margin: 0 0 0.85em; 53 | padding: 0 15px; 54 | color: #858585; 55 | border-left: 4px solid #e5e5e5; } 56 | 57 | img { 58 | max-width: 100%; } 59 | 60 | a { 61 | color: #4183c4; 62 | text-decoration: none; } 63 | a:hover, a:focus { 64 | outline: 0; 65 | text-decoration: underline; } 66 | a.discouraged { 67 | text-decoration: line-through; } 68 | a.discouraged:hover, a.discouraged:focus { 69 | text-decoration: underline line-through; } 70 | 71 | table { 72 | background: #fff; 73 | width: 100%; 74 | border-collapse: collapse; 75 | border-spacing: 0; 76 | overflow: auto; 77 | margin: 0 0 0.85em; } 78 | 79 | tr:nth-child(2n) { 80 | background-color: #fbfbfb; } 81 | 82 | th, td { 83 | padding: 6px 13px; 84 | border: 1px solid #ddd; } 85 | 86 | pre { 87 | margin: 0 0 1.275em; 88 | padding: .85em 1em; 89 | overflow: auto; 90 | background: #f7f7f7; 91 | font-size: .85em; 92 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } 93 | 94 | code { 95 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } 96 | 97 | p > code, li > code { 98 | background: #f7f7f7; 99 | padding: .2em; } 100 | p > code:before, p > code:after, li > code:before, li > code:after { 101 | letter-spacing: -.2em; 102 | content: "\00a0"; } 103 | 104 | pre code { 105 | padding: 0; 106 | white-space: pre; } 107 | 108 | .content-wrapper { 109 | display: flex; 110 | flex-direction: column; } 111 | @media (min-width: 768px) { 112 | .content-wrapper { 113 | flex-direction: row; } } 114 | 115 | .header { 116 | display: flex; 117 | padding: 8px; 118 | font-size: 0.875em; 119 | background: #444; 120 | color: #999; } 121 | 122 | .header-col { 123 | margin: 0; 124 | padding: 0 8px; } 125 | 126 | .header-col--primary { 127 | flex: 1; } 128 | 129 | .header-link { 130 | color: #fff; } 131 | 132 | .header-icon { 133 | padding-right: 6px; 134 | vertical-align: -4px; 135 | height: 16px; } 136 | 137 | .breadcrumbs { 138 | font-size: 0.875em; 139 | padding: 8px 16px; 140 | margin: 0; 141 | background: #fbfbfb; 142 | border-bottom: 1px solid #ddd; } 143 | 144 | .carat { 145 | height: 10px; 146 | margin: 0 5px; } 147 | 148 | .navigation { 149 | order: 2; } 150 | @media (min-width: 768px) { 151 | .navigation { 152 | order: 1; 153 | width: 25%; 154 | max-width: 300px; 155 | padding-bottom: 64px; 156 | overflow: hidden; 157 | word-wrap: normal; 158 | background: #fbfbfb; 159 | border-right: 1px solid #ddd; } } 160 | 161 | .nav-groups { 162 | list-style-type: none; 163 | padding-left: 0; } 164 | 165 | .nav-group-name { 166 | border-bottom: 1px solid #ddd; 167 | padding: 8px 0 8px 16px; } 168 | 169 | .nav-group-name-link { 170 | color: #333; } 171 | 172 | .nav-group-tasks { 173 | margin: 8px 0; 174 | padding: 0 0 0 8px; } 175 | 176 | .nav-group-task { 177 | font-size: 1em; 178 | list-style-type: none; 179 | white-space: nowrap; } 180 | 181 | .nav-group-task-link { 182 | color: #808080; } 183 | 184 | .main-content { 185 | order: 1; } 186 | @media (min-width: 768px) { 187 | .main-content { 188 | order: 2; 189 | flex: 1; 190 | padding-bottom: 60px; } } 191 | 192 | .section { 193 | padding: 0 32px; 194 | border-bottom: 1px solid #ddd; } 195 | 196 | .section-content { 197 | max-width: 834px; 198 | margin: 0 auto; 199 | padding: 16px 0; } 200 | 201 | .section-name { 202 | color: #666; 203 | display: block; } 204 | 205 | .declaration .highlight { 206 | overflow-x: initial; 207 | padding: 8px 0; 208 | margin: 0; 209 | background-color: transparent; 210 | border: none; } 211 | 212 | .task-group-section { 213 | border-top: 1px solid #ddd; } 214 | 215 | .task-group { 216 | padding-top: 0px; } 217 | 218 | .task-name-container a[name]:before { 219 | content: ""; 220 | display: block; } 221 | 222 | .item-container { 223 | padding: 0; } 224 | 225 | .item { 226 | padding-top: 8px; 227 | width: 100%; 228 | list-style-type: none; } 229 | .item a[name]:before { 230 | content: ""; 231 | display: block; } 232 | .item .token, .item .direct-link { 233 | padding-left: 3px; 234 | margin-left: 0px; 235 | font-size: 1rem; } 236 | .item .declaration-note { 237 | font-size: .85em; 238 | color: #808080; 239 | font-style: italic; } 240 | 241 | .pointer-container { 242 | border-bottom: 1px solid #ddd; 243 | left: -23px; 244 | padding-bottom: 13px; 245 | position: relative; 246 | width: 110%; } 247 | 248 | .pointer { 249 | left: 21px; 250 | top: 7px; 251 | display: block; 252 | position: absolute; 253 | width: 12px; 254 | height: 12px; 255 | border-left: 1px solid #ddd; 256 | border-top: 1px solid #ddd; 257 | background: #fff; 258 | transform: rotate(45deg); } 259 | 260 | .height-container { 261 | display: none; 262 | position: relative; 263 | width: 100%; 264 | overflow: hidden; } 265 | .height-container .section { 266 | background: #fff; 267 | border: 1px solid #ddd; 268 | border-top-width: 0; 269 | padding-top: 10px; 270 | padding-bottom: 5px; 271 | padding: 8px 16px; } 272 | 273 | .aside, .language { 274 | padding: 6px 12px; 275 | margin: 12px 0; 276 | border-left: 5px solid #dddddd; 277 | overflow-y: hidden; } 278 | .aside .aside-title, .language .aside-title { 279 | font-size: 9px; 280 | letter-spacing: 2px; 281 | text-transform: uppercase; 282 | padding-bottom: 0; 283 | margin: 0; 284 | color: #aaa; 285 | -webkit-user-select: none; } 286 | .aside p:last-child, .language p:last-child { 287 | margin-bottom: 0; } 288 | 289 | .language { 290 | border-left: 5px solid #cde9f4; } 291 | .language .aside-title { 292 | color: #4183c4; } 293 | 294 | .aside-warning, .aside-deprecated, .aside-unavailable { 295 | border-left: 5px solid #ff6666; } 296 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { 297 | color: #ff0000; } 298 | 299 | .graybox { 300 | border-collapse: collapse; 301 | width: 100%; } 302 | .graybox p { 303 | margin: 0; 304 | word-break: break-word; 305 | min-width: 50px; } 306 | .graybox td { 307 | border: 1px solid #ddd; 308 | padding: 5px 25px 5px 10px; 309 | vertical-align: middle; } 310 | .graybox tr td:first-of-type { 311 | text-align: right; 312 | padding: 7px; 313 | vertical-align: top; 314 | word-break: normal; 315 | width: 40px; } 316 | 317 | .slightly-smaller { 318 | font-size: 0.9em; } 319 | 320 | .footer { 321 | padding: 8px 16px; 322 | background: #444; 323 | color: #ddd; 324 | font-size: 0.8em; } 325 | .footer p { 326 | margin: 8px 0; } 327 | .footer a { 328 | color: #fff; } 329 | 330 | html.dash .header, html.dash .breadcrumbs, html.dash .navigation { 331 | display: none; } 332 | html.dash .height-container { 333 | display: block; } 334 | 335 | form[role=search] input { 336 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; 337 | font-size: 14px; 338 | line-height: 24px; 339 | padding: 0 10px; 340 | margin: 0; 341 | border: none; 342 | border-radius: 1em; } 343 | .loading form[role=search] input { 344 | background: white url(../img/spinner.gif) center right 4px no-repeat; } 345 | form[role=search] .tt-menu { 346 | margin: 0; 347 | min-width: 300px; 348 | background: #fbfbfb; 349 | color: #333; 350 | border: 1px solid #ddd; } 351 | form[role=search] .tt-highlight { 352 | font-weight: bold; } 353 | form[role=search] .tt-suggestion { 354 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; 355 | padding: 0 8px; } 356 | form[role=search] .tt-suggestion span { 357 | display: table-cell; 358 | white-space: nowrap; } 359 | form[role=search] .tt-suggestion .doc-parent-name { 360 | width: 100%; 361 | text-align: right; 362 | font-weight: normal; 363 | font-size: 0.9em; 364 | padding-left: 16px; } 365 | form[role=search] .tt-suggestion:hover, 366 | form[role=search] .tt-suggestion.tt-cursor { 367 | cursor: pointer; 368 | background-color: #4183c4; 369 | color: #fff; } 370 | form[role=search] .tt-suggestion:hover .doc-parent-name, 371 | form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { 372 | color: #fff; } 373 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/carat.png -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/dash.png -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/gh.png -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/img/spinner.gif -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LoggingFormatAndPipe Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |

22 | 23 | LoggingFormatAndPipe Docs 24 | 25 | (100% documented) 26 |

27 | 28 |

29 |

30 | 31 |
32 |

33 | 34 |

35 | 36 | 37 | View on GitHub 38 | 39 |

40 | 41 |
42 | 43 | 48 | 49 |
50 | 90 |
91 | 92 |
93 |
94 | 95 |

LoggingFormatAndPipe

96 | 97 |

LoggingFormatAndPipe provides a Swift Logging API Handler which allows you to customized both your log messages’ formats as well as their destinations.

98 | 99 |

If you don’t like the default log format change it to one you would like. If you want one destination to be formatted differently than your other destination you can with ease. Or send the same format to multiple destinations!

100 | 101 |

102 | Installation | Getting Started | Documentation 103 |

104 |

Installation

105 |

SwiftPM

106 | 107 |

To use the LoggingFormatAndPipe library in your project add the following in your Package.swift:

108 |
.package(url: "https://github.com/adorkable/swift-log-format-and-pipe.git", .from("0.1.2")),
109 | 
110 |

Getting Started

111 | 112 |

LoggingFormatAndPipe.Handler expects both a Formatter and a Pipe

113 |
let logger = Logger(label: "example") { _ in 
114 |     return LoggingFormatAndPipe.Handler(
115 |         formatter: ...,
116 |         pipe: ...
117 |     )
118 | }
119 | 
120 | 121 |

Example:

122 |
let logger = Logger(label: "example") { _ in 
123 |     return LoggingFormatAndPipe.Handler(
124 |         formatter: BasicFormatter.adorkable,
125 |         pipe: LoggerTextOutputStreamPipe.standardOutput
126 |     )
127 | }
128 | 
129 |

Formatting

130 | 131 |

There are a number of ways of customizing the format but are generally composed of a combination of LogComponents:

132 | 133 |
    134 |
  • .timestamp - Timestamp of log
  • 135 |
  • .level - Log level
  • 136 |
  • .message - The actual message
  • 137 |
  • .metadata - Log metadata
  • 138 |
  • .file - The log’s originating file
  • 139 |
  • .line - The log’s originating line number in the file
  • 140 |
  • .function - The log’s originating function
  • 141 |
  • .text(String) - Static text
  • 142 |
  • .group([LogComponents]) - Formatters may separate specified LogComponents in various ways as per their format, .group tells the Formatter to combine the LogComponents without using its separation
  • 143 |
144 |

BasicFormatter

145 | 146 |

BasicFormatter allows you to specify a sequence of LogComponents and a separator string and automatically processes them into a single line for each new log message.

147 | 148 |

It includes already setup static instances:

149 | 150 | 153 | 154 |

{timestamp} {level}: {message}

155 | 156 |

Example:

157 | 158 |

2019-07-30T13:49:07-0400 error: Test error message

159 | 160 |
    161 |
  • .adorkable - Adorkable’s standard format 😘
  • 162 |
163 | 164 |

{timestamp} ▶ {level} ▶ {file}:{line} ▶ {function} ▶ {message} ▶ {metadata}

165 | 166 |

Example:

167 | 168 |

2019-07-30T13:49:07-0400 ▶ error ▶ /asdf/swift-log-format-and-pipe/Tests/LoggingFormatAndPipeTests/FormatterTests.swift:25 ▶ testFormatter(_:) ▶ Test error message

169 |

Customizing a BasicFormatter

170 | 171 |

If none of these work you can customize your own instance!

172 | 173 |

Suppose you want a special short log format with a timestamp, the level, the file it originated in, and the message itself:

174 |
let myFormat = BasicFormatter(
175 |     [
176 |         .timestamp, 
177 |         .level,
178 |         .file,
179 |         .message
180 |     ]
181 | )
182 | 
183 | 184 |

To change the separator from a single space specify the separator parameter:

185 |
let myFormat = BasicFormatter(
186 |     ...,
187 |     separator: "|"
188 | )
189 | 
190 | 191 |

Note that BasicFormatter will not add an empty string and separator for a nil metadata.

192 | 193 |

To change the timestamp from the default:

194 |
let myDateFormat = DateFormatter()
195 | myDateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
196 | let myFormat = BasicFormatter(
197 |     ...,
198 |     timestampFormatter: myDateFormat
199 | )
200 | 
201 |

Implementing Formatter

202 | 203 |

You can also create your own Formatter conforming object by implementing:

204 | 205 |
    206 |
  • var timestampFormatter: DateFormatter { get }
  • 207 |
  • func processLog(level: Logger.Level, 208 | message: Logger.Message, 209 | prettyMetadata: String?, 210 | file: String, function: String, line: UInt) -> String
  • 211 |
212 | 213 |

More formatters to come!

214 |

Piping

215 | 216 |

Pipes specify where your formatted log lines end up going to. Included already are:

217 | 218 | 222 | 223 |

More pipes to come!

224 |

Implementing Pipe

225 | 226 |

You can also create your own Pipe conforming object by implementing:

227 | 228 |
    229 |
  • func handle(_ formattedLogLine: String)
  • 230 |
231 | 232 |

Easy!

233 | 234 |

Now you’ve got your use-case formatted log lines traveling this way and then, what a charm 🖤

235 |

API Documentation

236 | 237 |

For more insight into the library API documentation is found in the repo here

238 | 239 |
240 |
241 | 242 | 243 |
244 |
245 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | $content = link.parent().parent().next(); 27 | $content.slideToggle(animationDuration); 28 | 29 | // Keeps the document from jumping to the hash. 30 | var href = $(this).attr('href'); 31 | if (history.pushState) { 32 | history.pushState({}, '', href); 33 | } else { 34 | location.hash = href; 35 | } 36 | event.preventDefault(); 37 | }); 38 | 39 | // Dumb down quotes within code blocks that delimit strings instead of quotations 40 | // https://github.com/realm/jazzy/issues/714 41 | $("code q").replaceWith(function () { 42 | return ["\"", $(this).contents(), "\""]; 43 | }); 44 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/js/jazzy.search.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | var searchIndex = lunr(function() { 3 | this.ref('url'); 4 | this.field('name'); 5 | this.field('abstract'); 6 | }); 7 | 8 | var $typeahead = $('[data-typeahead]'); 9 | var $form = $typeahead.parents('form'); 10 | var searchURL = $form.attr('action'); 11 | 12 | function displayTemplate(result) { 13 | return result.name; 14 | } 15 | 16 | function suggestionTemplate(result) { 17 | var t = '
'; 18 | t += '' + result.name + ''; 19 | if (result.parent_name) { 20 | t += '' + result.parent_name + ''; 21 | } 22 | t += '
'; 23 | return t; 24 | } 25 | 26 | $typeahead.one('focus', function() { 27 | $form.addClass('loading'); 28 | 29 | $.getJSON(searchURL).then(function(searchData) { 30 | $.each(searchData, function (url, doc) { 31 | searchIndex.add({url: url, name: doc.name, abstract: doc.abstract}); 32 | }); 33 | 34 | $typeahead.typeahead( 35 | { 36 | highlight: true, 37 | minLength: 3 38 | }, 39 | { 40 | limit: 10, 41 | display: displayTemplate, 42 | templates: { suggestion: suggestionTemplate }, 43 | source: function(query, sync) { 44 | var results = searchIndex.search(query).map(function(result) { 45 | var doc = searchData[result.ref]; 46 | doc.url = result.ref; 47 | return doc; 48 | }); 49 | sync(results); 50 | } 51 | } 52 | ); 53 | $form.removeClass('loading'); 54 | $typeahead.trigger('focus'); 55 | }); 56 | }); 57 | 58 | var baseURL = searchURL.slice(0, -"search.json".length); 59 | 60 | $typeahead.on('typeahead:select', function(e, result) { 61 | window.location = baseURL + result.url; 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/Documents/search.json: -------------------------------------------------------------------------------- 1 | {"Structs/StdioOutputStream.html#/s:20LoggingFormatAndPipe17StdioOutputStreamV4fileSpySo7__sFILEVGvp":{"name":"file","abstract":"

File handler we’re writing to

","parent_name":"StdioOutputStream"},"Structs/StdioOutputStream.html#/s:20LoggingFormatAndPipe17StdioOutputStreamV5writeyySSF":{"name":"write(_:)","abstract":"

Write to file

","parent_name":"StdioOutputStream"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0VyACs0fgH0_pcfc":{"name":"init(_:)","abstract":"

Default init

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0V6handleyySSF":{"name":"handle(_:)","abstract":"

Our main log handling pipe method

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0V08standardG0ACvpZ":{"name":"standardOutput","abstract":"

Pipe logs to Standard Output (stdout)

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0V13standardErrorACvpZ":{"name":"standardError","abstract":"

Pipe logs to Standard Error (stderr)

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV9formatter4pipeAcA9Formatter_p_AA0D0_ptcfc":{"name":"init(formatter:pipe:)","abstract":"

Default init

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV9formatterAA9Formatter_pvp":{"name":"formatter","abstract":"

Formatter we’re formatting with

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV4pipeAA0D0_pvp":{"name":"pipe","abstract":"

PIpe we’re piping to

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV8logLevel0A06LoggerV0G0Ovp":{"name":"logLevel","abstract":"

Log level specification, used by Logger to filter all log levels less severe then the specified

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV3log5level7message8metadata4file8function4liney0A06LoggerV5LevelO_AM7MessageVSDySSAM13MetadataValueOGSgS2SSutF":{"name":"log(level:message:metadata:file:function:line:)","abstract":"

Our main Logging Backend method

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV8metadataSDySS0A06LoggerV13MetadataValueOGvp":{"name":"metadata","abstract":"

Our Logging Backend metadata

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV11metadataKey0A06LoggerV13MetadataValueOSgSS_tcip":{"name":"subscript(metadataKey:)","abstract":"

Add, remove, or change the logging metadata.

","parent_name":"Handler"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV6formatSayAA12LogComponentOGvp":{"name":"format","abstract":"

Log format sequential specification

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV9separatorSSSgvp":{"name":"separator","abstract":"

Log component separator

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV09timestampF0So06NSDateF0Cvp":{"name":"timestampFormatter","abstract":"

Log timestamp component formatter

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV09timestampF0So06NSDateF0CvpZ":{"name":"timestampFormatter","abstract":"

Default timestamp component formatter

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV_9separator09timestampF0ACSayAA12LogComponentOG_SSSo06NSDateF0Ctcfc":{"name":"init(_:separator:timestampFormatter:)","abstract":"

Default init

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV10processLog5level7message14prettyMetadata4file8function4lineSS0A06LoggerV5LevelO_AM7MessageVSSSgS2SSutF":{"name":"processLog(level:message:prettyMetadata:file:function:line:)","abstract":"

Our main log formatting method

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV5appleACvpZ":{"name":"apple","abstract":"

apple/swift-log‘s log format

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV9adorkableACvpZ":{"name":"adorkable","abstract":"

Adorkable’s go-to log format 😘

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html":{"name":"BasicFormatter","abstract":"

Your basic, customizable log formatter"},"Structs/Handler.html":{"name":"Handler","abstract":"

Logging Format and Pipe’s Logging Backend

"},"Structs/LoggerTextOutputStreamPipe.html":{"name":"LoggerTextOutputStreamPipe","abstract":"

A pipe for sending logs to a TextOutputStream

"},"Structs/StdioOutputStream.html":{"name":"StdioOutputStream","abstract":"

Copied from swift-log:Logging.swift until it is made public"},"Protocols/Pipe.html#/s:20LoggingFormatAndPipe0D0P6handleyySSF":{"name":"handle(_:)","abstract":"

Pipe’s chance to send a formatted line where it deems

","parent_name":"Pipe"},"Protocols/Formatter.html#/s:20LoggingFormatAndPipe9FormatterP09timestampE0So06NSDateE0Cvp":{"name":"timestampFormatter","abstract":"

Timestamp formatter

","parent_name":"Formatter"},"Protocols/Formatter.html#/s:20LoggingFormatAndPipe9FormatterP10processLog5level7message14prettyMetadata4file8function4lineSS0A06LoggerV5LevelO_AM7MessageVSSSgS2SSutF":{"name":"processLog(level:message:prettyMetadata:file:function:line:)","abstract":"

Formatter’s chance to format the log

","parent_name":"Formatter"},"Protocols/Formatter.html#/s:20LoggingFormatAndPipe9FormatterPAAE16processComponent_3now5level7message14prettyMetadata4file8function4lineSSAA03LogG0O_10Foundation4DateV0A06LoggerV5LevelOAS7MessageVSSSgS2SSutF":{"name":"processComponent(_:now:level:message:prettyMetadata:file:function:line:)","abstract":"

Common usage component formatter

","parent_name":"Formatter"},"Protocols/Formatter.html":{"name":"Formatter","abstract":"

Log Formatter

"},"Protocols/Pipe.html":{"name":"Pipe","abstract":"

Log PIpe

"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO9timestampyA2CmF":{"name":"timestamp","abstract":"

Timestamp of log","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO5levelyA2CmF":{"name":"level","abstract":"

Log level

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO7messageyA2CmF":{"name":"message","abstract":"

The actual message

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO8metadatayA2CmF":{"name":"metadata","abstract":"

Log metadata

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO4fileyA2CmF":{"name":"file","abstract":"

The log’s originating file

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO8functionyA2CmF":{"name":"function","abstract":"

The log’s originating function

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO4lineyA2CmF":{"name":"line","abstract":"

The log’s originating line number

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO4textyACSScACmF":{"name":"text(_:)","abstract":"

Literal text

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO5groupyACSayACGcACmF":{"name":"group(_:)","abstract":"

A group of LogComponents, not using the specified separator

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO20allNonmetaComponentsSayACGvpZ":{"name":"allNonmetaComponents","abstract":"

All basic log format component types

","parent_name":"LogComponent"},"Enums/LogComponent.html":{"name":"LogComponent","abstract":"

Possible log format components

"},"Enums.html":{"name":"Enumerations","abstract":"

The following enumerations are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"},"Structs.html":{"name":"Structures","abstract":"

The following structures are available globally.

"}} -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/docsets/LoggingFormatAndPipe.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /docs/docsets/LoggingFormatAndPipe.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/docsets/LoggingFormatAndPipe.tgz -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/img/dash.png -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/img/gh.png -------------------------------------------------------------------------------- /docs/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/swift-log-format-and-pipe/aa23b8bebf2c060ac0194715a6ed5c9af5f2d8bf/docs/img/spinner.gif -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LoggingFormatAndPipe Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |

22 | 23 | LoggingFormatAndPipe Docs 24 | 25 | (100% documented) 26 |

27 | 28 |

29 |

30 | 31 |
32 |

33 | 34 |

35 | 36 | 37 | View on GitHub 38 | 39 |

40 | 41 |
42 | 43 | 48 | 49 |
50 | 90 |
91 | 92 |
93 |
94 | 95 |

LoggingFormatAndPipe

96 | 97 |

LoggingFormatAndPipe provides a Swift Logging API Handler which allows you to customized both your log messages’ formats as well as their destinations.

98 | 99 |

If you don’t like the default log format change it to one you would like. If you want one destination to be formatted differently than your other destination you can with ease. Or send the same format to multiple destinations!

100 | 101 |

102 | Installation | Getting Started | Documentation 103 |

104 |

Installation

105 |

SwiftPM

106 | 107 |

To use the LoggingFormatAndPipe library in your project add the following in your Package.swift:

108 |
.package(url: "https://github.com/adorkable/swift-log-format-and-pipe.git", .from("0.1.2")),
109 | 
110 |

Getting Started

111 | 112 |

LoggingFormatAndPipe.Handler expects both a Formatter and a Pipe

113 |
let logger = Logger(label: "example") { _ in 
114 |     return LoggingFormatAndPipe.Handler(
115 |         formatter: ...,
116 |         pipe: ...
117 |     )
118 | }
119 | 
120 | 121 |

Example:

122 |
let logger = Logger(label: "example") { _ in 
123 |     return LoggingFormatAndPipe.Handler(
124 |         formatter: BasicFormatter.adorkable,
125 |         pipe: LoggerTextOutputStreamPipe.standardOutput
126 |     )
127 | }
128 | 
129 |

Formatting

130 | 131 |

There are a number of ways of customizing the format but are generally composed of a combination of LogComponents:

132 | 133 |
    134 |
  • .timestamp - Timestamp of log
  • 135 |
  • .level - Log level
  • 136 |
  • .message - The actual message
  • 137 |
  • .metadata - Log metadata
  • 138 |
  • .file - The log’s originating file
  • 139 |
  • .line - The log’s originating line number in the file
  • 140 |
  • .function - The log’s originating function
  • 141 |
  • .text(String) - Static text
  • 142 |
  • .group([LogComponents]) - Formatters may separate specified LogComponents in various ways as per their format, .group tells the Formatter to combine the LogComponents without using its separation
  • 143 |
144 |

BasicFormatter

145 | 146 |

BasicFormatter allows you to specify a sequence of LogComponents and a separator string and automatically processes them into a single line for each new log message.

147 | 148 |

It includes already setup static instances:

149 | 150 | 153 | 154 |

{timestamp} {level}: {message}

155 | 156 |

Example:

157 | 158 |

2019-07-30T13:49:07-0400 error: Test error message

159 | 160 |
    161 |
  • .adorkable - Adorkable’s standard format 😘
  • 162 |
163 | 164 |

{timestamp} ▶ {level} ▶ {file}:{line} ▶ {function} ▶ {message} ▶ {metadata}

165 | 166 |

Example:

167 | 168 |

2019-07-30T13:49:07-0400 ▶ error ▶ /asdf/swift-log-format-and-pipe/Tests/LoggingFormatAndPipeTests/FormatterTests.swift:25 ▶ testFormatter(_:) ▶ Test error message

169 |

Customizing a BasicFormatter

170 | 171 |

If none of these work you can customize your own instance!

172 | 173 |

Suppose you want a special short log format with a timestamp, the level, the file it originated in, and the message itself:

174 |
let myFormat = BasicFormatter(
175 |     [
176 |         .timestamp, 
177 |         .level,
178 |         .file,
179 |         .message
180 |     ]
181 | )
182 | 
183 | 184 |

To change the separator from a single space specify the separator parameter:

185 |
let myFormat = BasicFormatter(
186 |     ...,
187 |     separator: "|"
188 | )
189 | 
190 | 191 |

Note that BasicFormatter will not add an empty string and separator for a nil metadata.

192 | 193 |

To change the timestamp from the default:

194 |
let myDateFormat = DateFormatter()
195 | myDateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
196 | let myFormat = BasicFormatter(
197 |     ...,
198 |     timestampFormatter: myDateFormat
199 | )
200 | 
201 |

Implementing Formatter

202 | 203 |

You can also create your own Formatter conforming object by implementing:

204 | 205 |
    206 |
  • var timestampFormatter: DateFormatter { get }
  • 207 |
  • func processLog(level: Logger.Level, 208 | message: Logger.Message, 209 | prettyMetadata: String?, 210 | file: String, function: String, line: UInt) -> String
  • 211 |
212 | 213 |

More formatters to come!

214 |

Piping

215 | 216 |

Pipes specify where your formatted log lines end up going to. Included already are:

217 | 218 | 222 | 223 |

More pipes to come!

224 |

Implementing Pipe

225 | 226 |

You can also create your own Pipe conforming object by implementing:

227 | 228 |
    229 |
  • func handle(_ formattedLogLine: String)
  • 230 |
231 | 232 |

Easy!

233 | 234 |

Now you’ve got your use-case formatted log lines traveling this way and then, what a charm 🖤

235 |

API Documentation

236 | 237 |

For more insight into the library API documentation is found in the repo here

238 | 239 |
240 |
241 | 242 | 243 |
244 |
245 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /docs/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | $content = link.parent().parent().next(); 27 | $content.slideToggle(animationDuration); 28 | 29 | // Keeps the document from jumping to the hash. 30 | var href = $(this).attr('href'); 31 | if (history.pushState) { 32 | history.pushState({}, '', href); 33 | } else { 34 | location.hash = href; 35 | } 36 | event.preventDefault(); 37 | }); 38 | 39 | // Dumb down quotes within code blocks that delimit strings instead of quotations 40 | // https://github.com/realm/jazzy/issues/714 41 | $("code q").replaceWith(function () { 42 | return ["\"", $(this).contents(), "\""]; 43 | }); 44 | -------------------------------------------------------------------------------- /docs/js/jazzy.search.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | var searchIndex = lunr(function() { 3 | this.ref('url'); 4 | this.field('name'); 5 | this.field('abstract'); 6 | }); 7 | 8 | var $typeahead = $('[data-typeahead]'); 9 | var $form = $typeahead.parents('form'); 10 | var searchURL = $form.attr('action'); 11 | 12 | function displayTemplate(result) { 13 | return result.name; 14 | } 15 | 16 | function suggestionTemplate(result) { 17 | var t = '
'; 18 | t += '' + result.name + ''; 19 | if (result.parent_name) { 20 | t += '' + result.parent_name + ''; 21 | } 22 | t += '
'; 23 | return t; 24 | } 25 | 26 | $typeahead.one('focus', function() { 27 | $form.addClass('loading'); 28 | 29 | $.getJSON(searchURL).then(function(searchData) { 30 | $.each(searchData, function (url, doc) { 31 | searchIndex.add({url: url, name: doc.name, abstract: doc.abstract}); 32 | }); 33 | 34 | $typeahead.typeahead( 35 | { 36 | highlight: true, 37 | minLength: 3 38 | }, 39 | { 40 | limit: 10, 41 | display: displayTemplate, 42 | templates: { suggestion: suggestionTemplate }, 43 | source: function(query, sync) { 44 | var results = searchIndex.search(query).map(function(result) { 45 | var doc = searchData[result.ref]; 46 | doc.url = result.ref; 47 | return doc; 48 | }); 49 | sync(results); 50 | } 51 | } 52 | ); 53 | $form.removeClass('loading'); 54 | $typeahead.trigger('focus'); 55 | }); 56 | }); 57 | 58 | var baseURL = searchURL.slice(0, -"search.json".length); 59 | 60 | $typeahead.on('typeahead:select', function(e, result) { 61 | window.location = baseURL + result.url; 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /docs/search.json: -------------------------------------------------------------------------------- 1 | {"Structs/StdioOutputStream.html#/s:20LoggingFormatAndPipe17StdioOutputStreamV4fileSpySo7__sFILEVGvp":{"name":"file","abstract":"

File handler we’re writing to

","parent_name":"StdioOutputStream"},"Structs/StdioOutputStream.html#/s:20LoggingFormatAndPipe17StdioOutputStreamV5writeyySSF":{"name":"write(_:)","abstract":"

Write to file

","parent_name":"StdioOutputStream"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0VyACs0fgH0_pcfc":{"name":"init(_:)","abstract":"

Default init

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0V6handleyySSF":{"name":"handle(_:)","abstract":"

Our main log handling pipe method

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0V08standardG0ACvpZ":{"name":"standardOutput","abstract":"

Pipe logs to Standard Output (stdout)

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/LoggerTextOutputStreamPipe.html#/s:20LoggingFormatAndPipe022LoggerTextOutputStreamD0V13standardErrorACvpZ":{"name":"standardError","abstract":"

Pipe logs to Standard Error (stderr)

","parent_name":"LoggerTextOutputStreamPipe"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV9formatter4pipeAcA9Formatter_p_AA0D0_ptcfc":{"name":"init(formatter:pipe:)","abstract":"

Default init

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV9formatterAA9Formatter_pvp":{"name":"formatter","abstract":"

Formatter we’re formatting with

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV4pipeAA0D0_pvp":{"name":"pipe","abstract":"

PIpe we’re piping to

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV8logLevel0A06LoggerV0G0Ovp":{"name":"logLevel","abstract":"

Log level specification, used by Logger to filter all log levels less severe then the specified

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV3log5level7message8metadata4file8function4liney0A06LoggerV5LevelO_AM7MessageVSDySSAM13MetadataValueOGSgS2SSutF":{"name":"log(level:message:metadata:file:function:line:)","abstract":"

Our main Logging Backend method

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV8metadataSDySS0A06LoggerV13MetadataValueOGvp":{"name":"metadata","abstract":"

Our Logging Backend metadata

","parent_name":"Handler"},"Structs/Handler.html#/s:20LoggingFormatAndPipe7HandlerV11metadataKey0A06LoggerV13MetadataValueOSgSS_tcip":{"name":"subscript(metadataKey:)","abstract":"

Add, remove, or change the logging metadata.

","parent_name":"Handler"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV6formatSayAA12LogComponentOGvp":{"name":"format","abstract":"

Log format sequential specification

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV9separatorSSSgvp":{"name":"separator","abstract":"

Log component separator

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV09timestampF0So06NSDateF0Cvp":{"name":"timestampFormatter","abstract":"

Log timestamp component formatter

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV09timestampF0So06NSDateF0CvpZ":{"name":"timestampFormatter","abstract":"

Default timestamp component formatter

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV_9separator09timestampF0ACSayAA12LogComponentOG_SSSo06NSDateF0Ctcfc":{"name":"init(_:separator:timestampFormatter:)","abstract":"

Default init

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV10processLog5level7message14prettyMetadata4file8function4lineSS0A06LoggerV5LevelO_AM7MessageVSSSgS2SSutF":{"name":"processLog(level:message:prettyMetadata:file:function:line:)","abstract":"

Our main log formatting method

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV5appleACvpZ":{"name":"apple","abstract":"

apple/swift-log‘s log format

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html#/s:20LoggingFormatAndPipe14BasicFormatterV9adorkableACvpZ":{"name":"adorkable","abstract":"

Adorkable’s go-to log format 😘

","parent_name":"BasicFormatter"},"Structs/BasicFormatter.html":{"name":"BasicFormatter","abstract":"

Your basic, customizable log formatter"},"Structs/Handler.html":{"name":"Handler","abstract":"

Logging Format and Pipe’s Logging Backend

"},"Structs/LoggerTextOutputStreamPipe.html":{"name":"LoggerTextOutputStreamPipe","abstract":"

A pipe for sending logs to a TextOutputStream

"},"Structs/StdioOutputStream.html":{"name":"StdioOutputStream","abstract":"

Copied from swift-log:Logging.swift until it is made public"},"Protocols/Pipe.html#/s:20LoggingFormatAndPipe0D0P6handleyySSF":{"name":"handle(_:)","abstract":"

Pipe’s chance to send a formatted line where it deems

","parent_name":"Pipe"},"Protocols/Formatter.html#/s:20LoggingFormatAndPipe9FormatterP09timestampE0So06NSDateE0Cvp":{"name":"timestampFormatter","abstract":"

Timestamp formatter

","parent_name":"Formatter"},"Protocols/Formatter.html#/s:20LoggingFormatAndPipe9FormatterP10processLog5level7message14prettyMetadata4file8function4lineSS0A06LoggerV5LevelO_AM7MessageVSSSgS2SSutF":{"name":"processLog(level:message:prettyMetadata:file:function:line:)","abstract":"

Formatter’s chance to format the log

","parent_name":"Formatter"},"Protocols/Formatter.html#/s:20LoggingFormatAndPipe9FormatterPAAE16processComponent_3now5level7message14prettyMetadata4file8function4lineSSAA03LogG0O_10Foundation4DateV0A06LoggerV5LevelOAS7MessageVSSSgS2SSutF":{"name":"processComponent(_:now:level:message:prettyMetadata:file:function:line:)","abstract":"

Common usage component formatter

","parent_name":"Formatter"},"Protocols/Formatter.html":{"name":"Formatter","abstract":"

Log Formatter

"},"Protocols/Pipe.html":{"name":"Pipe","abstract":"

Log PIpe

"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO9timestampyA2CmF":{"name":"timestamp","abstract":"

Timestamp of log","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO5levelyA2CmF":{"name":"level","abstract":"

Log level

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO7messageyA2CmF":{"name":"message","abstract":"

The actual message

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO8metadatayA2CmF":{"name":"metadata","abstract":"

Log metadata

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO4fileyA2CmF":{"name":"file","abstract":"

The log’s originating file

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO8functionyA2CmF":{"name":"function","abstract":"

The log’s originating function

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO4lineyA2CmF":{"name":"line","abstract":"

The log’s originating line number

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO4textyACSScACmF":{"name":"text(_:)","abstract":"

Literal text

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO5groupyACSayACGcACmF":{"name":"group(_:)","abstract":"

A group of LogComponents, not using the specified separator

","parent_name":"LogComponent"},"Enums/LogComponent.html#/s:20LoggingFormatAndPipe12LogComponentO20allNonmetaComponentsSayACGvpZ":{"name":"allNonmetaComponents","abstract":"

All basic log format component types

","parent_name":"LogComponent"},"Enums/LogComponent.html":{"name":"LogComponent","abstract":"

Possible log format components

"},"Enums.html":{"name":"Enumerations","abstract":"

The following enumerations are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"},"Structs.html":{"name":"Structures","abstract":"

The following structures are available globally.

"}} -------------------------------------------------------------------------------- /docs/undocumented.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": [ 3 | 4 | ], 5 | "source_directory": "/Users/ian/Documents/Adorkable/swift-log-format-and-pipe" 6 | } -------------------------------------------------------------------------------- /updateDocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # TODO: test for sourcekitten and jazzy, recommend installation 4 | sourcekitten doc --spm-module LoggingFormatAndPipe > LoggingFormatAndPipeSourceKitten.json 5 | jazzy --clean --sourcekitten-sourcefile LoggingFormatAndPipeSourceKitten.json 6 | rm LoggingFormatAndPipeSourceKitten.json 7 | --------------------------------------------------------------------------------