Skip to content

Commit

Permalink
feat: accepts LOGGING_BACKEND=INK for json logging (#1352)
Browse files Browse the repository at this point in the history
* use Ink for multiline logs in datadog, expand Sentry tags

* default Ink module attr

* default Ink module attr

* set logger in every application

* new line and dots
  • Loading branch information
Ino Murko authored Feb 26, 2020
1 parent 1b5c2ec commit fb4742b
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 58 deletions.
55 changes: 55 additions & 0 deletions apps/omg_status/lib/omg_status/release_tasks/set_logger.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2019-2019 OmiseGO Pte Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

defmodule OMG.Status.ReleaseTasks.SetLogger do
@moduledoc false
use Distillery.Releases.Config.Provider
require Logger

@app :logger
@default_backend Ink

@impl Provider
def init(_) do
logger_backends = Application.get_env(@app, :backends, persistent: true)
logger_backend = get_logger_backend()

remove =
case logger_backend do
:console -> Ink
_ -> :console
end

backends = logger_backends |> Kernel.--([remove]) |> Enum.concat([logger_backend]) |> Enum.uniq()
:ok = Application.put_env(@app, :backends, backends, persistent: true)
end

defp get_logger_backend() do
logger =
"LOGGER_BACKEND"
|> get_env()
|> validate_string(@default_backend)

_ = Logger.info("CONFIGURATION: App: #{@app} Key: LOGGER_BACKEND Value: #{inspect(logger)}.")
logger
end

defp get_env(key), do: System.get_env(key)

defp validate_string(nil, default), do: default
defp validate_string(value, default), do: do_validate_string(String.upcase(value), default)
defp do_validate_string("CONSOLE", _default), do: :console
defp do_validate_string("INK", _default), do: Ink
defp do_validate_string(_, default), do: default
end
21 changes: 6 additions & 15 deletions apps/omg_status/lib/omg_status/release_tasks/set_sentry.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule OMG.Status.ReleaseTasks.SetSentry do
@app :sentry
@impl Provider

def init(_args) do
def init(release: release, current_version: current_version) do
_ = Application.ensure_all_started(:logger)
app_env = get_app_env()
sentry_dsn = System.get_env("SENTRY_DSN")
Expand All @@ -45,9 +45,12 @@ defmodule OMG.Status.ReleaseTasks.SetSentry do

:ok =
Application.put_env(@app, :tags, %{
application: get_application(),
application: release,
eth_network: get_env("ETHEREUM_NETWORK"),
eth_node: get_rpc_client_type()
eth_node: get_rpc_client_type(),
current_version: "vsn-#{current_version}",
app_env: "#{app_env}",
hostname: "#{hostname}"
})

_ ->
Expand Down Expand Up @@ -77,18 +80,6 @@ defmodule OMG.Status.ReleaseTasks.SetSentry do
hostname
end

defp get_application() do
app =
case Code.ensure_loaded?(OMG.Watcher) do
true -> :watcher
_ -> :child_chain
end

_ = Logger.info("CONFIGURATION: App: #{@app} Key: application Value: #{inspect(app)}.")

app
end

defp get_rpc_client_type() do
rpc_client_type = validate_rpc_client_type(get_env("ETH_NODE"), Application.get_env(@app, :tags)[:eth_node])
_ = Logger.info("CONFIGURATION: App: #{@app} Key: ETH_NODE Value: #{inspect(rpc_client_type)}.")
Expand Down
1 change: 1 addition & 0 deletions apps/omg_status/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ defmodule OMG.Status.Mixfile do
{:spandex_datadog, "~> 0.4"},
{:decorator, "~> 1.2"},
{:vmstats, "~> 2.3", runtime: false},
{:ink, "~> 1.0"},
# umbrella apps
{:omg_bus, in_umbrella: true}
]
Expand Down
61 changes: 61 additions & 0 deletions apps/omg_status/test/omg_status/release_tasks/set_logger_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright 2019-2020 OmiseGO Pte Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

defmodule OMG.Status.ReleaseTasks.SetLoggerTest do
use ExUnit.Case, async: false
alias OMG.Status.ReleaseTasks.SetLogger
@app :logger
setup_all do
logger_backends = Application.get_env(@app, :backends, persistent: true)

