diff --git a/Extras/Examples/CommandLineExample/LICENSE b/Extras/Examples/CommandLineExample/LICENSE new file mode 100644 index 0000000..8263bf8 --- /dev/null +++ b/Extras/Examples/CommandLineExample/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Elegant Chaos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Extras/Examples/CommandLineExample/Package.resolved b/Extras/Examples/CommandLineExample/Package.resolved new file mode 100644 index 0000000..8dc99f0 --- /dev/null +++ b/Extras/Examples/CommandLineExample/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Logger", + "repositoryURL": "/Users/developer/Developer/Projects/Logger", + "state": { + "branch": "main", + "revision": "6375bbc118d0ee0633de5e74797bf2f4cf2ac0af", + "version": null + } + } + ] + }, + "version": 1 +} diff --git a/Extras/Examples/CommandLineExample/Package.swift b/Extras/Examples/CommandLineExample/Package.swift new file mode 100644 index 0000000..21d6a4f --- /dev/null +++ b/Extras/Examples/CommandLineExample/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version:5.0 + +import PackageDescription + +let package = Package( + name: "LoggerExample", + platforms: [ + .macOS(.v10_13), .iOS(.v12), .tvOS(.v12), .watchOS(.v5) + ], + products: [ + .executable( + name: "Example", + targets: ["Example"]) + ], + dependencies: [ + .package(url: "../../..", .branch("main")) + ], + targets: [ + .target( + name: "Example", + dependencies: ["Logger"]) + ] + ) diff --git a/Extras/Examples/CommandLineExample/README.md b/Extras/Examples/CommandLineExample/README.md new file mode 100644 index 0000000..34c1286 --- /dev/null +++ b/Extras/Examples/CommandLineExample/README.md @@ -0,0 +1,110 @@ +[comment]: <> (Header Generated by ActionStatus 1.0.2 - 351) + +[![Test results][tests shield]][actions] [![Latest release][release shield]][releases] [![swift 5.0 shield] ![swift dev shield]][swift] ![Platforms: macOS, iOS, tvOS, watchOS, Linux][platforms shield] + +[release shield]: https://img.shields.io/github/v/release/elegantchaos/Logger +[platforms shield]: https://img.shields.io/badge/platforms-macOS_iOS_tvOS_watchOS_Linux-lightgrey.svg?style=flat "macOS, iOS, tvOS, watchOS, Linux" +[tests shield]: https://github.com/elegantchaos/Logger/workflows/tests/badge.svg +[swift 5.0 shield]: https://img.shields.io/badge/swift-5.0-F05138.svg "Swift 5.0" +[swift dev shield]: https://img.shields.io/badge/swift-dev-F05138.svg "Swift dev" + +[swift]: https://swift.org +[releases]: https://github.com/elegantchaos/Logger/releases +[actions]: https://github.com/elegantchaos/Logger/actions + +[comment]: <> (End of ActionStatus Header) + +# Logger + +Configurable logging for Swift. + +Declare multiple log channels. +Send log messages and objects to them. +Enable individual channels with minimal overhead for the disabled ones. + +### Basic Usage + +Just import the module and make one or more channels. + +```swift + +import Logger + +let logger = Channel("com.acme.example.main") +let detailLogger = Channel("com.acme.example.detail") +```` + +To log output, just write it to a channel. Different kinds or levels of info can go to different channels as required: + +```swift +logger.log("Hello world!") +detailLogger.log("We just logged hello world in the main channel") +``` + +To log for debug builds only: + +```swift +logger.debug("This will never show up in a release build") +``` + +### Configuration + +The list of enabled channels is persistent between runs of your program, and all channels start disabled by default. + +You can enable specific channels from the command line when you run: + +``` +.build/debug/Example -logs "+myChannel,+anotherChannel" +``` + + +You can also disable channels: + +``` +.build/debug/Example -logs "-myChannel,-anotherChannel" +``` + +Or completely reset the list of enabled channels: + +``` +.build/debug/Example -logs "=someChannel,someOtherChannel" +``` + + + + + +### Discussion + +This is a swift version of a pattern I've implemented [a number of times before](http://elegantchaos.com/2011/11/16/eclogging-better-logging-for-objective-c). I often use it as a kind of test project to learn a language with, but I also use the library functionality in pretty much everything that I do. + +The main idea is that when debugging complex problems, it's often useful to be able to write extensive logging code. + +It's healthy to be able to leave this code in place, but enable it only when needed. It's useful to be able to do this at runtime, sometimes even in release versions, without disabled logging code having a negative performance impact. + +For this to scale to a large application with many subsystems, you need to be able to separate log output into functional areas, so that you can look only at the bit you're interested in. + +Additional features and/or motivations: + +- enabling/disabling channels persistently or at runtime +- logging to console, disk, the network, or anywhere else +- auto-generatating an interface for runtime configuration +- being able to keep some logging in a final release, but dissolve other debug-only stuff away + +#### This Version + +Motto for this version: *less is more*. + +The implementation of [ECLogging](https://github.com/elegantchaos/ECLogging) started getting a bit gnarly. + +This aims to be a stripped down version with just the essentials. + +Specific aims + +- swifty +- asynchronous +- simple(r) way to enable/disable channels from the command line +- support the new os_log() model + + + diff --git a/Extras/Examples/CommandLineExample/Sources/Example/main.swift b/Extras/Examples/CommandLineExample/Sources/Example/main.swift new file mode 100644 index 0000000..286d0d3 --- /dev/null +++ b/Extras/Examples/CommandLineExample/Sources/Example/main.swift @@ -0,0 +1,25 @@ +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// Created by Sam Deane, 15/02/2018. +// All code (c) 2018 - present day, Elegant Chaos Limited. +// For licensing terms, see http://elegantchaos.com/license/liberal/. +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +import Logger + +let stdout = Logger.stdout + +let test = Channel("test") +let test2 = Channel("com.elegantchaos.other.test2", handlers: [PrintHandler("print", showName: true, showSubsystem: true)]) + +stdout.log("This should get printed to stdout.") +stdout.log("There shouldn't be any contex information included in the output.\n") + +test.log("This should get printed to the default console location.") +test.log("On the Mac it'll be the console. On Linux, currently, it's stdout.") +test.log("Unlike the Logger.stdout channel, this one also shows the channel name.\n\n") + +test2.log("This should always be logged to stdout, but will show the console name and the subsystem.\n") + +stdout.debug("This should only appear for debug builds.\n") + +Logger.defaultManager.flush() diff --git a/Package.swift b/Package.swift index 3b587d5..63b995c 100644 --- a/Package.swift +++ b/Package.swift @@ -2,39 +2,26 @@ import PackageDescription -var products: [Product] = [ - .library( - name: "Logger", - targets: ["Logger"]), - .library( - name: "LoggerUI", - targets: ["LoggerUI"]), - .library( - name: "LoggerKit", - targets: ["LoggerKit"]), - .library( - name: "LoggerTestSupport", - targets: ["LoggerTestSupport"]) -] - - -#if os(macOS) -products.append( - .executable( - name: "LoggerExample", - targets: ["LoggerExample"] - ) -) -#endif - let package = Package( name: "Logger", platforms: [ .macOS(.v10_13), .iOS(.v12), .tvOS(.v12), .watchOS(.v5) ], - products: products, - dependencies: [ + products: [ + .library( + name: "Logger", + targets: ["Logger"]), + .library( + name: "LoggerUI", + targets: ["LoggerUI"]), + .library( + name: "LoggerKit", + targets: ["LoggerKit"]), + .library( + name: "LoggerTestSupport", + targets: ["LoggerTestSupport"]) ], + dependencies: [], targets: [ .target( name: "Logger", @@ -45,9 +32,6 @@ let package = Package( .target( name: "LoggerUI", dependencies: ["Logger"]), - .target( - name: "LoggerExample", - dependencies: ["Logger"]), .target( name: "LoggerTestSupport", dependencies: ["Logger"]), @@ -56,6 +40,6 @@ let package = Package( dependencies: ["Logger", "LoggerTestSupport"]), .testTarget( name: "LoggerKitTests", - dependencies: ["LoggerKit", "LoggerTestSupport"]), + dependencies: ["LoggerKit", "LoggerTestSupport"]) ] )