From 8fa16119463d2f2c38c9c30a9ad80392b27df5a3 Mon Sep 17 00:00:00 2001 From: Bart van Oort Date: Tue, 21 May 2024 18:12:10 +0200 Subject: [PATCH] docs: update ReadMe and LoggerJSON moduledoc with info about the Elastic formatter --- README.md | 60 +++++++++++++++++++- lib/logger_json.ex | 4 ++ lib/logger_json/formatters/elastic.ex | 2 +- test/logger_json/formatters/elastic_test.exs | 6 +- 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a5dd602..5068606 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,14 @@ A collection of formatters and utilities for JSON-based logging for various clou ## Supported formatters -- [`LoggerJSON.Formatters.Basic`](https://hexdocs.pm/logger_json/LoggerJSON.Formatters.Basic.html) - a basic JSON formatter that logs messages in a structured format, can be used with any JSON-based logging system, like ElasticSearch, Logstash, etc. +- [`LoggerJSON.Formatters.Basic`](https://hexdocs.pm/logger_json/LoggerJSON.Formatters.Basic.html) - a basic JSON formatter that logs messages in a structured, but generic format, can be used with any JSON-based logging system. - [`LoggerJSON.Formatters.GoogleCloud`](https://hexdocs.pm/logger_json/LoggerJSON.Formatters.GoogleCloud.html) - a formatter that logs messages in a structured format that can be consumed by Google Cloud Logger and Google Cloud Error Reporter. - [`LoggerJSON.Formatters.Datadog`](https://hexdocs.pm/logger_json/LoggerJSON.Formatters.Datadog.html) - a formatter that logs messages in a structured format that can be consumed by Datadog. +- [`LoggerJSON.Formatters.Elastic`](https://hexdocs.pm/logger_json/LoggerJSON.Formatters.Elastic.html) - a formatter that logs messages in a structured format that conforms to the [Elastic Common Schema (ECS)](https://www.elastic.co/guide/en/ecs/8.11/ecs-reference.html), so it can be consumed by ElasticSearch, LogStash, FileBeat and Kibana. + ## Installation Add `logger_json` to your list of dependencies in `mix.exs`: @@ -245,6 +247,62 @@ as much as possible. } ``` +## Elastic + +Follows the [Elastic Common Schema (ECS)](https://www.elastic.co/guide/en/ecs/8.11/ecs-reference.html) format. + +```json +{ + "@timestamp": "2024-05-21T15:17:35.374Z", + "ecs.version": "8.11.0", + "log.level": "info", + "log.logger": "Elixir.LoggerJSON.Formatters.ElasticTest", + "log.origin": { + "file.line": 18, + "file.name": "/app/logger_json/test/logger_json/formatters/elastic_test.exs", + "function": "test logs message of every level/1" + }, + "message": "Hello" +} +``` + +When an error is thrown, the message field is populated with the error message and the `error.` fields will be set: + +> Note: when throwing a custom exception type that defines the fields `id` and/or `code`, then the `error.id` and/or `error.code` fields will be set respectively. + +```json +{ + "@timestamp": "2024-05-21T15:20:11.623Z", + "ecs.version": "8.11.0", + "error.message": "runtime error", + "error.stack_trace": "** (RuntimeError) runtime error\n test/logger_json/formatters/elastic_test.exs:191: anonymous fn/0 in LoggerJSON.Formatters.ElasticTest.\"test logs exceptions\"/1\n", + "error.type": "Elixir.RuntimeError", + "log.level": "error", + "message": "runtime error" +} +``` + +Any custom metadata fields will be added to the root of the message, so that your application can fill any other ECS fields that you require: + +> Note that this also allows you to produce messages that do not strictly adhere to the ECS specification. + +```json +// with Logger.metadata(:"device.model.name": "My Awesome Device") +{ + "@timestamp": "2024-05-21T15:17:35.374Z", + "ecs.version": "8.11.0", + "log.level": "info", + "log.logger": "Elixir.LoggerJSON.Formatters.ElasticTest", + "log.origin": { + "file.line": 18, + "file.name": "/app/logger_json/test/logger_json/formatters/elastic_test.exs", + "function": "test logs message of every level/1" + }, + "message": "Hello", + "device.model.name": "My Awesome Device" +} +``` + ## Copyright and License Copyright (c) 2016 Andrew Dryga diff --git a/lib/logger_json.ex b/lib/logger_json.ex index 7751123..0172754 100644 --- a/lib/logger_json.ex +++ b/lib/logger_json.ex @@ -13,6 +13,10 @@ defmodule LoggerJSON do * `LoggerJSON.Formatters.Datadog` - a formatter that logs messages in a structured format that can be consumed by Datadog. + * `LoggerJSON.Formatters.Elastic` - a formatter that logs messages in a structured format that conforms to the + [Elastic Common Schema (ECS)](https://www.elastic.co/guide/en/ecs/8.11/ecs-reference.html), + so it can be consumed by ElasticSearch, LogStash, FileBeat and Kibana. + ## Installation Add `logger_json` to your list of dependencies in `mix.exs`: diff --git a/lib/logger_json/formatters/elastic.ex b/lib/logger_json/formatters/elastic.ex index 15e9f2e..d6bbad0 100644 --- a/lib/logger_json/formatters/elastic.ex +++ b/lib/logger_json/formatters/elastic.ex @@ -207,7 +207,7 @@ defmodule LoggerJSON.Formatters.Elastic do %{ "log.logger": module, "log.origin": %{ - "file.name": file, + "file.name": to_string(file), "file.line": line, function: "#{function}/#{arity}" } diff --git a/test/logger_json/formatters/elastic_test.exs b/test/logger_json/formatters/elastic_test.exs index 2c7bc6e..b50b521 100644 --- a/test/logger_json/formatters/elastic_test.exs +++ b/test/logger_json/formatters/elastic_test.exs @@ -36,8 +36,8 @@ defmodule LoggerJSON.Formatters.ElasticTest do assert {:ok, _, _} = DateTime.from_iso8601(timestamp) assert origin_line > 0 - assert String.ends_with?(to_string(origin_file), "test/logger_json/formatters/elastic_test.exs") - assert String.starts_with?(to_string(origin_function), "test logs message of every level/1") + assert String.ends_with?(origin_file, "test/logger_json/formatters/elastic_test.exs") + assert String.starts_with?(origin_function, "test logs message of every level/1") assert log_entry["domain"] == nil end end @@ -197,6 +197,8 @@ defmodule LoggerJSON.Formatters.ElasticTest do end) |> decode_or_print_error() + Jason.encode_to_iodata!(log_entry, pretty: true) |> IO.puts() + assert %{ "message" => "runtime error", "error.message" => "runtime error",