on_exit(fn ->
:ok = Application.put_env(@app, :backends, logger_backends)
:ok = System.delete_env("LOGGER_BACKEND")
end)

:ok
end

setup do
:ok = System.delete_env("LOGGER_BACKEND")
end

test "if environment variables (INK) get applied in the configuration" do
:ok = System.put_env("LOGGER_BACKEND", "INK")
:ok = SetLogger.init([])
configuration = Application.get_env(@app, :backends)
assert Enum.member?(configuration, Ink) == true
end

test "if environment variables (CONSOLE) get applied in the configuration" do
# env var to console and asserting that Ink gets removed
:ok = System.put_env("LOGGER_BACKEND", "conSole")
:ok = SetLogger.init([])
configuration = Application.get_env(@app, :backends)
assert Enum.member?(configuration, :console) == true
assert Enum.member?(configuration, Ink) == false
end

test "if environment variables are not present the default configuration gets used (INK)" do
# in mix_env == test the default logger is :console and Sentry.LoggerBackend
# we want to test our production default setting which is Ink and Sentry.LoggerBackend
# so we modify the configuration first so that it looks like in mix env prod
Application.put_env(@app, :backends, [Ink, Sentry.LoggerBackend], persistent: true)
# we continue with setting the backend to console and asserting that Ink gets removed
:ok = SetLogger.init([])
configuration = Application.get_env(@app, :backends)
assert Enum.member?(configuration, :console) == false
assert Enum.member?(configuration, Ink) == true
end
end
29 changes: 18 additions & 11 deletions apps/omg_status/test/omg_status/release_tasks/set_sentry_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule OMG.Status.ReleaseTasks.SetSentryTest do
:ok = System.put_env("APP_ENV", "YOLO")
:ok = System.put_env("HOSTNAME", "server name")
:ok = System.put_env("ETHEREUM_NETWORK", "RINKEBY")
:ok = SetSentry.init([])
:ok = SetSentry.init(release: :watcher, current_version: "current_version")
configuration = Enum.sort(Application.get_all_env(@app))
dsn = configuration[:dsn]
app_env = configuration[:environment_name]
Expand All @@ -64,18 +64,25 @@ defmodule OMG.Status.ReleaseTasks.SetSentryTest do
"RINKEBY" = Map.get(tags, :eth_network)
:geth = Map.get(tags, :eth_node)

^configuration =
@configuration_old
|> Keyword.put(:dsn, "/dsn/dsn/dsn")
|> Keyword.put(:environment_name, "YOLO")
|> Keyword.put(:included_environments, ["YOLO"])
|> Keyword.put(:server_name, "server name")
|> Keyword.put(:tags, %{application: :watcher, eth_network: "RINKEBY", eth_node: :geth})
|> Enum.sort()
assert configuration ==
@configuration_old
|> Keyword.put(:dsn, "/dsn/dsn/dsn")
|> Keyword.put(:environment_name, "YOLO")
|> Keyword.put(:included_environments, ["YOLO"])
|> Keyword.put(:server_name, "server name")
|> Keyword.put(:tags, %{
application: :watcher,
eth_network: "RINKEBY",
eth_node: :geth,
app_env: "YOLO",
current_version: "vsn-current_version",
hostname: "server name"
})
|> Enum.sort()
end

test "if sentry is disabled if there's no SENTRY DSN env var set" do
:ok = SetSentry.init([])
:ok = SetSentry.init(release: :child_chain, current_version: "current_version")
configuration = Enum.sort(Application.get_all_env(@app))
dsn = configuration[:dsn]
app_env = configuration[:environment_name]
Expand Down Expand Up @@ -106,7 +113,7 @@ defmodule OMG.Status.ReleaseTasks.SetSentryTest do
:ok = System.put_env("SENTRY_DSN", "/dsn/dsn/dsn")

