From 298ffd2eec1e0f524dde5023cee2faa65a5f1f13 Mon Sep 17 00:00:00 2001 From: Stas Date: Fri, 26 Jan 2024 12:57:46 +0100 Subject: [PATCH] feat: setting log level per tenant via options (#286) --- VERSION | 2 +- lib/supavisor.ex | 27 ++++++++++++++++----------- lib/supavisor/client_handler.ex | 16 +++++++++++++--- lib/supavisor/db_handler.ex | 1 + lib/supavisor/helpers.ex | 9 +++++++++ lib/supavisor/manager.ex | 2 ++ test/supavisor/db_handler_test.exs | 3 ++- 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/VERSION b/VERSION index c442f5e7..32ffe120 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.22 +1.1.23 diff --git a/lib/supavisor.ex b/lib/supavisor.ex index 2a008cf4..b926fd78 100644 --- a/lib/supavisor.ex +++ b/lib/supavisor.ex @@ -16,19 +16,22 @@ defmodule Supavisor do @registry Supavisor.Registry.Tenants - @spec start_dist(id, secrets, Node.t() | boolean()) :: - {:ok, pid()} | {:error, any()} - def start_dist(id, secrets, force_node \\ false) do + @spec start_dist(id, secrets, keyword()) :: {:ok, pid()} | {:error, any()} + def start_dist(id, secrets, options \\ []) do + options = Keyword.validate!(options, log_level: nil, force_node: false) + log_level = Keyword.fetch!(options, :log_level) + force_node = Keyword.fetch!(options, :force_node) + case get_global_sup(id) do nil -> node = if force_node, do: force_node, else: determine_node(id) if node == node() do Logger.debug("Starting local pool for #{inspect(id)}") - start_local_pool(id, secrets) + start_local_pool(id, secrets, log_level) else Logger.debug("Starting remote pool for #{inspect(id)}") - H.rpc(node, __MODULE__, :start_local_pool, [id, secrets]) + H.rpc(node, __MODULE__, :start_local_pool, [id, secrets, log_level]) end pid -> @@ -200,8 +203,8 @@ defmodule Supavisor do Enum.at(nodes, index) end - @spec start_local_pool(id, secrets) :: {:ok, pid} | {:error, any} - def start_local_pool({{type, tenant}, _user, _mode, _db_name} = id, secrets) do + @spec start_local_pool(id, secrets, atom()) :: {:ok, pid} | {:error, any} + def start_local_pool({{type, tenant}, _user, _mode, _db_name} = id, secrets, log_level \\ nil) do Logger.debug("Starting pool(s) for #{inspect(id)}") user = elem(secrets, 1).().alias @@ -221,12 +224,12 @@ defmodule Supavisor do %T.Tenant{} = tenant -> Map.put(tenant, :replica_type, :write) end - |> supervisor_args(id, secrets) + |> supervisor_args(id, secrets, log_level) end) DynamicSupervisor.start_child( {:via, PartitionSupervisor, {Supavisor.DynamicSupervisor, id}}, - {Supavisor.TenantSupervisor, %{id: id, replicas: opts}} + {Supavisor.TenantSupervisor, %{id: id, replicas: opts, log_level: log_level}} ) |> case do {:error, {:already_started, pid}} -> {:ok, pid} @@ -245,7 +248,8 @@ defmodule Supavisor do defp supervisor_args( tenant_record, {tenant, user, mode, db_name} = id, - {method, secrets} + {method, secrets}, + log_level ) do %{ db_host: db_host, @@ -303,7 +307,8 @@ defmodule Supavisor do default_parameter_status: ps, max_clients: max_clients, client_idle_timeout: client_idle_timeout, - default_pool_strategy: default_pool_strategy + default_pool_strategy: default_pool_strategy, + log_level: log_level } end diff --git a/lib/supavisor/client_handler.ex b/lib/supavisor/client_handler.ex index 8f49dfa5..ad1f9c73 100644 --- a/lib/supavisor/client_handler.ex +++ b/lib/supavisor/client_handler.ex @@ -62,7 +62,8 @@ defmodule Supavisor.ClientHandler do db_name: nil, last_query: nil, heartbeat_interval: 0, - connection_start: System.monotonic_time() + connection_start: System.monotonic_time(), + log_level: nil } :gen_statem.enter_loop(__MODULE__, [hibernate_after: 5_000], :exchange, data) @@ -139,7 +140,15 @@ defmodule Supavisor.ClientHandler do Logger.debug("Client startup message: #{inspect(hello)}") {type, {user, tenant_or_alias, db_name}} = HH.parse_user_info(hello.payload) - {:keep_state, data, + log_level = + case hello.payload["options"]["log_level"] do + nil -> nil + level -> String.to_existing_atom(level) + end + + H.set_log_level(log_level) + + {:keep_state, %{data | log_level: log_level}, {:next_event, :internal, {:hello, {type, {user, tenant_or_alias, db_name}}}}} {:error, error} -> @@ -274,7 +283,8 @@ defmodule Supavisor.ClientHandler do def handle_event(:internal, :subscribe, _, data) do Logger.debug("Subscribe to tenant #{inspect(data.id)}") - with {:ok, sup} <- Supavisor.start_dist(data.id, data.auth_secrets), + with {:ok, sup} <- + Supavisor.start_dist(data.id, data.auth_secrets, log_level: data.log_level), {:ok, opts} <- Supavisor.subscribe(sup, data.id) do Process.monitor(opts.workers.manager) data = Map.merge(data, opts.workers) diff --git a/lib/supavisor/db_handler.ex b/lib/supavisor/db_handler.ex index eee3e45b..f09faa83 100644 --- a/lib/supavisor/db_handler.ex +++ b/lib/supavisor/db_handler.ex @@ -35,6 +35,7 @@ defmodule Supavisor.DbHandler do @impl true def init(args) do Process.flag(:trap_exit, true) + H.set_log_level(args.log_level) H.set_max_heap_size(150) {_, tenant} = args.tenant diff --git a/lib/supavisor/helpers.ex b/lib/supavisor/helpers.ex index d23108ae..e575055b 100644 --- a/lib/supavisor/helpers.ex +++ b/lib/supavisor/helpers.ex @@ -1,5 +1,6 @@ defmodule Supavisor.Helpers do @moduledoc false + require Logger @spec check_creds_get_ver(map) :: {:ok, String.t() | nil} | {:error, String.t()} @@ -343,4 +344,12 @@ defmodule Supavisor.Helpers do max_heap_words = div(max_heap_size * 1024 * 1024, :erlang.system_info(:wordsize)) Process.flag(:max_heap_size, %{size: max_heap_words}) end + + @spec set_log_level(atom()) :: :ok + def set_log_level(nil), do: :ok + + def set_log_level(level) when is_atom(level) do + Logger.notice("Setting log level to #{inspect(level)}") + Logger.put_process_level(self(), level) + end end diff --git a/lib/supavisor/manager.ex b/lib/supavisor/manager.ex index b42e4689..705c7307 100644 --- a/lib/supavisor/manager.ex +++ b/lib/supavisor/manager.ex @@ -5,6 +5,7 @@ defmodule Supavisor.Manager do alias Supavisor.Protocol.Server alias Supavisor.Tenants + alias Supavisor.Helpers, as: H @check_timeout 120_000 @@ -33,6 +34,7 @@ defmodule Supavisor.Manager do @impl true def init(args) do + H.set_log_level(args.log_level) tid = :ets.new(__MODULE__, [:public]) [args | _] = Enum.filter(args.replicas, fn e -> e.replica_type == :write end) diff --git a/test/supavisor/db_handler_test.exs b/test/supavisor/db_handler_test.exs index 211ee11b..2f41f6a0 100644 --- a/test/supavisor/db_handler_test.exs +++ b/test/supavisor/db_handler_test.exs @@ -13,7 +13,8 @@ defmodule Supavisor.DbHandlerTest do user_alias: "test_user_alias", user: "user", mode: :transaction, - replica_type: :single + replica_type: :single, + log_level: nil } {:ok, :connect, data, {_, next_event, _}} = Db.init(args)