{"id":18425566,"url":"https://github.com/atomix/dazl","last_synced_at":"2025-04-07T16:31:48.771Z","repository":{"id":152129414,"uuid":"625060284","full_name":"atomix/dazl","owner":"atomix","description":"Configurable abstraction layer for Go logging frameworks","archived":false,"fork":false,"pushed_at":"2023-04-21T21:45:19.000Z","size":177,"stargazers_count":19,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T05:05:11.589Z","etag":null,"topics":["framework","go","golang","logging"],"latest_commit_sha":null,"homepage":"","language":"Go","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/atomix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSES/Apache-2.0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-08T00:40:14.000Z","updated_at":"2023-11-09T17:03:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"3b45a9ca-1076-446e-9fdf-9c742a161758","html_url":"https://github.com/atomix/dazl","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fdazl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fdazl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fdazl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fdazl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomix","download_url":"https://codeload.github.com/atomix/dazl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247687972,"owners_count":20979571,"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":["framework","go","golang","logging"],"created_at":"2024-11-06T05:04:23.957Z","updated_at":"2025-04-07T16:31:48.298Z","avatar_url":"https://github.com/atomix.png","language":"Go","readme":"\u003c!--\nSPDX-FileCopyrightText: 2023-present Intel Corporation\nSPDX-License-Identifier: Apache-2.0\n--\u003e\n\n# dazl\n\n[![build](https://img.shields.io/github/actions/workflow/status/atomix/dazl/test.yml)](https://github.com/atomix/dazl/actions/workflows/test.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/atomix/dazl)](https://goreportcard.com/report/github.com/atomix/dazl)\n[![codecov](https://codecov.io/gh/atomix/dazl/branch/master/graph/badge.svg?token=NTBMFA3GIN)](https://codecov.io/gh/atomix/dazl)\n[![license](https://img.shields.io/badge/License-Apache_2.0-blue.svg?label=license)](https://opensource.org/licenses/Apache-2.0)\n[![reference](https://pkg.go.dev/badge/github.com/atomix/dazl)](https://pkg.go.dev/github.com/atomix/dazl)\n\n## Configurable abstraction layer for Go logging frameworks\n\nDazl is not just another Go logging framework. We're not here to reinvent Go logging for the nth time. Dazl is an\nabstraction layer that provides a unified interface and configuration format on top of existing logging frameworks,\nusing a proven approach adapted from popular frameworks in other languages like [slf4j](https://slf4j.org).\n\nDazl is a pluggable logging abstraction with support for multiple existing backend frameworks:\n* [zap](https://github.com/uber-go/zap)\n* [zerolog](https://github.com/rs/zerolog)\n\nDazl loggers add numerous features on top of existing frameworks:\n* Decouples Go libraries from specific logging implementations\n* Makes logging configurable via YAML configuration files\n* Structured logging with support for JSON or console encoding and user-defined fields\n* Hierarchical loggers, inheritance, sampling and other advanced features\n* Supports runtime configuration changes for easy debugging\n\n# User Guide\n\n* [Use cases](#use-cases)\n  * [Logging in Go libraries](#logging-in-go-libraries)\n  * [Configuration of Go services](#configuration-of-go-application-logging)\n* [Getting started](#getting-started)\n  * [Add the dazl dependency](#add-the-dazl-dependencies)\n  * [Import a logging backend](#import-a-logging-backend)\n  * [Configure logging](#configure-logging)\n  * [Run the application](#run-the-application)\n* [Go API](#go-api)\n  * [Initializing the framework](#initializing-the-logging-framework)\n  * [Working with loggers](#loggers)\n  * [Log levels](#log-levels)\n  * [Structured logging](#structured-logging)\n* [Configuration files](#configuration-files)\n  * [Encoders](#encoders)\n    * [JSON](#json-encoder)\n    * [Console](#console-encoder)\n  * [Writers](#configuring-writers)\n  * [Loggers](#configuring-loggers)\n  * [Reference](#reference)\n* [Runtime configuration changes](#runtime-configuration-changes)\n  * [Changing the log level](#changing-the-log-level)\n* [Custom logging frameworks](#custom-logging-frameworks)\n  * [Custom encoders](#encoding)\n  * [Custom writers](#log-writers)\n\n## Use cases\n\nThere are numerous benefits to using a logging abstraction, but dazl is designed to serve a couple of important use \ncases for two types of applications in particular.\n\n### Logging in Go libraries\n\nGo libraries designed to be imported and used by other Go modules can use dazl to avoid adding a dependency on a \nspecific logging framework, tying their users to the same framework. Additionally, dazl enables your users to configure\nloggers and log formats indepenedently, with no added work for you. The users of your library ought to be able to\nselect their own logging framework and configure the format and severity of log outputs. Simply add a dependency on\nthe dazl logger, and leave it up to your users to import whichever logging backend they desire.\n\n### Configuration of Go application logging\n\nOne of the most common use cases for Go applications is in cloud applications deployed in containers and on platforms\nlike Kubernetes. Most Go logging frameworks provide programmatic APIs for configuring loggers, levels, formats, and\nother logging options. Using dazl in Go-based services enables your users to configure logging independent of the\ncode, eliminating the need to recompile code to modify the verbosity or format of application logs.\n\n# Getting started\n\n## Add the dazl dependencies\n\nTo start using dazl, first add the framework to your `go.mod`:\n\n```bash\ngo get -u github.com/atomix/dazl\n```\n\nAdditionally, add the dependency for one of the [logging backends](#initializing-the-logging-framework)L\n\n```bash\ngo get -u github.com/atomix/dazl/zap\n```\n\n## Import a logging backend\n\nImport the logging backend in your module `main`:\n\n`main.go`\n```go\npackage main\n\nimport (\n    \"github.com/atomix/dazl\"\n    _ \"github.com/atomix/dazl/zap\"\n)\n\nvar log = dazl.GetLogger()\n\nfunc main() {\n    log.Info(\"Hello world!\")\n}\n```\n\nTo avoid adding unnecessary dependencies on logging frameworks, logging backends should only be imported within\nyour module `main`.\n\n## Configure logging\n\nCreate a `logging.yaml` file to configure the logging framework:\n\n`logging.yaml`\n```yaml\nencoders:\n  json:\n    fields:\n      - message\n      - level:\n          format: uppercase\n      - caller:\n          format: short\n      - timestamp:\n          format: iso8601\n\nwriters:\n  stdout:\n    encoder: json\n\nrootLogger:\n  level: info\n  outputs:\n    - stdout\n```\n\nTo print logs to an output, the `logging.yaml` configuration must configure one or more `writers` and configure the\n`rootLogger` or child `loggers` with `outputs` to output messages from those loggers to the configured writer(s).\n\n## Run the application\n\nFinally, when you run the application `main` from the same directory as your `logging.yaml` file, you should see\nthe logs printed to stdout:\n\n```bash\ngo run ./main.go\n```\n\nFor more information [check out the example module](./examples).\n\n# Go API\n\n## Initializing the logging framework\n\nThe dazl logger does not log to any output unless a logging framework is imported. To maintain independence from any\nparticular logging backend, applications should only import a specific logging framework from within a `main` file.\nLibraries designed to be imported by other projects should never import a logging backend themselves. Instead, leave\nthe specific logging framework implementation up to your users.\n\nThe logging backend is configured by importing the framework into your application's `main` package.\n\n### Logging with zap\n\nTo configure dazl to use the [zap](https://github.com/uber-go/zap) logging backend, add the `zap` framework\nto your module's `go.mod`:\n\n```bash\ngo get -u github.com/atomix/dazl/zap\n```\n\nThen import the `github.com/atomix/dazl/zap` framework implementation in your `main` package:\n\n```go\npackage main\n\nimport _ \"github.com/atomix/dazl/zap\"\n\nfunc main() {\n    ...\n}\n```\n\n### Logging with zerolog\n\nTo configure dazl to use the [zerolog](https://github.com/rs/zerolog) logging backend, add the `zerolog` framework\nto your module's `go.mod`:\n\n```bash\ngo get -u github.com/atomix/dazl/zerolog\n```\n\nThen import the `github.com/atomix/dazl/zerolog` framework implementation in your `main` package:\n\n```go\npackage main\n\nimport _ \"github.com/atomix/dazl/zerolog\"\n\nfunc main() {\n    ...\n}\n```\n\n## Loggers\n\nThe typical usage of the framework is to create a `Logger` once at the top of each Go package:\n\n```go\nvar log = dazl.GetLogger()\n```\n\nPackage loggers are assigned the name of the package calling `GetLogger()` or `GetPackageLogger()`. So, if you\ncall `dazl.GetLogger()` from the `github.com/atomix/atomix/runtime` package, the logger will be assigned the\nname `github.com/atomix/atomix/runtime`. The naming strategy becomes important for\n[logger configuration](#configuration) and, in particular, [inheritance](#inheritance).\n\n```go\nconst author = \"kuujo\"\n\nvar log = dazl.GetLogger()\n\nfunc main() {\n    log.Infof(\"The author of dazl is %s\", author)\n}\n```\n\n```\n2023-03-31T01:13:30.607Z\tINFO\tmain.go:12\tThe author of dazl is kuujo\n```\n\nAlternatively, custom loggers can be retrieved via `GetLogger`:\n\n```go\nvar log = dazl.GetLogger(\"foo/bar\")\n```\n\nLogger names must be formatted in path format, with each element separated by a `/`. This format is used\nto establish a hierarchy for [inheritence](#inheritance) of logger configurations.\n\nAll loggers are descendants of the root logger:\n\n```go\nvar log = dazl.GetRootLogger()\n```\n\n## Log levels\n\nDazl supports a fairly standard set of log levels for loggers:\n\n* `debug`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `panic`\n\nThe levels for each logger can be configured individually via their configuration:\n\n```yaml\nloggers:\n  github.com/atomix/atomix/runtime:\n    level: warn\n```\n\nThe `Logger` interface exposes methods for simple logging, formatted logging, and structured logging with typed\nfields for each log level:\n* `Debug(args ...any)`\n* `Debugf(msg string, args ...any)`\n* `Debugw(msg string, fields ...Field)`\n* `Info(args ...any)`\n* `Infof(msg string, args ...any)`\n* `Infow(msg string, fields ...Field)`\n* `Warn(args ...any)`\n* `Warnf(msg string, args ...any)`\n* `Warnw(msg string, fields ...Field)`\n* ...\n\nMessages will only be written to log [outputs](#outputs) if the configured level of the logger is higher than the\nmessage level.\n\n## Structured logging\n\nStructured logging is supported for the JSON [encoding](#encodings), and JSON fields are configurable via\nthe `Logger` API.\n\nThe simplest way to add fields to your structured logs is to call one of the `*w` methods on the `Logger` interface.\nThese methods accept an arbitrary number of `...Field`s to write to the logs. Fields are typed and named values\nthat can be constructed via functions in the `dazl` package:\n\n```go\nlog.Warnw(\"Something went wrong!\", \n    dazl.String(\"user\", user.Name), \n    dazl.Uint64(\"user-id\", user.ID))\n```\n\nAlternatively, you can create a structured logger with a fixed set of fields using the `WithFields` method:\n\n```go\nvar log = dazl.GetLogger().WithFields(\n    dazl.String(\"user\", user.Name),\n    dazl.Uint64(\"id\", user.ID))\nlog.Warn(\"Something went wrong!\")\n```\n\nWhen the logger is output to a JSON encoded writer, the above code will log the fields as part of the JSON object:\n\n```\n{\"timestamp\":\"2023-04-07T19:24:09-07:00\",\"logger\":\"2/4\",\"message\":\"Something went wrong!\",\"user\":\"Jordan Halterman\",\"id\":5678}\n```\n\n# Configuration files\n\nLoggers can be configured via a YAML configuration file. The configuration files may be in one of many\nlocations on the file system:\n\n* `logging.yaml`\n* `~/logging.yaml`\n* `/etc/dazl/logging.yaml`\n\nThe configuration file contains a set of `loggers` which specifies the level and outputs of each logger,\n`writers` which specify where to write log messages, and `encoders` defining how to encode log messages.\n\n## Configuring encoders\n\nThe `encoders` section of the configuration defines how dazl encodes log messages. Dazl supports two\nencodings: `json` and `console`. Each encoder defines the set of `fields` to output and optionally the\nformat of the fields.\n\n```yaml\nencoders:\n  json:\n    fields:\n      ...\n  console:\n    fields:\n      ...\n```\n\nEncoders are referenced by [`writers`](#configuring-writers) and used to encode messages.\n\nNote that support for some encoding options such as renaming keys or formatting fields depends on whether those\nfeatures are supported the underlying logging framework. If some requested features are not supported by the\nimported logging framework, dazl may panic at startup.\n\n### JSON encoder\n\nThe `json` encoder configuration defines the set of fields to include in all JSON formatted messages. Each\nJSON field also supports an additional `key` to override the default JSON key for that field:\n\n```yaml\nencoders:\n  json:\n    # A list of fields to include\n    fields:\n      # The log message\n      - message:\n          # The JSON key for the field\n          key: msg\n      # The logger name\n      - name:\n          # The JSON key for the field\n          key: logger\n      # The log level\n      - level:\n          # The JSON key for the field\n          key: level\n          # The level format: 'uppercase' or 'lowercase'\n          format: uppercase\n      # The time at which the message was logged\n      - timestamp:\n          # The JSON key for the field\n          key: time\n          # The time format: 'iso8601' or 'unix'\n          format: iso8601\n      # The line of code at which the message was logged\n      - caller:\n          # The JSON key for the field\n          key: caller\n          # The caller format: 'short' or 'long'\n          format: short\n      # The log stacktrace\n      - stacktrace:\n          # The JSON key for the field\n          key: trace\n```\n\n### Console encoder\n\nThe `console` encoder configuration defines the colums to encode with each log message:\n\n```yaml\nencoders:\n  console:\n    # A list of fields to include\n    fields:\n      # The log message\n      - message\n      # The logger name\n      - name\n      # The log level\n      - level:\n          # The level format: 'uppercase' or 'lowercase'\n          format: uppercase\n      # The time at which the message was logged\n      - timestamp:\n          # The time format: 'iso8601' or 'unix'\n          format: iso8601\n      # The line of code at which the message was logged\n      - caller:\n          # The caller format: 'short' or 'long'\n          format: short\n      # The log stacktrace\n      - stacktrace\n```\n\n## Encoder fields\n\nBoth the `json` and `console` encoders support the following set of fields:\n* `message`\n* `name`\n* `level`\n* `timestamp`\n* `caller`\n* `stacktrace`\n\nIf any field is excluded from the encoder's field list, dazl will _attempt_ to exclude that field from the log\noutput, but some logging backends may not support this ability and therefore may include those fields in their output.\n\n### Level formats\n\nThe format of the log level can be configured for each encoder via the `format` key:\n\n```yaml\nencoders:\n  json:\n    level:\n      format: uppercase\n```\n\nDefined level formats include:\n* `uppercase` - upper case level name\n* `lowercase` - lower case level name\n\nNote that support for level formats depends on support from the imported logging backend. Dazl may panic at startup\nif the underlying logging framework does not support the configured level format.\n\n### Timestamp formats\n\nThe format of the timestamp can be configured for each encoder via the `format` key:\n\n```yaml\nencoders:\n  json:\n    timestamp:\n      format: ISO8601\n```\n\nDefined timestamp formats include:\n* `ISO8601`\n* `unix`\n\nNote that support for timestamp formats depends on support from the imported logging backend. Dazl may panic at startup\nif the underlying logging framework does not support the configured timestamp format.\n\n### Caller formats\n\nThe format of the caller can be configured for each encoder via the `format` key:\n\n```yaml\nencoders:\n  json:\n    caller:\n      format: uppercase\n```\n\nDefined caller formats include:\n* `short`\n* `full`\n\nNote that support for caller formats depends on support from the imported logging backend. Dazl may panic at startup\nif the underlying logging framework does not support the configured level format.\n\n## Configuring writers\n\n```yaml\n# A set of named writers for loggers to write to.\n# All writers must specify an 'encoder' to use\nwriters:\n  # The stdout writer\n  stdout:\n    # The name of the encoder to use for the writer\n    encoder: console\n  # The stderr writer\n  stderr:\n    # The name of the encoder to use for the writer\n    encoder: console\n  # Remaining writers are files\n  file:\n    # The path to the file\n    path: ./example.log\n    # The name of the encoder to use for the writer\n    encoder: json\n```\n\n## Configuring loggers\n\n### The root logger\n\nThe default logging configuration is configured via the `rootLogger` key:\n\n```yaml\nrootLogger:\n  level: info\n```\n\nAll loggers inherit their default configuration from the root logger. The root logger configuration should at\nleast specify a minimum log `level` for all loggers, and at least one `outputs` to a [writer](#writers).\n\n```yaml\nrootLogger:\n  level: info\n  outputs:\n    - stdout\n```\n\n### Named loggers\n\nOnce the `rootLogger` has been defined, all other loggers that are descendants of the root logger may be defined and\nconfigured in the `loggers` section of the configuration file:\n\n```yaml\nloggers:\n  github.com/atomix/atomix/runtime:\n    level: info\n  github.com/atomix/atomix/sidecar:\n    level: warn\n```\n\n### Outputs\n\nOnce you've defined the set of writers to which to write your application logs, named loggers can be directed to\nthose writers via their configured `outputs`:\n\n```yaml\nrootLogger:\n  level: info\n  outputs:\n    - stdout\n```\n\nEach output must specify a `writer` to write to. As with log levels, loggers inherit the outputs of their ancestors, so\nwith an output to the `stdout` writer in the root logger configuration, all loggers will have an output to `stdout`.\n\n### Output levels\n\nIn some cases, you may want to restrict the verbosity of logs to one output without restricting the verbosity of all\nmessages for a logger. For example, you may want to write `info` and higher messages to the console for\nhuman readability, and `debug` and higher messages to a file for later debugging. Each output supports a `level`\nthat can be used to filter the logs to that output:\n\n```yaml\nloggers:\n  github.com/atomix/atomix:\n    # Pass through all messages over 'debug' level to the outputs\n    level: debug\n    outputs:\n      # Limit the messages from this logger to stdout to 'info' level\n      - stdout:\n          level: info\n      # Pass through all messages to the 'file' writer\n      - file\n\nwriters:\n  stdout:\n    encoder: console\n  file:\n    path: ./app.log\n    encoder: json\n```\n\n### Output overrides\n\nDescendants may override their ancestor loggers' output configurations. This can be done by simply specifying the\nsame output name. For example, to override the log level for the `rootLogger`'s `stdout` output:\n\n```yaml\n# Configure the stdout writer to use console encoding\nwriters:\n  stdout:\n    encoder: console\n\nrootLogger:\n  level: info\n  outputs:\n    # Output the root logger to stdout\n    - stdout\n\nloggers:\n  github.com/atomix/atomix/runtime:\n    outputs:\n      # Limit outputs from this logger to stdout to minimum of 'warn' level\n      stdout:\n        level: warn\n```\n\n### Sampling\n\nSamplers can be added to either loggers to reduce the number of messages logged:\n\n```yaml\nloggers:\n  github.com/atomix/atomix/runtime:\n    sample:\n      basic:\n        interval: 10\n```\n\nSamplers can also be added to individual outputs to limit only the messages to that particular output:\n\n```yaml\nloggers:\n  github.com/atomix/atomix/runtime:\n    outputs:\n      stdout:\n        sample:\n          basic:\n            interval: 10\n```\n\n### Basic sampler\n\nThe `basic` sampler logs every nth message below `maxLevel` according to the configured `interval`:\n\n```yaml\nloggers:\n  github.com/atomix/atomix/runtime:\n    sample:\n      basic:\n        interval: 10\n        maxLevel: debug\n```\n\n### Random sampler\n\nThe `random` sampler randomly logs messages below `maxLevel` by choosing a random integer between `0` and `interval`:\n\n```yaml\nloggers:\n  github.com/atomix/atomix/runtime:\n    sample:\n      random:\n        interval: 10\n        maxLevel: debug\n```\n\n### Inheritance\n\nThe path-like format used for logger names is used to establish a hierarchy of loggers. The dazl configuration\nenables developers and their users to configure individual loggers at runtime. Log levels are inherited by\ndescendants of a logger. This enables users to easily enable logging for specific Go packages, their subpackages,\nor entire Go modules with a single configuration change:\n\n```yaml\n# Enable debug logging for all Atomix code\nloggers:\n  github.com/atomix:\n    level: debug\n```\n\nYou can set the `dazl.Level` for a logger at startup time via configuration files or at runtime\nvia the `Logger` API to control the granularity of a logger's output:\n\n```go\ndazl.GetLogger(\"github.com/atomix\").SetLevel(dazl.DebugLevel)\n```\n\nThe root logger is the ancestor of all other loggers and can be configured via `GetRootLogger`:\n\n```go\ndazl.GetRootLogger().SetLevel(dazl.InfoLevel)\n```\n\nIf the level for a logger is not explicitly set, it will inherit its level from its nearest ancestor in\nthe logger hierarchy. For example, setting the `github.com/atomix/atomix/runtime` logger to the `debug`\nlevel will change the loggers for all loggers in the `github.com/atomix/atomix/runtime/...` packages\nto the `debug` level.\n\n## Reference\n\nA [reference configuration file](./examples/reference.yaml) detailing and documenting all the available configuration \noptions in `logging.yaml` is available in the [examples](./examples) directory of this repo.\n\n# Runtime configuration changes\n\n## Changing the log level\n\nYou can set the `dazl.Level` for a logger at startup time via configuration files or at runtime\nvia the `Logger` API to control the granularity of a logger's output:\n\n```go\ndazl.GetLogger(\"github.com/atomix\").SetLevel(dazl.DebugLevel)\n```\n\nThe root logger is the ancestor of all other loggers and can be configured via `GetRootLogger`:\n\n```go\ndazl.GetRootLogger().SetLevel(dazl.InfoLevel)\n```\n\n# Custom logging frameworks\n\nDazl provides several existing implementations of logging frameworks:\n\n* [zap](./zap/framework.go)\n* [zerolog](./zerolog/framework.go)\n\nLogging frameworks are implemented by implementing the `Framework` interface:\n\n```go\nconst name = \"example\"\n\ntype Framework struct{}\n\nfunc (f Framework) Name() string {\n    return name\n}\n```\n\nFrameworks should register when imported:\n\n```go\nfunc init() {\n    dazl.Register(\u0026Framework{})\n}\n```\n\n## Encoding\n\n`Framework` implementations should implement one or more of the `*EncodingFramework` interfaces to indicate support\nfor encoding formats. Frameworks implement these interfaces to provide `Encoder`s which are used by dazl to create new\n`Writer`s:\n\n```go\ntype JSONEncoder struct{}\n\nfunc (e *JSONEncoder) NewWriter(writer io.Writer) (dazl.Writer, error) {\n    ...\n}\n```\n\n## JSON encoding\n\nTo implement support for JSON encoding, implement the `JSONEncodingFramework` interface:\n\n```go\nfunc (f Framework) JSONEncoder() Encoder {\n    return \u0026JSONEncoder{}\n}\n```\n\n## Console encoding\n\nTo implement support for JSON encoding, implement the `ConsoleEncodingFramework` interface:\n\n```go\nfunc (f Framework) ConsoleEncoder() Encoder {\n    return \u0026ConsoleEncoder{}\n}\n```\n\n## Encoding options\n`Encoder` implementations may support configuration options by implementing optional interfaces with the\nfollowing methods:\n\n* `WithMessageKey(key string) (dazl.Encoder, error)`\n* `WithNameEnabled() (dazl.Encoder, error)`\n* `WithNameKey(key string) (dazl.Encoder, error)`\n* `WithLevelEnabled() (dazl.Encoder, error)`\n* `WithLevelKey(key string) (dazl.Encoder, error)`\n* `WithLevelFormat(format dazl.LevelFormat) (dazl.Encoder, error)`\n* `WithTimestampEnabled() (dazl.Encoder, error)`\n* `WithTimestampKey(key string) (dazl.Encoder, error)`\n* `WithTimestampFormat(format dazl.TimestampFormat) (dazl.Encoder, error)`\n* `WithCallerEnabled() (dazl.Encoder, error)`\n* `WithCallerKey(key string) (dazl.Encoder, error)`\n* `WithCallerFormat(format dazl.CallerFormat) (dazl.Encoder, error)`\n* `WithStacktraceEnabled() (dazl.Encoder, error)`\n* `WithStacktraceKey(key string) (dazl.Encoder, error)`\n\n## Log writers\n\n`Encoder`s create `Writer`s for use by the dazl `Logger`. All `Writer`s must implement the following methods:\n\n* `WithName(name string) dazl.Writer`\n* `WithSkipCalls(calls int) dazl.Writer`\n* `Debug(msg string)`\n* `Info(msg string)`\n* `Warn(msg string)`\n* `Error(msg string)`\n* `Panic(msg string)`\n* `Fatal(msg string)`\n\n### Writer options\n\n`Writer` implementations may optionally support additional features by implementing optional interfaces\nby adding the following methods:\n\n* `WithStringField(name string, value string) dazl.Writer`\n* `WithIntField(name string, value int) dazl.Writer`\n* `WithInt32Field(name string, value int32) dazl.Writer`\n* `WithInt64Field(name string, value int64) dazl.Writer`\n* `WithUintField(name string, value uint) dazl.Writer`\n* `WithUint32Field(name string, value uint32) dazl.Writer`\n* `WithUint64Field(name string, value uint64) dazl.Writer`\n* `WithFloat32Field(name string, value float32) dazl.Writer`\n* `WithFloat64Field(name string, value float64) dazl.Writer`\n* `WithBoolField(name string, value bool) dazl.Writer`\n* `WithStringSliceField(name string, values []string) dazl.Writer`\n* `WithIntSliceField(name string, values []int) dazl.Writer`\n* `WithInt32SliceField(name string, values []int32) dazl.Writer`\n* `WithInt64SliceField(name string, values []int64) dazl.Writer`\n* `WithUintSliceField(name string, values []uint) dazl.Writer`\n* `WithUint32SliceField(name string, values []uint32) dazl.Writer`\n* `WithUint64SliceField(name string, values []uint64) dazl.Writer`\n* `WithFloat32SliceField(name string, values []float32) dazl.Writer`\n* `WithFloat64SliceField(name string, values []float64) dazl.Writer`\n* `WithBoolSliceField(name string, values []bool) dazl.Writer`\n* `WithErrorField(name string, err error) dazl.Writer`\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomix%2Fdazl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomix%2Fdazl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomix%2Fdazl/lists"}