try do
SetSentry.init([])
SetSentry.init(release: :child_chain, current_version: "current_version")
catch
:exit, _reason ->
:ok
Expand Down
1 change: 1 addition & 0 deletions bin/variables
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export EXIT_PROCESSOR_SLA_MARGIN=5520
export FEE_CLAIMER_ADDRESS=0x3b9f4c1dd26e0be593373b1d36cee2008cbeb837
export DD_HOSTNAME=localhost
export DD_DISABLED=false
export LOGGER_BACKEND=console
# expects it's executed from the root of the project
FILE='./localchain_contract_addresses.env'
while IFS= read -r line; do
Expand Down
9 changes: 8 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ config :logger, :console,
metadata: [:module, :function, :request_id, :trace_id, :span_id]

config :logger,
backends: [:console]
backends: [Sentry.LoggerBackend, Ink]

config :logger, Ink,
name: "elixir-omg"

config :logger, Sentry.LoggerBackend,
include_logger_metadata: true,
ignore_plug: true

config :sentry,
dsn: nil,
Expand Down
3 changes: 3 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
use Mix.Config

config :logger,
backends: [:console, Sentry.LoggerBackend]
3 changes: 3 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use Mix.Config

config :logger, level: :warn

config :logger,
backends: [:console, Sentry.LoggerBackend]

config :sentry,
dsn: nil,
environment_name: nil,
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ services:
- ETHEREUM_EVENTS_CHECK_INTERVAL_MS=800
- ETHEREUM_STALLED_SYNC_THRESHOLD_MS=20000
- FEE_CLAIMER_ADDRESS=0x3b9f4c1dd26e0be593373b1d36cee2008cbeb837
- LOGGER_BACKEND=console
restart: always
ports:
- "9656:9656"
Expand Down Expand Up @@ -113,6 +114,7 @@ services:
- ETHEREUM_BLOCK_TIME_SECONDS=1
- EXIT_PROCESSOR_SLA_MARGIN=5520
- EXIT_PROCESSOR_SLA_MARGIN_FORCED=TRUE
- LOGGER_BACKEND=console
restart: always
ports:
- "7434:7434"
Expand Down Expand Up @@ -149,6 +151,7 @@ services:
- ETHEREUM_BLOCK_TIME_SECONDS=1
- EXIT_PROCESSOR_SLA_MARGIN=5520
- EXIT_PROCESSOR_SLA_MARGIN_FORCED=TRUE
- LOGGER_BACKEND=console
restart: always
ports:
- "7534:7534"
Expand Down
31 changes: 16 additions & 15 deletions docs/deployment_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
- "PORT" - Child Chain or Watcher API port. Defaults to 9656 for Child Chain and 7434 for Watcher.
- "HOSTNAME" - server domain name of Child Chain or Watcher. *mandatory*
- "DD_DISABLED" - boolean that allows you to turn on or of Datadog metrics. Defaults to true.
- "APP_ENV" - environment name in which the the application was deployed *mandatory*
- "DB_PATH" - directory of the KV db *mandatory*
- "ETHEREUM_RPC_URL" - address of Geth or Parity instance *mandatory*
- "ETH_NODE" - Geth, Parity or Infura *mandatory*
- "SENTRY_DSN" - if not set, Sentry is disabled
- "DD_HOSTNAME" - Datadog hostname
- "DD_PORT" - Datadog agent UDP port for metrics
- "DD_APM_PORT" - Datadog TCP port for APM
- "BATCH_SIZE" - Datadog batch size for APM
- "SYNC_THRESHOLD" - Datadog sync threshold for APM
- "APP_ENV" - environment name in which the the application was deployed. *mandatory*
- "DB_PATH" - directory of the KV db. *mandatory*
- "ETHEREUM_RPC_URL" - address of Geth or Parity instance. *mandatory*
- "ETH_NODE" - Geth, Parity or Infura. *mandatory*
- "SENTRY_DSN" - if not set, Sentry is disabled.
- "DD_HOSTNAME" - Datadog hostname.
- "DD_PORT" - Datadog agent UDP port for metrics.
- "DD_APM_PORT" - Datadog TCP port for APM.
- "BATCH_SIZE" - Datadog batch size for APM.
- "SYNC_THRESHOLD" - Datadog sync threshold for APM.
- "ETHEREUM_EVENTS_CHECK_INTERVAL_MS" - the frequency of HTTP requests towards the Ethereum clients and scanning for interested events. Should be less then average block time (10 to 20 seconds) on Ethereum mainnet.
- "ETHEREUM_STALLED_SYNC_THRESHOLD_MS" - the threshold before considering an unchanging Ethereum block height to be considered a stalled sync. Should be slightly larger than the expected block time.
- "FEE_CLAIMER_ADDRESS" - [Child Chain only!] 20-bytes HEX-encoded string of Ethereum address of Fee Claimer. Set via ENV vars only for Child Chain. For the Watcher this values is not important and fallbacks to "DEAD000000000000000000000000000000000000".
- "EXIT_PROCESSOR_SLA_MARGIN" - [Watcher only!] - number of Ethereum blocks since start of an invalid exit, before `unchallenged_exit` is reported to prompt to mass exit. Must be smaller than "MIN_EXIT_PERIOD_SECONDS", unless "EXIT_PROCESSOR_SLA_MARGIN_FORCED=TRUE"
- "ETHEREUM_BLOCK_TIME_SECONDS" - should mirror Ethereum network's setting, defaults to 15 seconds
- "EXIT_PROCESSOR_SLA_MARGIN" - [Watcher only!] - number of Ethereum blocks since start of an invalid exit, before `unchallenged_exit` is reported to prompt to mass exit. Must be smaller than "MIN_EXIT_PERIOD_SECONDS", unless "EXIT_PROCESSOR_SLA_MARGIN_FORCED=TRUE".
- "ETHEREUM_BLOCK_TIME_SECONDS" - should mirror Ethereum network's setting, defaults to 15 seconds.
- "LOGGER_BACKEND" - Ink or console. Ink will encode logs as json (useful for Datadog). Console will use the default elixir Logger backend. Default is Ink.

