{"id":15561333,"url":"https://github.com/curatoopensource/injectableloggers","last_synced_at":"2026-01-16T12:27:56.125Z","repository":{"id":56915525,"uuid":"131716918","full_name":"CuratoOpenSource/InjectableLoggers","owner":"CuratoOpenSource","description":"A nice set of protocols that will help logger(s) at being loosely coupled, injectable and testable.","archived":false,"fork":false,"pushed_at":"2020-11-03T16:04:42.000Z","size":297,"stargazers_count":5,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-04-09T03:01:53.673Z","etag":null,"topics":["dependency-injection","log","logger","logging","mock","mocking","mocks","protocol","protocols","swift","swift4","testability","testable","testing"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CuratoOpenSource.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","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":"2018-05-01T13:35:57.000Z","updated_at":"2023-07-22T20:01:22.000Z","dependencies_parsed_at":"2022-08-21T03:50:30.850Z","dependency_job_id":null,"html_url":"https://github.com/CuratoOpenSource/InjectableLoggers","commit_stats":null,"previous_names":["lvnkmn/injectableloggers"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FInjectableLoggers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FInjectableLoggers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FInjectableLoggers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FInjectableLoggers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CuratoOpenSource","download_url":"https://codeload.github.com/CuratoOpenSource/InjectableLoggers/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250528681,"owners_count":21445511,"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":["dependency-injection","log","logger","logging","mock","mocking","mocks","protocol","protocols","swift","swift4","testability","testable","testing"],"created_at":"2024-10-02T16:07:29.241Z","updated_at":"2025-12-11T23:01:39.067Z","avatar_url":"https://github.com/CuratoOpenSource.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InjectableLoggers\n [![Version](http://img.shields.io/cocoapods/v/InjectableLoggers.svg?style=flat)](http://cocoapods.org/pods/Zoomy) [![Platform](http://img.shields.io/cocoapods/p/InjectableLoggers.svg?style=flat)](http://cocoapods.org/pods/Zoomy) [![License](http://img.shields.io/cocoapods/l/InjectableLoggers.svg?style=flat)](LICENSE)\n\nA nice set of protocols that will help logger(s) at being loosely coupled, injectable and testable.\n\n## Example\n\nTo see the example project, run the following in your terminal:\n\n`pod try InjectableLoggers`\n\n## Setup\nJust add: \n\n`import InjectableLoggers`\n\nto the files where you need some injectable logging action.\n\n### Making your logger injectable\n\nDepending on how much functionality you want (to expose) from a logger, make a logger conform to one of the following protocols:\n\n`CanLog`\n\n`CanLogMessage`\n\n`CanLogMessageAtLevel`\n\nAll of thes protocols have lightweight and sensible default implementations and make sure you never have to implement more than one of their methods.\n\n### Making an existing logger injectable\n\n#### When it uses instance methods for logging\n\n```swift\nextension SomeoneElsesLogger: CanLogMessageAtLevel /* CanLog || CanLogMessage */ {\n\n\tfunc log(_ message Any, at: LogLevel) {\n\t\t//call existing logging functionality here\n\t}\n}\n```\n\n#### When it uses class methods for logging\n\n```swift\nstruct Logger: CanLogMessageAtLevel /* CanLog || CanLogMessage */ {\n\n\tfunc log(_ message Any, at: LogLevel) {\n\t\t//call existing logging functionality here\n\t}\n}\n```\n\n### Doing some logging\n\nDepending on which protocols your loggers conform to, you can call the following methods:\n\n```swift\nlogger.log() //Will log \"\" to default LogLevel if expected\nlogger.log(42) //Will log 42 to default LogLevel if expected\nlogger.log(\"Something not to important\", at LogLevel.verbose)\nlogger.log(\"Something broke!\", at: LogLevel.error)\n```\n\nBonus! This lib comes with two concrete loggers 🎉\n\n**ConsoleLogger**\n\n```swift\nlet logger: CanLogMessage = ConsoleLogger()\n\nlogger.log() // logs to console: \"\"\nlogger.log(42) // logs to console: 42\nlogger.log(\"Hi there\") // logs to console: \"Hi there\"\n```\n\n**Logger**\n\n```swift\nlet logger: CanLogMessageAtLevel = Logger(settings: .warningSettings)\n\nlogger.log(\"Some info\", atLevel LogLevel.info) //Won't log anything because of settings\nlogger.log(\"Something's up\") // logs to settings.destination: \"⚠️ Something's up\"\nlogger.log(\"Something went wrong\") // logs to settings.destination: \"⛔️ Something's up\"\n```\n\n`settings.destination`?\n\nYes, settings has it's own `CanLogMessage` instance (`ConsoleLogger` by default) which is used for logging all created strings. This not only made `Logger` completely testable (and tested) but it also allows you to log to different destinations if needed.\n\n\n### Testing that what was expected is being logged\nAnother bonus! This lib comes with a pretty handy mock logger called `MockLogger` 🎉\n\n```swift\nclass ViewControllerTests: XCTestCase {\n    \n    var sut: ViewController!\n    var mockLogger: MockLogger!\n    \n    override func setUp() {\n        super.setUp()\n        \n        sut = ViewController()\n        mockLogger = MockLogger()\n    }\n    \n    // MARK: Single line assertions\n    func testViewDidLoad() {\n        //Arrange\n        sut.logger = mockLogger //Inject mockLogger\n        \n        //Act\n        sut.viewDidLoad()\n        \n        //Assert\n        XCTAssertEqual(mockLogger.loggedMessages(at: Loglevel.info).last?.message as? String, \"viewDidLoad()\")\n    }\n    \n    // MARK: More verbose assertions\n    func testDidReceiveMemoryWarning() {\n        //Arrange\n        sut.logger = mockLogger //Inject mockLogger\n        \n        //Act\n        sut.didReceiveMemoryWarning()\n        \n        //Assert\n        XCTAssertEqual(mockLogger.loggedMessages.last?.message as? String, \"didReceiveMemoryWarning()\")\n        XCTAssertEqual(mockLogger.loggedMessages.last?.level, Loglevel.warning)\n    }\n}\n```\n\nFor some more advance testing check out the example project.\n\n## Installation\n\nInjectableLoggers is available through [Swift Package Manager](https://swift.org/package-manager/). To install it, simply add it to your project using this repository's URL as explained [here](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app).\n\n## License\n\nInjectableLoggers is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuratoopensource%2Finjectableloggers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcuratoopensource%2Finjectableloggers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuratoopensource%2Finjectableloggers/lists"}