{"id":18060646,"url":"https://github.com/0xleif/chronicle","last_synced_at":"2025-10-08T23:19:35.059Z","repository":{"id":52952578,"uuid":"355005056","full_name":"0xLeif/Chronicle","owner":"0xLeif","description":"🪵  Simple Swift Logger in under 90 loc","archived":false,"fork":false,"pushed_at":"2021-05-11T21:27:29.000Z","size":30,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-20T18:46:10.113Z","etag":null,"topics":["logging","swift"],"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/0xLeif.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":"2021-04-06T00:01:09.000Z","updated_at":"2022-06-14T21:08:50.000Z","dependencies_parsed_at":"2022-08-28T09:03:08.951Z","dependency_job_id":null,"html_url":"https://github.com/0xLeif/Chronicle","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/0xLeif/Chronicle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xLeif%2FChronicle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xLeif%2FChronicle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xLeif%2FChronicle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xLeif%2FChronicle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xLeif","download_url":"https://codeload.github.com/0xLeif/Chronicle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xLeif%2FChronicle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000728,"owners_count":26082862,"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","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["logging","swift"],"created_at":"2024-10-31T04:10:02.899Z","updated_at":"2025-10-08T23:19:35.030Z","avatar_url":"https://github.com/0xLeif.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chronicle\n\n*Simple Swift Logger in under 90 loc*\n\n### Default Format\n\n**`{Date} {Label} {Emoji}: {Message}`**\n\n4/5/21, 7:05:42 PM CDT [com.example.chronicle] ℹ️: Info\n```\nDate = 4/5/21, 7:05:42 PM CDT\nLabel = [com.example.chronicle]\nEmoji = ℹ️\nMessage = Info\n```\n\n## Examples\n\n### Default Chronicle\n```swift\nlet chrono = Chronicle(\n    label: \"com.example.chronicle\"\n)\n\nenum SomeError: Error { case abc }\n\nchrono.log(level: .success(\"Success\"))\nchrono.log(level: .info(\"Info\"))\nchrono.log(level: .warning(\"Warning\"))\nchrono.log(level: .error(\"Error\", SomeError.abc))\nchrono.log(level: .fatal(\"Fatal\", SomeError.abc))\n```\n\n**Logging**\n```\n4/9/21, 9:42:08 PM CDT [com.example.chronicle] ✅: Success\n4/9/21, 9:42:08 PM CDT [com.example.chronicle] ℹ️: Info\n4/9/21, 9:42:08 PM CDT [com.example.chronicle] ⚠️: Warning\n4/9/21, 9:42:08 PM CDT [com.example.chronicle] ❗️: Error\n{\n\tabc: The operation couldn’t be completed. (ChronicleTests.ChronicleTests.(unknown context at $10708b2f8).(unknown context at $10708b344).SomeError error 0.)\n}\n4/9/21, 9:42:08 PM CDT [com.example.chronicle] 🚨: Fatal\n{\n\tabc: The operation couldn’t be completed. (ChronicleTests.ChronicleTests.(unknown context at $10708b2f8).(unknown context at $10708b344).SomeError error 0.)\n}\n```\n\n\n## Output Formatter\n```swift\npublic protocol ChronicleFormatter {\n    var dateFormatter: DateFormatter { get }\n    func format(label: String) -\u003e String\n    func format(logLevel: Chronicle.LogLevel) -\u003e String\n    func output(\n        formattedDate: String,\n        formattedLabel: String,\n        formattedLogMessage: String\n    ) -\u003e String\n}\n```\n\n### Default Formatter\n\n```swift\nextension Chronicle {\n    public struct DefaultFormatters {\n        public struct DefaultFormatter: ChronicleFormatter {\n            public init() { }\n            \n            public var dateFormatter: DateFormatter = {\n                let formatter = DateFormatter()\n                \n                formatter.dateStyle = .short\n                formatter.timeStyle = .long\n                \n                return formatter\n            }()\n            \n            public func format(label: String) -\u003e String { \"[\\(label)]\" }\n            \n            public func format(logLevel: Chronicle.LogLevel) -\u003e String {\n                \"\\(logLevel.emoji): \\(logLevel.output)\"\n            }\n            \n            public func output(\n                formattedDate: String,\n                formattedLabel: String,\n                formattedLogMessage: String\n            ) -\u003e String {\n                formattedDate + \" \" + formattedLabel + \" \" + formattedLogMessage\n            }\n        }\n    }\n}\n```\n\n### Output Handler\n\n```swift\npublic protocol ChronicleHandler {\n    func handle(output: String) -\u003e Void\n    func didHandle(chronicle: Chronicle, level: Chronicle.LogLevel)\n}\n```\n\n### Default Handlers\n\n```swift\nextension Chronicle {\n    public struct DefaultHandlers {\n        public struct PrintHandler: ChronicleHandler {\n            public init() { }\n            \n            public func handle(output: String) { print(output) }\n            \n            public func didHandle(chronicle: Chronicle, level: Chronicle.LogLevel) { }\n        }\n        \n        public struct FileHandler: ChronicleHandler {\n            private let lock = NSLock()\n            \n            public var fileURL: URL {\n                FileManager.default.urls(for: .documentDirectory,\n                                         in: .userDomainMask)[0]\n                    .appendingPathComponent(fileName)\n            }\n            \n            public var fileName: String\n            \n            public init(fileName: String = \"chronicle.log\") {\n                self.fileName = fileName\n            }\n            \n            public func handle(output: String) {\n                var fileOutput = \"\"\n                \n                lock.lock()\n                \n                defer {\n                    fileOutput.append(output)\n                    \n                    do {\n                        try fileOutput.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8)\n                    } catch {\n                        dump(error)\n                    }\n                    \n                    lock.unlock()\n                }\n                \n                guard let contents = try? Data(contentsOf: fileURL) else {\n                    return\n                }\n                \n                let fileContents = String(data: contents, encoding: .utf8)\n                \n                if let fileContents = fileContents {\n                    fileOutput.append(fileContents + \"\\n\")\n                }\n                \n            }\n            \n            public func didHandle(chronicle: Chronicle, level: Chronicle.LogLevel) { }\n        }\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xleif%2Fchronicle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xleif%2Fchronicle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xleif%2Fchronicle/lists"}