***Erlang VM configuration***

Expand All @@ -28,7 +29,7 @@
***Contract address configuration***
We allow a static configuration or a dynamic one, served as a http endpoint (one of them is mandatory).

- "ETHEREUM_NETWORK" - "RINKEBY" or "LOCALCHAIN"
- "ETHEREUM_NETWORK" - "RINKEBY" or "LOCALCHAIN".
- "CONTRACT_EXCHANGER_URL" - a server that can serve JSON in form of
```
{
Expand Down Expand Up @@ -65,9 +66,9 @@ The contract addresses that are required to be included in the `contract_addr` f

***Watcher security-critical only***

- "CHILD_CHAIN_URL" - Location of the Child Chain API *mandatory*
- "CHILD_CHAIN_URL" - Location of the Child Chain API. *mandatory*

***Watcher security-critical + informational***

- "DATABASE_URL" - Postgres address *mandatory*
- "CHILD_CHAIN_URL" - Location of the Child Chain API *mandatory*
- "CHILD_CHAIN_URL" - Location of the Child Chain API. *mandatory*
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e0100f8ef7d1124222c11ad362c857d3df7cb5f4204054f9f0f4a728666591fc"},
"httpoison": {:hex, :httpoison, "1.4.0", "e0b3c2ad6fa573134e42194d13e925acfa8f89d138bc621ffb7b1989e6d22e73", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "37b6f39cb92136ee72276f4bf4da81495e7935d720c3a15daf1553953153e3f7"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
"ink": {:hex, :ink, "1.0.2", "7bd9251601b352fb3b821cbad897d46d838e1a532de32e3ef82806aeef58cd3f", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "37c7efc3c0a45631d4ad8f75a0f03c644565ea2e9782dcce7e1d04bdd7197ecf"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"},
"jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm", "fc3499fed7a726995aa659143a248534adc754ebd16ccd437cd93b649a95091f"},
"keccakf1600": {:hex, :keccakf1600_orig, "2.0.0", "0a7217ddb3ee8220d449bbf7575ec39d4e967099f220a91e3dfca4dbaef91963", [:rebar3], [], "hexpm", "bdbbb02d67bea35605f95d4e3de48203347374e414da7945c4f2f7fd13ffe632"},
Expand Down
Loading

0 comments on commit fb4742b

Please sign in to comment.