Skip to content

Commit

Permalink
feat: inspector
Browse files Browse the repository at this point in the history
  • Loading branch information
mhanberg committed Oct 31, 2023
1 parent eaa8062 commit 4725400
Show file tree
Hide file tree
Showing 25 changed files with 788 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
request: 2
],
line_length: 120,
import_deps: [:gen_lsp],
import_deps: [:gen_lsp, :plug, :temple],
plugins: [Styler],
inputs: [
".formatter.exs",
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ result
# Ignore dialyzer plt files
/priv/plts/*.plt
/priv/plts/*.plt.hash

/priv/css/*
14 changes: 14 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

@import url('https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&family=Rubik:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');

pre {
@apply bg-zinc-500 text-white rounded px-2 text-sm;
}

h1, h2, h3, h4, h5 {
@apply font-fancy font-semibold;
}
17 changes: 17 additions & 0 deletions assets/tailwind.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// See the Tailwind configuration guide for advanced usage
// https://tailwindcss.com/docs/configuration

const defaultTheme = require("tailwindcss/defaultTheme");

module.exports = {
content: ["./js/**/*.js", "./lib/**/*.ex"],
theme: {
extend: {
fontFamily: {
sans: ['"Inter"', ...defaultTheme.fontFamily.sans],
fancy: ['"Rubik"', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [],
};
2 changes: 1 addition & 1 deletion bin/start
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

cd "$(dirname "$0")"/.. || exit 1

elixir -S mix run --no-halt -e "Application.ensure_all_started(:next_ls)" -- "$@"
mix run --no-halt -e "Application.ensure_all_started(:next_ls)" -- "$@"
36 changes: 35 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@ import Config

config :next_ls, :indexing_timeout, 100

config :logger, :default_handler, config: [type: :standard_error]
config :temple,
engine: EEx.SmartEngine,
attributes: {Temple, :attributes}

config :tailwind,
version: "3.3.2",
default: [
args: ~w(
--config=assets/tailwind.config.js
--input=assets/css/app.css
--output=priv/css/site.css
)
]

# config :logger, :default_handler, config: [type: :standard_error]
config :logger, :default_handler,
config: [
file: ~c".elixir-tools/next-ls.log",
filesync_repeat_interval: 5000,
file_check: 5000,
max_no_bytes: 10_000_000,
max_no_files: 5,
compress_on_rotate: true
]

config :next_ls, :logger, [
{:handler, :ui_logger, NextLS.UI.Logger,
%{
config: %{},
formatter: Logger.Formatter.new()
}}
]

config :logger, :default_formatter,
format: "\n$time $metadata[$level] $message\n"

import_config "#{config_env()}.exs"
2 changes: 2 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
import Config

config :next_ls, :assets, tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}
27 changes: 26 additions & 1 deletion lib/next_ls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ defmodule NextLS do
cache = Keyword.fetch!(args, :cache)
{:ok, logger} = DynamicSupervisor.start_child(dynamic_supervisor, {NextLS.Logger, lsp: lsp})

{:ok, ui} =
DynamicSupervisor.start_child(
dynamic_supervisor,
{Bandit, [plug: NextLS.UI.Router, port: "NEXTLS_UI_PORT" |> System.get_env("0") |> String.to_integer()]}
)

{:ok,
assign(lsp,
auto_update: Keyword.get(args, :auto_update, false),
Expand All @@ -85,7 +91,8 @@ defmodule NextLS do
registry: registry,
extensions: extensions,
ready: false,
client_capabilities: nil
client_capabilities: nil,
ui: ui
)}
end

Expand Down Expand Up @@ -127,6 +134,7 @@ defmodule NextLS do
nil
end,
document_formatting_provider: true,
execute_command_provider: %GenLSP.Structures.ExecuteCommandOptions{commands: ["open-ui"]},
hover_provider: true,
workspace_symbol_provider: true,
document_symbol_provider: true,
Expand Down Expand Up @@ -572,6 +580,23 @@ defmodule NextLS do
{:reply, [], lsp}
end

def handle_request(
%GenLSP.Requests.WorkspaceExecuteCommand{params: %GenLSP.Structures.ExecuteCommandParams{command: command}},
lsp
) do
{:ok, {_, port}} = ThousandIsland.listener_info(lsp.assigns.ui)

case command do
"open-ui" ->
System.cmd("open", ["http://localhost:#{port}"])

_ ->
NextLS.Logger.warning(lsp.logger, "[Next LS] Unknown workspace command: #{command}")
end

{:reply, nil, lsp}
end

def handle_request(%Shutdown{}, lsp) do
{:reply, nil, assign(lsp, exit_code: 0)}
end
Expand Down
129 changes: 127 additions & 2 deletions lib/next_ls/application.ex
Original file line number Diff line number Diff line change
@@ -1,3 +1,116 @@
defmodule NextLS.OpentelemetrySchematic do
@moduledoc false
require Logger

@tracer_id __MODULE__

def setup do
:ok =
:telemetry.attach_many(
"schematic-handler",
[
[:schematic, :unify, :start],
[:schematic, :unify, :stop]
],
&__MODULE__.process/4,
nil
)
end

def process([:schematic, :unify, :start], _measurements, metadata, _config) do
OpentelemetryTelemetry.start_telemetry_span(
@tracer_id,
:"schematic.unify.#{metadata.kind} #{metadata.dir}",
metadata,
%{kind: :server, attributes: metadata}
)
end

def process([:schematic, :unify, :stop], _measurements, metadata, _config) do
OpentelemetryTelemetry.set_current_telemetry_span(@tracer_id, metadata)
OpentelemetryTelemetry.end_telemetry_span(@tracer_id, metadata)
end
end

defmodule NextLS.OpentelemetryGenLSP do
@moduledoc false
require Logger
require OpenTelemetry.Tracer, as: Tracer

@tracer_id __MODULE__

def setup do
:ok =
:telemetry.attach_many(
"gen-lsp-handler",
[
[:gen_lsp, :loop, :start],
[:gen_lsp, :loop, :stop],
[:gen_lsp, :notification, :emit],
[:gen_lsp, :info, :start],
[:gen_lsp, :info, :stop],
[:gen_lsp, :buffer, :read],
[:gen_lsp, :buffer, :write]
],
&__MODULE__.process/4,
nil
)
end

def process([:gen_lsp, :buffer, :read], _measurements, metadata, _config) do
OpenTelemetry.Ctx.clear()

OpentelemetryTelemetry.start_telemetry_span(@tracer_id, :"gen_lsp.read", metadata, %{
kind: :server,
attributes: metadata
})
end

def process([:gen_lsp, :loop, :start], _measurements, metadata, _config) do
parent_context = OpentelemetryProcessPropagator.fetch_parent_ctx(1, :"$callers")

if parent_context != :undefined do
OpenTelemetry.Ctx.attach(parent_context)
end

Tracer.update_name(:"gen_lsp.receive.#{metadata.type} #{metadata.method}")
end

def process([:gen_lsp, :loop, :stop], _measurements, %{type: :request, reply: true} = _metadata, _config) do
OpenTelemetry.Ctx.clear()
end

def process([:gen_lsp, :loop, :stop], _measurements, metadata, _config) do
OpentelemetryTelemetry.set_current_telemetry_span(@tracer_id, metadata)
OpentelemetryTelemetry.end_telemetry_span(@tracer_id, metadata)
OpenTelemetry.Ctx.clear()
end

def process([:gen_lsp, :notification, :emit], _measurements, metadata, _config) do
OpentelemetryTelemetry.start_telemetry_span(
@tracer_id,
:"gen_lsp.send.notification #{metadata.method}",
metadata,
%{
kind: :server,
attributes: metadata
}
)
end

def process([:gen_lsp, :buffer, :write], _measurements, metadata, _config) do
parent_context = OpentelemetryProcessPropagator.fetch_parent_ctx(1, :"$callers")

if parent_context != :undefined do
OpenTelemetry.Ctx.attach(parent_context)
end

OpentelemetryTelemetry.set_current_telemetry_span(@tracer_id, metadata)
OpentelemetryTelemetry.end_telemetry_span(@tracer_id, metadata)
OpenTelemetry.Ctx.clear()
end
end

defmodule NextLS.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
Expand All @@ -7,6 +120,8 @@ defmodule NextLS.Application do

@impl true
def start(_type, _args) do
Logger.add_handlers(:next_ls)

case System.cmd("epmd", ["-daemon"], stderr_to_stdout: true) do
{_, 0} ->
:ok
Expand All @@ -19,11 +134,21 @@ defmodule NextLS.Application do

Node.start(:"next-ls-#{System.system_time()}", :shortnames)

children = [NextLS.LSPSupervisor]
children = [
NextLS.UI.CodeReloader,
{Registry, name: NextLS.UI.Registry, keys: :duplicate},
NextLS.LSPSupervisor
]

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: NextLS.Supervisor]
Supervisor.start_link(children, opts)
Supervisor.start_link(children ++ asset_children(), opts)
end

def asset_children do
for conf <- Application.get_env(:next_ls, :assets, []) do
{NextLS.UI.Assets, conf}
end
end
end
5 changes: 4 additions & 1 deletion lib/next_ls/db.ex
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,10 @@ defmodule NextLS.DB do
def __query__({conn, logger}, query, args) do
args = Enum.map(args, &cast/1)

case Exqlite.Basic.exec(conn, query, args) do
{duration, result} = :timer.tc(fn -> Exqlite.Basic.exec(conn, query, args) end, :millisecond)
IO.inspect("#{duration}ms")

case result do
{:error, %{message: message, statement: statement}, _} ->
NextLS.Logger.warning(logger, """
sqlite3 error: #{message}
Expand Down
9 changes: 8 additions & 1 deletion lib/next_ls/db/activity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ defmodule NextLS.DB.Activity do
:gen_statem.start_link({:local, Keyword.get(args, :name)}, __MODULE__, Keyword.drop(args, [:name]), [])
end

def update(statem, count), do: :gen_statem.cast(statem, count)
def update(statem, count) do
Registry.dispatch(NextLS.UI.Registry, :activity_socket, fn entries ->
for {pid, _} <- entries, do: send(pid, {:activity, count})

end)

:gen_statem.cast(statem, count)
end

@impl :gen_statem
def callback_mode, do: :state_functions
Expand Down
10 changes: 10 additions & 0 deletions lib/next_ls/logger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule NextLS.Logger do
@moduledoc false
use GenServer

require Logger

def start_link(arg) do
GenServer.start_link(__MODULE__, arg, Keyword.take(arg, [:name]))
end
Expand All @@ -22,6 +24,14 @@ defmodule NextLS.Logger do

def handle_cast({:log, type, msg}, state) do
apply(GenLSP, type, [state.lsp, String.trim("[NextLS] #{msg}")])

case type do
:log -> Logger.debug(msg)
:warning -> Logger.warning(msg)
:error -> Logger.error(msg)
:info -> Logger.info(msg)
end

{:noreply, state}
end

Expand Down
Loading

0 comments on commit 4725400

Please sign in to comment.