{"id":20724516,"url":"https://github.com/laserdisc-io/log-effect","last_synced_at":"2026-01-21T05:05:31.666Z","repository":{"id":33044853,"uuid":"139831085","full_name":"laserdisc-io/log-effect","owner":"laserdisc-io","description":"A simple macro-less logging typeclass with some common backends","archived":false,"fork":false,"pushed_at":"2025-12-28T18:42:30.000Z","size":928,"stargazers_count":22,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-31T09:42:38.080Z","etag":null,"topics":["cats","fs2","functional-programming","logging","mtl","scala","tagless-final","typeclass","zio"],"latest_commit_sha":null,"homepage":"","language":"Scala","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/laserdisc-io.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-07-05T10:04:36.000Z","updated_at":"2025-12-28T18:42:34.000Z","dependencies_parsed_at":"2023-02-18T18:01:41.415Z","dependency_job_id":"e9f2dca9-279a-4fbe-9187-8d29dc61479a","html_url":"https://github.com/laserdisc-io/log-effect","commit_stats":null,"previous_names":[],"tags_count":69,"template":false,"template_full_name":null,"purl":"pkg:github/laserdisc-io/log-effect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Flog-effect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Flog-effect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Flog-effect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Flog-effect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/laserdisc-io","download_url":"https://codeload.github.com/laserdisc-io/log-effect/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laserdisc-io%2Flog-effect/sbom","scorecard":{"id":579490,"data":{"date":"2025-08-11","repo":{"name":"github.com/laserdisc-io/log-effect","commit":"3bc889efea089c259c2f78ec9422742c1ede129e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.6,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":7,"reason":"9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/clean.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:103: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:119: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:124: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:129: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:142: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:153: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:163: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:173: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:183: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:193: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:203: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:246: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:251: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:256: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:269: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:280: update your workflow using https://app.stepsecurity.io/secureworkflow/laserdisc-io/log-effect/ci.yml/master?enable=pin","Info:   0 out of  16 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T18:48:28.331Z","repository_id":33044853,"created_at":"2025-08-20T18:48:28.331Z","updated_at":"2025-08-20T18:48:28.331Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28627388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cats","fs2","functional-programming","logging","mtl","scala","tagless-final","typeclass","zio"],"created_at":"2024-11-17T04:15:09.964Z","updated_at":"2026-01-21T05:05:31.650Z","avatar_url":"https://github.com/laserdisc-io.png","language":"Scala","readme":"# Log Effect\n[![Continuous Integration](https://github.com/laserdisc-io/log-effect/actions/workflows/ci.yml/badge.svg)](https://github.com/laserdisc-io/log-effect/actions/workflows/ci.yml)\n[![Known Vulnerabilities](https://snyk.io/test/github/laserdisc-io/log-effect/badge.svg?targetFile=build.sbt)](https://snyk.io/test/github/laserdisc-io/log-effect?targetFile=build.sbt)\n[![Join the chat at https://gitter.im/laserdisc-io/laserdisc](https://badges.gitter.im/laserdisc-io/laserdisc.svg)](https://gitter.im/laserdisc-io/laserdisc?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://raw.githubusercontent.com/laserdisc-io/log-effect/master/LICENSE)\n[![Scala Steward badge](https://img.shields.io/badge/Scala_Steward-helping-blue.svg?style=flat\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org)\n\n[![log-effect-fs2 Scala version support](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-fs2/latest-by-scala-version.svg?platform=jvm\u0026color=2282c3)](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-fs2)\n\n\n[![log-effect-zio Scala version support](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-zio/latest-by-scala-version.svg?platform=jvm\u0026color=fb0005)](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-zio)\n\n[![log-effect-core Scala version support](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-core/latest-by-scala-version.svg?platform=jvm\u0026color=9311fc)](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-core)\n\n[![log-effect-interop Scala version support](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-interop/latest-by-scala-version.svg?platform=jvm\u0026color=009933)](https://index.scala-lang.org/laserdisc-io/log-effect/log-effect-interop)\n\n## Start\nLog Effect is available for Scala **_2.12_**, **_2.13_** and **_3_**. Helper constructors are provided for **Cats Effect**'s `Sync` `F[_]`, for **Fs2**'s `Stream` and for **ZIO**'s `Task`. \nAdd\n```scala\nlibraryDependencies += \"io.laserdisc\" %% \"log-effect-fs2\" % \u003clatest-fs2-version\u003e\n```\nfor **Fs2** or **Cats Effect**. Add instead\n```scala\nlibraryDependencies += \"io.laserdisc\" %% \"log-effect-zio\" % \u003clatest-zio-version\u003e\n```\nfor **ZIO**. If the intention is, instead, to create your own implementation of the typeclass, adding this\n```scala\nlibraryDependencies += \"io.laserdisc\" %% \"log-effect-core\" % \u003clatest-core-version\u003e\n```\nwill be enough. For the latest versions available please refer to the badges below the title.\n\n## Backends\nCurrently Log Effect supports the following backends\n- Log4s\n- Java Logging (Jul)\n- Scribe\n- Console\n- No log sink \n\n## Dependencies\n\n|                          | Cats | Fs2 | Cats Effect | Log Effect Core   |\n| ------------------------:| ----:| ---:| -----------:| -----------------:|\n| [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-fs2_2.13.svg?label=log-effect-fs2\u0026colorB=2282c3)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-fs2_2.13) | 2.9.0 | 3.4.0 | 3.4.1 | [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-core_2.13.svg?label=%20\u0026colorB=9311fc)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-core_2.13) |\n\n\u003cbr/\u003e\n\n|                          | Zio | Log Effect Core |\n| ------------------------:| ---:| ---------------:|\n| [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-zio_2.13.svg?label=log-effect-zio\u0026colorB=fb0005)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-zio_2.13) | 2.0.4 | [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-core_2.12.svg?label=%20\u0026colorB=9311fc)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-core_2.13) | \n\n\u003cbr/\u003e\n\n|                          | Log4cats | Log Effect Core   |\n| ------------------------:| --------:| -----------------:|\n| [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-interop_2.13.svg?label=log-effect-interop\u0026colorB=009933)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-interop_2.13) | 2.5.0 | [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-core_2.13.svg?label=%20\u0026colorB=9311fc)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-core_2.13) |\n\n\u003cbr/\u003e\n\n|                          | Log4s  | Scribe |\n| ------------------------:| ------:| ------:|\n| [![Maven Central](https://img.shields.io/maven-central/v/io.laserdisc/log-effect-core_2.13.svg?label=log-effect-core\u0026colorB=9311fc)](https://maven-badges.herokuapp.com/maven-central/io.laserdisc/log-effect-core_2.13) | 1.10.0 | 3.10.5 |\n\n\u003cbr/\u003e\n\n## Examples\n\n### Get Logs\n\n#### Cats Effect Sync\nTo get an instance of `LogWriter` for **Cats Effect**'s `Sync` the options below are available (see [here](./fs2/src/main/scala/log/effect/fs2/SyncLogWriter.scala))\n\n*full compiling example [here](./fs2/src/test/scala/ReadmeConstructionCodeSnippetsTest.scala)*\n```scala\nval log4s1: F[LogWriter[F]] =\n  F.delay(l4s.getLogger(\"test\")) map log4sLog[F]\n\nval log4s2: F[LogWriter[F]] = log4sLog(\"a logger\")\n\nval log4s3: F[LogWriter[F]] = {\n  case class LoggerClass()\n  log4sLog(classOf[LoggerClass])\n}\n\nval jul1: F[LogWriter[F]] =\n  F.delay(jul.Logger.getLogger(\"a logger\")) map julLog[F]\n\nval jul2: F[LogWriter[F]] = julLog\n\nval scribe1: F[LogWriter[F]] =\n  F.delay(scribe.Logger(\"a logger\")) map scribeLog[F]\n\nval scribe2: F[LogWriter[F]] = scribeLog(\"a logger\")\n\nval scribe3: F[LogWriter[F]] = {\n  case class LoggerClass()\n  scribeLog(classOf[LoggerClass])\n}\n\nval console1: LogWriter[F] = consoleLog\n\nval console2: LogWriter[F] = consoleLogUpToLevel(LogLevels.Warn)\n\nval noOp: LogWriter[F] = noOpLog[F]\n```\n\n#### Fs2 Stream\nSimilarly, to get instances of `LogWriter` for **Fs2**'s `Stream` the constructors below are available [here](./fs2/src/main/scala/log/effect/fs2/SyncLogWriter.scala)\n\n*full compiling example [here](./fs2/src/test/scala/ReadmeConstructionCodeSnippetsTest.scala)*\n```scala\nval log4s1: fs2.Stream[F, LogWriter[F]] =\n  Stream.eval(F.delay(l4s.getLogger(\"test\"))) \u003e\u003e= log4sLogStream[F]\n\nval log4s2: fs2.Stream[F, LogWriter[F]] = log4sLogStream(\"a logger\")\n\nval log4s3: fs2.Stream[F, LogWriter[F]] = {\n  case class LoggerClass()\n  log4sLogStream(classOf[LoggerClass])\n}\n\nval jul1: fs2.Stream[F, LogWriter[F]] =\n  Stream.eval(F.delay(jul.Logger.getLogger(\"a logger\"))) \u003e\u003e= julLogStream[F]\n\nval jul2: fs2.Stream[F, LogWriter[F]] = julLogStream\n\nval scribe1: fs2.Stream[F, LogWriter[F]] =\n  Stream.eval(F.delay(scribe.Logger(\"a logger\"))) \u003e\u003e= scribeLogStream[F]\n\nval scribe2: fs2.Stream[F, LogWriter[F]] = scribeLogStream(\"a logger\")\n\nval scribe3: fs2.Stream[F, LogWriter[F]] = {\n  case class LoggerClass()\n  scribeLogStream(classOf[LoggerClass])\n}\n\nval console1: fs2.Stream[F, LogWriter[F]] = consoleLogStream\n\nval console2: fs2.Stream[F, LogWriter[F]] = consoleLogStreamUpToLevel(LogLevels.Warn)\n\nval noOp: fs2.Stream[F, LogWriter[F]] = noOpLogStream\n```\n*See [here](https://github.com/laserdisc-io/laserdisc#example-usage) for an example with [Laserdisc](https://github.com/laserdisc-io/laserdisc)*\n\n#### Zio Task\nTo create instances for `ZIO` some useful constructors can be found [here](./zio/src/main/scala/log/effect/zio/ZioLogWriter.scala). Note as they exploit the power and expressiveness of `RLayer` an the `RIO` pattern as shown below.\n\n##### Create LogWriter as a Layer\n*full compiling example [here](./zio/src/test/scala/ReadmeLayerConstructionCodeSnippetsTest.scala)*\n```scala\n// Case 1: from a possible config\nval logNameLiveFromConfig: ULayer[ZLogName] =\n  aConfigLive \u003e\u003e\u003e ZLayer(ZIO.service[AConfig].map(c =\u003e LogName(c.logName)))\n\nval log4sCase1: TaskLayer[ZLogWriter] =\n  logNameLiveFromConfig \u003e\u003e\u003e log4sLayerFromName\n\nval scribeCase1: TaskLayer[ZLogWriter] =\n  logNameLiveFromConfig \u003e\u003e\u003e scribeLayerFromName\n\n// Case 2: from a name\nval log4sCase2: TaskLayer[ZLogWriter] =\n  logNameLive \u003e\u003e\u003e log4sLayerFromName\n\nval scribeCase2: TaskLayer[ZLogWriter] =\n  logNameLive \u003e\u003e\u003e scribeLayerFromName\n\n// Case 3: from a logger\nval log4sCase3: TaskLayer[ZLogWriter] =\n  log4sLoggerLive \u003e\u003e\u003e log4sLayerFromLogger\n\nval julCase3: TaskLayer[ZLogWriter] =\n  julLoggerLive \u003e\u003e\u003e julLayerFromLogger\n\nval scribeCase3: TaskLayer[ZLogWriter] =\n  scribeLoggerLive \u003e\u003e\u003e scribeLayerFromLogger\n```\n\n##### Create LogWriter as RIO\n*full compiling example [here](./zio/src/test/scala/ReadmeRioConstructionCodeSnippetsTest.scala)*\n```scala\n// Case 1: from a possible config in a Layer (gives a Layer)\nval log4sCase1: RLayer[AConfig, ZLogWriter] =\n  ZLayer(ZIO.serviceWithZIO { c =\u003e\n    log4sFromName.provideEnvironment(ZEnvironment(c.logName))\n  })\nval scribe4sCase1: RLayer[AConfig, ZLogWriter] =\n  ZLayer(ZIO.serviceWithZIO { c =\u003e\n    scribeFromName.provideEnvironment(ZEnvironment(c.logName))\n  })\n\n// Case 2: from a name\nval log4sCase2: Task[Unit] =\n  log4sFromName.provideEnvironment(ZEnvironment(aLogName)).flatMap { logger =\u003e\n    someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logger))\n  }\nval scribeCase2: Task[Unit] =\n  scribeFromName.provideEnvironment(ZEnvironment(aLogName)).flatMap { logger =\u003e\n    someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logger))\n  }\n\n// Case 3: from a logger\nval log4sCase3: Task[Unit] =\n  for {\n    logger    \u003c- ZIO.attempt(l4s.getLogger(aLogName))\n    logWriter \u003c- log4sFromLogger.provideEnvironment(ZEnvironment(logger))\n    _         \u003c- someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logWriter))\n  } yield ()\nval julCase3: Task[Unit] =\n  for {\n    logger    \u003c- ZIO.attempt(jul.Logger.getLogger(aLogName))\n    logWriter \u003c- julFromLogger.provideEnvironment(ZEnvironment(logger))\n    _         \u003c- someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logWriter))\n  } yield ()\nval scribeCase3: Task[Unit] =\n  for {\n    logger    \u003c- ZIO.attempt(scribe.Logger(aLogName))\n    logWriter \u003c- scribeFromLogger.provideEnvironment(ZEnvironment(logger))\n    _         \u003c- someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logWriter))\n  } yield ()\n\n// Case 4: from a class\nval log4sCase4: Task[Unit] = {\n  case class LoggerClass();\n  log4sFromClass.provideEnvironment(ZEnvironment(classOf[LoggerClass])).flatMap { logger =\u003e\n    someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logger))\n  }\n}\nval scribeCase4: Task[Unit] = {\n  case class LoggerClass();\n  scribeFromClass.provideEnvironment(ZEnvironment(classOf[LoggerClass])).flatMap { logger =\u003e\n    someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logger))\n  }\n}\n\n// Case 5 (Jul): from global logger object\nval julCase5: Task[Unit] =\n  julGlobal.flatMap(logger =\u003e\n    someZioProgramUsingLogs.provideEnvironment(ZEnvironment(logger))\n  )\n\n// Case 6: console logger\nval console1: Task[Unit] =\n  someZioProgramUsingLogs.provideEnvironment(ZEnvironment(consoleLog))\n\nval console2: Task[Unit] =\n  someZioProgramUsingLogs.provideEnvironment(\n    ZEnvironment(consoleLogUpToLevel(LogLevels.Warn))\n  )\n\n// Case 7: No-op logger\nval noOp: Task[Unit] =\n  someZioProgramUsingLogs.provideEnvironment(ZEnvironment(noOpLog))\n```\n\n\n### Submit Logs\n\nThe following ways of submitting logs are supported:\n\n- _in a monadic sequence of effects_\n```scala\nimport cats.effect.Sync\nimport cats.syntax.flatMap._\nimport cats.syntax.functor._\nimport log.effect.LogWriter\n\ndef process[F[_]](implicit F: Sync[F], log: LogWriter[F]): F[(Int, Int)] =\n  for {\n    _ \u003c- log.trace(\"We start\")\n    a \u003c- F.delay(10)\n    _ \u003c- log.trace(\"Keep going\")\n    b \u003c- F.delay(20)\n    _ \u003c- log.trace(\"We reached this point\")\n    _ \u003c- log.info(s\"Process complete: ${(a, b)}\")\n  } yield (a, b)\n```\n\n - _in a streaming environment using `LogWriter`'s syntax_\n```scala\nimport java.nio.channels.AsynchronousChannelGroup\n\nimport cats.effect.{ ConcurrentEffect, ContextShift, Timer }\nimport cats.syntax.flatMap._\nimport log.effect.LogWriter\n\nimport scala.concurrent.ExecutionContext\n\nsealed trait RedisClient[F[_]] {\n  def address: String\n}\nobject RedisClient {\n  def apply[F[_]](addr: String): fs2.Stream[F, RedisClient[F]] =\n    fs2.Stream.emit(new RedisClient[F] { val address = addr })\n}\n\nimplicit def EC: ExecutionContext         = ???\nimplicit def CG: AsynchronousChannelGroup = ???\n\ndef redisClient[F[_]: ConcurrentEffect: ContextShift: Timer](\n  address: String\n)(implicit log: LogWriter[F]): fs2.Stream[F, RedisClient[F]] =\n  RedisClient[F](address) evalMap { client =\u003e\n    log.info(s\"Laserdisc Redis client for $address\") \u003e\u003e ConcurrentEffect[F].pure(client)\n  }\n```\n\n- _in a streaming environment using `fs2` streams' syntax_\n```scala\nimport java.nio.channels.AsynchronousChannelGroup\n\nimport cats.effect.{ ConcurrentEffect, ContextShift, Timer }\nimport log.effect.LogWriter\nimport log.effect.fs2.syntax._\n\nimport scala.concurrent.ExecutionContext\n\nsealed trait RedisClient[F[_]] {\n  def address: String\n}\nobject RedisClient {\n  def apply[F[_]](addr: String): fs2.Stream[F, RedisClient[F]] =\n    fs2.Stream.emit(new RedisClient[F] { val address = addr })\n}\n\nimplicit def EC: ExecutionContext         = ???\nimplicit def CG: AsynchronousChannelGroup = ???\n\ndef redisCache[F[_]: ConcurrentEffect: ContextShift: Timer](\n  address: String\n)(implicit log: LogWriter[F]): fs2.Stream[F, RedisClient[F]] =\n  for {\n    _      \u003c- log.infoS(s\"About to connect a Laserdisc Redis client for $address\")\n    client \u003c- RedisClient[F](address)\n    _      \u003c- log.infoS(\"The connection went fine. Talking to the server\")\n  } yield client\n```\n\n- _through the companion's syntax_\n```scala\nimport cats.effect.Sync\nimport cats.syntax.apply._\nimport cats.syntax.flatMap._\nimport log.effect.LogWriter\n\ndef double[F[_]: Sync: LogWriter](source: fs2.Stream[F, Int]): fs2.Stream[F, Int] =\n  source evalMap { n =\u003e\n    LogWriter.debug(\"Processing a number\") \u003e\u003e\n      LogWriter.debug(n.toString) \u003e\u003e\n      Sync[F].pure(n * 2) \u003c*\n      LogWriter.debug(\"Processed\")\n  } handleErrorWith { th =\u003e\n    fs2.Stream eval (\n      LogWriter.error(\"Ops, something didn't work\", th) \u003e\u003e Sync[F].pure(0)\n    )\n  }\n```\n\n- _through the companion's syntax for `fs2` streams_\n```scala\nimport cats.effect.Sync\nimport cats.syntax.apply._\nimport cats.syntax.flatMap._\nimport log.effect.LogWriter\nimport log.effect.fs2.syntax._\n\ndef double[F[_]: Sync: LogWriter](source: fs2.Stream[F, Int]): fs2.Stream[F, Int] =\n  (source \u003e\u003e= { n =\u003e\n    LogWriter.debugS(\"Processing a number\") \u003e\u003e\n      LogWriter.debugS(n.toString) \u003e\u003e\n      fs2.Stream.eval(Sync[F].pure(n * 2)) \u003c*\n      LogWriter.debugS(\"Processed\")\n  }) handleErrorWith { th =\u003e\n    LogWriter.errorS(\"Ops, something didn't work\", th) \u003e\u003e fs2.Stream.eval(Sync[F].pure(0))\n  }\n```\n\n- _through the companion's accessor for the `write` method_\n```scala\nimport java.nio.channels.AsynchronousChannelGroup\n\nimport cats.Show\nimport cats.effect.{ ConcurrentEffect, ContextShift, Timer }\nimport cats.instances.string._\nimport cats.syntax.either._\nimport cats.syntax.flatMap._\nimport log.effect.LogLevels.{ Debug, Error }\nimport log.effect.fs2.interop.show._\nimport log.effect.{ Failure, LogWriter }\n\nimport scala.concurrent.ExecutionContext\n\nsealed trait RedisClient[F[_]] {\n  def address: String\n}\nobject RedisClient {\n  def apply[F[_]](addr: String): fs2.Stream[F, RedisClient[F]] =\n    fs2.Stream.emit(new RedisClient[F] { val address = addr })\n}\n\ntype |[A, B] = Either[A, B]\n\nimplicit def EC: ExecutionContext         = ???\nimplicit def CG: AsynchronousChannelGroup = ???\n\ndef redisClient[F[_]: ConcurrentEffect: ContextShift: Timer: LogWriter](\n  address: String\n): fs2.Stream[F, Throwable | RedisClient[F]] = {\n  // Cats Show instances are needed for every logged type\n  implicit val clientShow: Show[RedisClient[F]] = ???\n\n  RedisClient[F](address) evalMap { client =\u003e\n    LogWriter.write(Debug, \"Connected client details:\") \u003e\u003e // Or\n      LogWriter.debug(address) \u003e\u003e                          // And\n      LogWriter.debug(client) \u003e\u003e\n      ConcurrentEffect[F].pure(client.asRight)\n  } handleErrorWith { th =\u003e\n    fs2.Stream eval (\n      LogWriter.write(\n        Error,\n        Failure(\"Ops, something didn't work\", th)\n      ) \u003e\u003e ConcurrentEffect[F].pure(th.asLeft)\n    )\n  }\n}\n```\nor using the fs2 Stream specific syntax like `writeS` or the level alternatives for types that provide a `cats.Show` instance \n```scala\nimport cats.Show\nimport cats.effect.Sync\nimport log.effect.LogLevels.Error\nimport log.effect.{ Failure, LogWriter }\nimport log.effect.fs2.syntax._\n\ntrait A\nobject A {\n  def empty: A = ???\n  implicit val aShow: Show[A] = new Show[A] {\n    override def show(t: A): String = ???\n  }\n}\n\ndef double[F[_]: Sync: LogWriter](source: fs2.Stream[F, Int]): fs2.Stream[F, A] = {\n  // Cats Show instances are needed for every logged type\n  implicit def intShow: Show[Int] = ???\n\n  def processAnInt: Int =\u003e A = ???\n\n  (for {\n    n \u003c- source\n    _ \u003c- LogWriter.debugS(\"Processing a number\")\n    _ \u003c- LogWriter.debugS(n) // N.B. the syntax requires a `cats.Show` for `Int`\n    r \u003c- (processAnInt andThen fs2.Stream.emit)(n)\n    _ \u003c- LogWriter.debugS(\"Processed\")\n    _ \u003c- LogWriter.debugS(r) // Same here, a `cats.Show` for `A` is needed\n  } yield r) handleErrorWith { th =\u003e\n    LogWriter.writeS(\n      Error,\n      Failure(\"Ops, something didn't work\", th)\n    ) \u003e\u003e fs2.Stream.emit(A.empty) // and `write again`\n  }\n}\n```\n**NB:** note above the `LogWriter`'s implicit evidence given as context bound and the `import log.effect.fs2.interop.show._`. The latter is needed to summon an `internal.Show` given a `cats.Show`.\n\n## Interop\n\nIn some cases log-effect can be used in projects that have a different logging system already in place. A basic interoperability with other logging libraries is provided in `log-effect-interop`. The supported ones at the moment are\n- log4cats\n\nSee an example below. \n```scala\nlibraryDependencies += \"io.laserdisc\" %% \"log-effect-interop\" % \u003clatest-interop-version\u003e\n```\n```scala\nimport cats.effect.{Resource, Sync}\nimport cats.syntax.flatMap._\nimport io.chrisdavenport.log4cats.Logger\nimport log.effect.LogWriter\n\nimport log.effect.interop.log4cats._\n\nsealed trait RedisClient[F[_]] {\n  def address: String\n  def write: F[Unit]\n}\nobject RedisClient {\n  def apply[F[_]: LogWriter](addr: String)(implicit F: Sync[F]): Resource[F, RedisClient[F]] =\n    Resource.make(\n      F.pure(\n        new RedisClient[F] {\n          val address        = addr\n          def write: F[Unit] = LogWriter.info(address)\n        }\n      )\n    )(_ =\u003e F.unit)\n}\n\ndef buildLog4catsLogger[F[_]]: F[Logger[F]] = ???\n\ndef storeOwnAddress[F[_]: Sync](address: String): F[Unit] =\n  buildLog4catsLogger[F] \u003e\u003e= { implicit l =\u003e\n    RedisClient[F](address).use { cl =\u003e\n      cl.write\n    }\n  }\n```\n**NB:** note the `import log.effect.interop.log4cats._` that enables the derivation of a `LogWriter[F]` when a `log4cats`' `Logger[F]` is in scope.\n\n## License\n\nLog-effect is licensed under the **[MIT License](LICENSE)** (the \"License\"); you may not use this software except in\ncompliance with the License. \u003cbr\u003eUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an\n\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and limitations under the License.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaserdisc-io%2Flog-effect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaserdisc-io%2Flog-effect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaserdisc-io%2Flog-effect/lists"}