{"id":20246778,"url":"https://github.com/vivint/woody","last_synced_at":"2026-05-06T04:04:11.313Z","repository":{"id":56927663,"uuid":"102663170","full_name":"vivint/Woody","owner":"vivint","description":"A micro logging framework to help unify logs across apps and frameworks","archived":false,"fork":false,"pushed_at":"2019-04-09T21:52:57.000Z","size":43,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-17T07:17:51.825Z","etag":null,"topics":["carthage","cocoapod","ios","logging","macos","objective-c","swift","swift-framework","tvos","watchos"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vivint.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-06T22:11:32.000Z","updated_at":"2019-04-09T21:37:12.000Z","dependencies_parsed_at":"2022-08-20T23:30:41.895Z","dependency_job_id":null,"html_url":"https://github.com/vivint/Woody","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivint%2FWoody","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivint%2FWoody/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivint%2FWoody/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivint%2FWoody/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vivint","download_url":"https://codeload.github.com/vivint/Woody/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241692660,"owners_count":20004271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carthage","cocoapod","ios","logging","macos","objective-c","swift","swift-framework","tvos","watchos"],"created_at":"2024-11-14T09:33:03.503Z","updated_at":"2026-05-06T04:04:11.302Z","avatar_url":"https://github.com/vivint.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Woody\n\nWoody is a micro logging framework with support for Swift \u0026 Objective-C that helps decouple which logging framework the end client (usually an app) would like to use.  For example you have multiple in house frameworks which are used across multiple different apps and you don't want to tie them all to a specific logging framework like [CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack) or [SwiftyBeaver](https://github.com/SwiftyBeaver/SwiftyBeaver).  Woody allows you to not worry about which logging framework your app team wants to use when developing those in house frameworks and instead leaves that up to the end consumer of your framework.\n\n## Usage\n\n### Swift\n\n```swift\nimport Woody\n\nlet log = Woody.self\n\nlog.verbose(\"Verbose message\")\nlog.info(\"Info message\")\nlog.debug(\"Debug message\")\nlog.warning(\"Warning message\")\nlog.error(\"Error message\")\n```\n\n### Objective-C\n\n```objc\n@import Woody;\n\nWLogVerbose(@\"Verbose message\");\nWLogInfo(@\"Info message\");\nWLogDebug(@\"Debug message\");\nWLogWarning(@\"Warning message\");\nWLogError(@\"Error message\");\n```\n\n## Setup\n\n### Install\n\nThis library supports both Carthage and CocoaPods\n\n#### CocoaPods\n\nAdd this line to your Podfile\n```ruby\npod 'Woody'\n```\n\n#### Carthage\n\nAdd this line to your Cartfile\n```\ngithub \"vivint/Woody\" ~\u003e 0.2.0\n```\n\nBelow are two guides for use in either a framework or app target\n\n### Frameworks\n\nThe easiest way to get started using Woody in a framework is to add a `Logging.swift` file like this:\n\n```swift\nimport Foundation\nimport Woody\n\nlet log = Woody.self\n\n// Mark these as deprecated to make sure we don't forget to use Woody logging\n@available(*, deprecated, message: \"Use logging utilities instead\")\nfunc print(_ items: Any..., separator: String = \" \", terminator: String = \"\\n\") {\n    Swift.print(items, separator: separator, terminator: terminator)\n}\n\n@available(*, deprecated, message: \"Use logging utilities instead\")\nfunc debugPrint(_ items: Any..., separator: String = \" \", terminator: String = \"\\n\") {\n    Swift.debugPrint(items, separator: separator, terminator: terminator)\n}\n\n@available(*, deprecated, message: \"Use logging utilities instead\")\nfunc NSLog(_ format: String, _ args: CVarArg...) {\n    Foundation.NSLog(format, args)\n}\n```\n\n### Apps (iOS, tvOS, watchOS, macOS)\n\n\nThe easiest way to setup logging in an app is to add a `AppDelegate+Logging.swift` file and adding the following items:\n\nThis sets up an easy way to log throughout the app\n```swift\nimport Woody\n\nlet log = Woody.self\n```\n\nI have found these useful to make sure other developers of the project are using the logging methods instead of any built in ones.\n```swift\nimport Foundation\n\n\n// Mark these as deprecated to make sure we don't forget to use logging in the app\n@available(*, deprecated, message: \"Use logging utilities instead\")\nfunc print(_ items: Any..., separator: String = \" \", terminator: String = \"\\n\") {\n    Swift.print(items, separator: separator, terminator: terminator)\n}\n\n@available(*, deprecated, message: \"Use logging utilities instead\")\nfunc debugPrint(_ items: Any..., separator: String = \" \", terminator: String = \"\\n\") {\n    Swift.debugPrint(items, separator: separator, terminator: terminator)\n}\n\n@available(*, deprecated, message: \"Use logging utilities instead\")\nfunc NSLog(_ format: String, _ args: CVarArg...) {\n    Foundation.NSLog(format, args)\n}\n```\n\nYou need to setup a delegate to get called whenever a log happens\n\n```swift\nclass LoggingDelegate: WoodyDelegate {\n    func verbose(_ msg: String, filepath: String, function: String, line: Int) {\n\tprint(\"VERBOSE: \\(filepath).\\(function): \\(line) - \\(msg)\")\n    }\n\n    func debug(_ msg: String, filepath: String, function: String, line: Int) {\n\tprint(\"DEBUG: \\(filepath).\\(function): \\(line) - \\(msg)\")\n    }\n\n    func info(_ msg: String, filepath: String, function: String, line: Int) {\n\tprint(\"INFO: \\(filepath).\\(function): \\(line) - \\(msg)\")\n    }\n\n    func warning(_ msg: String, filepath: String, function: String, line: Int) {\n\tprint(\"WARNING: \\(filepath).\\(function): \\(line) - \\(msg)\")\n    }\n\n    func error(_ msg: String, filepath: String, function: String, line: Int) {\n\tprint(\"ERROR: \\(filepath).\\(function): \\(line) - \\(msg)\")\n    }\n}\n```\n\nExtend the `AppDelegate` to add a method to setup logging\n\n```swift\nextension AppDelegate {\n    func setupLogging() {\n        log.delegate = LoggingDelegate()\n    }\n}\n```\n\nLast of all you need to call you new `setupLogging()` method in your `appDidFinishLaunching`.  (I would put it at the very top so you don't miss any logs when the app is launching)\n\n\n### Using other logging providers\n\nIf you would like to forward the logs on to a different provider like [SwiftyBeaver](https://github.com/SwiftyBeaver/SwiftyBeaver) you can easily do that in your `WoodyDelegate`\n\n```swift\nimport SwiftyBeaver\n\n\nclass LoggingDelegate: WoodyDelegate {\n    func verbose(_ msg: String, filepath: String, function: String, line: Int) {\n        SwiftyBeaver.verbose(msg, filepath, function, line: line)\n    }\n\n    func debug(_ msg: String, filepath: String, function: String, line: Int) {\n        SwiftyBeaver.debug(msg, filepath, function, line: line)\n    }\n\n    func info(_ msg: String, filepath: String, function: String, line: Int) {\n        SwiftyBeaver.info(msg, filepath, function, line: line)\n    }\n\n    func warning(_ msg: String, filepath: String, function: String, line: Int) {\n        SwiftyBeaver.warning(msg, filepath, function, line: line)\n    }\n\n    func error(_ msg: String, filepath: String, function: String, line: Int) {\n        SwiftyBeaver.error(msg, filepath, function, line: line)\n    }\n}\n```\n\nAnd then in your `setupLogging()` you can add some Destinations to SwiftyBeaver\n\n```swift\nextension AppDelegate {\n    func setupLogging(logLevel: SwiftyBeaver.Level = .verbose) {\n        log.delegate = LoggingDelegate()\n\n        let console = ConsoleDestination()\n        // use custom format and set console output to short time, log level \u0026 message\n        console.format = \"$C$L$c $N.$F:$l - $M\"\n        console.minLevel = logLevel\n        SwiftyBeaver.addDestination(console)\n\n        let cloud = SBPlatformDestination(appID: \"APP_ID\", appSecret: \"SECRET\", encryptionKey: \"KEY\")\n        cloud.minLevel = logLevel\n        SwiftyBeaver.addDestination(cloud)\n    }\n}\n```\n\n### Ideas\n\n* Give the ability to users of Woody register themselves as Woody consumer and allow the end user to filter out logs for each framework that has registered.\n* Possibly send logs to console by default if no `WoodyDelegate` is set.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivint%2Fwoody","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvivint%2Fwoody","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivint%2Fwoody/lists"}