From 32f8313dfd0d279214b999a746aeb10cf1e8dbf3 Mon Sep 17 00:00:00 2001 From: Mitchell Hanberg Date: Wed, 5 Jul 2023 22:41:58 -0400 Subject: [PATCH] fix: start dedicated process for runtime logging (#94) Fixes #92 --- lib/next_ls.ex | 14 +++++++------- lib/next_ls/logger.ex | 22 ++++++++++++++++++++++ lib/next_ls/runtime.ex | 11 ++++++----- test/next_ls/runtime_test.exs | 21 ++++++++++++++++----- 4 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 lib/next_ls/logger.ex diff --git a/lib/next_ls.ex b/lib/next_ls.ex index 1aa5167b..f070b5d5 100644 --- a/lib/next_ls.ex +++ b/lib/next_ls.ex @@ -70,6 +70,7 @@ defmodule NextLS do extensions = Keyword.get(args, :extensions, [NextLS.ElixirExtension]) cache = Keyword.fetch!(args, :cache) symbol_table = Keyword.fetch!(args, :symbol_table) + {:ok, logger} = DynamicSupervisor.start_child(dynamic_supervisor, {NextLS.Logger, lsp: lsp}) {:ok, assign(lsp, @@ -77,6 +78,7 @@ defmodule NextLS do documents: %{}, refresh_refs: %{}, cache: cache, + logger: logger, symbol_table: symbol_table, task_supervisor: task_supervisor, dynamic_supervisor: dynamic_supervisor, @@ -269,7 +271,11 @@ defmodule NextLS do {:ok, runtime} = DynamicSupervisor.start_child( lsp.assigns.dynamic_supervisor, - {NextLS.Runtime, extension_registry: lsp.assigns.extension_registry, working_dir: working_dir, parent: self()} + {NextLS.Runtime, + extension_registry: lsp.assigns.extension_registry, + working_dir: working_dir, + parent: self(), + logger: lsp.assigns.logger} ) Process.monitor(runtime) @@ -447,12 +453,6 @@ defmodule NextLS do {:noreply, assign(lsp, runtime: nil)} end - def handle_info({:log, message}, lsp) do - GenLSP.log(lsp, "[NextLS] " <> String.trim(message)) - - {:noreply, lsp} - end - def handle_info(message, lsp) do GenLSP.log(lsp, "[NextLS] Unhanded message: #{inspect(message)}") {:noreply, lsp} diff --git a/lib/next_ls/logger.ex b/lib/next_ls/logger.ex new file mode 100644 index 00000000..06500f84 --- /dev/null +++ b/lib/next_ls/logger.ex @@ -0,0 +1,22 @@ +defmodule NextLS.Logger do + use GenServer + + def start_link(arg) do + GenServer.start_link(__MODULE__, arg, Keyword.take(arg, [:name])) + end + + def log(server, msg), do: GenServer.cast(server, {:log, :log, msg}) + def error(server, msg), do: GenServer.cast(server, {:log, :error, msg}) + def info(server, msg), do: GenServer.cast(server, {:log, :info, msg}) + def warning(server, msg), do: GenServer.cast(server, {:log, :warning, msg}) + + def init(args) do + lsp = Keyword.fetch!(args, :lsp) + {:ok, %{lsp: lsp}} + end + + def handle_cast({:log, type, msg}, state) do + apply(GenLSP, type, [state.lsp, "[NextLS] #{msg}" |> String.trim()]) + {:noreply, state} + end +end diff --git a/lib/next_ls/runtime.ex b/lib/next_ls/runtime.ex index 0905d34c..499be534 100644 --- a/lib/next_ls/runtime.ex +++ b/lib/next_ls/runtime.ex @@ -43,6 +43,7 @@ defmodule NextLS.Runtime do sname = "nextls-runtime-#{System.system_time()}" working_dir = Keyword.fetch!(opts, :working_dir) parent = Keyword.fetch!(opts, :parent) + logger = Keyword.fetch!(opts, :logger) extension_registry = Keyword.fetch!(opts, :extension_registry) port = @@ -81,7 +82,7 @@ defmodule NextLS.Runtime do with {:ok, host} <- :inet.gethostname(), node <- :"#{sname}@#{host}", true <- connect(node, port, 120) do - send(parent, {:log, "Connected to node #{node}"}) + NextLS.Logger.log(logger, "Connected to node #{node}") :next_ls |> :code.priv_dir() @@ -89,7 +90,7 @@ defmodule NextLS.Runtime do |> then(&:rpc.call(node, Code, :compile_file, [&1])) |> tap(fn {:badrpc, :EXIT, {error, _}} -> - send(parent, {:log, error}) + NextLS.Logger.error(logger, error) _ -> :ok @@ -103,7 +104,7 @@ defmodule NextLS.Runtime do end end) - {:ok, %{port: port, parent: parent, errors: nil, extension_registry: extension_registry}} + {:ok, %{port: port, logger: logger, parent: parent, errors: nil, extension_registry: extension_registry}} end @impl GenServer @@ -143,12 +144,12 @@ defmodule NextLS.Runtime do end def handle_info({port, {:data, data}}, %{port: port} = state) do - send(state.parent, {:log, data}) + NextLS.Logger.log(state.logger, data) {:noreply, state} end def handle_info({port, other}, %{port: port} = state) do - send(state.parent, {:log, other}) + NextLS.Logger.log(state.logger, other) {:noreply, state} end diff --git a/test/next_ls/runtime_test.exs b/test/next_ls/runtime_test.exs index f78b5b45..f8911aeb 100644 --- a/test/next_ls/runtime_test.exs +++ b/test/next_ls/runtime_test.exs @@ -26,8 +26,8 @@ defmodule NextLs.RuntimeTest do Task.start_link(fn -> recv = fn recv -> receive do - {:log, msg} -> - Logger.debug(msg) + msg -> + Logger.debug(inspect(msg)) end recv.(recv) @@ -41,7 +41,11 @@ defmodule NextLs.RuntimeTest do test "returns the response in an ok tuple", %{logger: logger, cwd: cwd} do start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry}) - pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry}) + + pid = + start_supervised!( + {Runtime, working_dir: cwd, parent: self(), logger: logger, extension_registry: RuntimeTestRegistry} + ) Process.link(pid) @@ -52,7 +56,11 @@ defmodule NextLs.RuntimeTest do test "call returns an error when the runtime is node ready", %{logger: logger, cwd: cwd} do start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry}) - pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry}) + + pid = + start_supervised!( + {Runtime, working_dir: cwd, parent: self(), logger: logger, extension_registry: RuntimeTestRegistry} + ) Process.link(pid) @@ -63,7 +71,10 @@ defmodule NextLs.RuntimeTest do start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry}) capture_log(fn -> - pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry}) + pid = + start_supervised!( + {Runtime, working_dir: cwd, parent: self(), logger: logger, extension_registry: RuntimeTestRegistry} + ) Process.link(pid)