Skip to content

Commit

Permalink
feat: telemetry & clone support (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
doomspork committed Jan 22, 2024
1 parent 8e97b97 commit 78e254e
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 1 deletion.
7 changes: 7 additions & 0 deletions lib/library.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ defmodule Lunar.Library do
end

def unquote(wrapped_func)(_arity, args, state) do
:telemetry.execute([:lunar, :deflua, :invocation], %{count: 1}, %{
args: args,
function_name: unquote(func),
scope: __MODULE__.scope(),
module_name: __MODULE__
})

res = apply(__MODULE__, unquote(func), args)
{[res], state}
end
Expand Down
45 changes: 44 additions & 1 deletion lib/lunar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,25 @@ defmodule Lunar do
@type error :: {:error, atom() | String.t()}

@doc """
Initialize a new Lunar
Initialize a new Lunar runtime
"""
@spec init() :: Lunar.t()
def init do
:telemetry.execute([:lunar, :init], %{count: 1}, %{})
%Lunar{id: Nanoid.generate(), state: Luerl.init()}
end

@doc """
A convenience function for copying a Lunar runtime and setting a new `id`
"""
def clone(lunar) do
new_id = Nanoid.generate()

:telemetry.execute([:lunar, :clone], %{count: 1}, %{})

%{lunar | id: new_id}
end

@doc """
Encodes an Elixir value and makes it available at the key/path.
Expand All @@ -39,6 +51,11 @@ defmodule Lunar do

case Luerl.set_table_keys_dec(lunar.state, key, value) do
{:ok, _result, new_state} ->
:telemetry.execute([:lunar, :set_variable], %{count: 1}, %{
key: key,
value: value
})

{:ok, %{lunar | state: new_state, variables: Map.put(lunar.variables, key, value)}}

{:lua_error, reason, _state} ->
Expand All @@ -56,6 +73,11 @@ defmodule Lunar do
"""
@spec load_module!(Lunar.t(), Lunar.Library.t()) :: Lunar.t()
def load_module!(lunar, module) do
:telemetry.execute([:lunar, :load_module!], %{count: 1}, %{
scope: module.scope(),
module_name: module
})

new_state = Luerl.load_module_dec(lunar.state, [module.scope()], module)
%{lunar | state: new_state, modules: [module | lunar.modules]}
end
Expand All @@ -67,6 +89,8 @@ defmodule Lunar do
def load_lua!(lunar, path) do
case Luerl.dofile(lunar.state, String.to_charlist(path)) do
{:ok, _result, new_state} ->
:telemetry.execute([:lunar, :load_lua!], %{count: 1}, %{path: path})

%{lunar | state: new_state, lua_files: [path | lunar.lua_files]}

:error ->
Expand All @@ -86,12 +110,31 @@ defmodule Lunar do
"""
@spec run(Lunar.t(), String.t()) :: {:ok, any(), Lunar.t()} | error
def run(lunar, lua) do
:telemetry.span(
[:lunar, :run],
%{},
fn ->
result = run_lunar(lunar, lua)
{result, %{}}
end
)
end

defp run_lunar(lunar, lua) do
case Luerl.do(lunar.state, lua) do
{:ok, result, new_state} ->
:telemetry.execute([:lunar, :run, :success], %{count: 1}, %{})

{:ok, result, %{lunar | state: new_state}}

{:error, reason, _state} ->
:telemetry.execute([:lunar, :run, :failure], %{count: 1}, %{
reason: parse_luerl_error(reason)
})

{:error, reason}
end
end

defp parse_luerl_error([{line_no, type, reason}]), do: "line #{line_no}: #{type} #{reason}"
end
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defmodule Lunar.MixProject do
[
{:luerl, "~> 1.1"},
{:nanoid, "~> 2.1.0"},
{:telemetry, ">= 1.0.0"},

# Dev & Test dependencies
{:credo, "~> 1.6", only: [:dev, :test], runtime: false},
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
"makeup_erlang": {:hex, :makeup_erlang, "0.1.3", "d684f4bac8690e70b06eb52dad65d26de2eefa44cd19d64a8095e1417df7c8fd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b78dc853d2e670ff6390b605d807263bf606da3c82be37f9d7f68635bd886fc9"},
"nanoid": {:hex, :nanoid, "2.1.0", "d192a5bf1d774258bc49762b480fca0e3128178fa6d35a464af2a738526607fd", [:mix], [], "hexpm", "ebc7a342d02d213534a7f93a091d569b9fea7f26fcd3a638dc655060fc1f76ac"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
}
78 changes: 78 additions & 0 deletions test/lunar_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,84 @@ defmodule LunarTest do
{:ok, lunar: Lunar.init()}
end

describe ":telemetry" do
setup do
_ref =
:telemetry_test.attach_event_handlers(self(), [
[:lunar, :init],
[:lunar, :clone],
[:lunar, :deflua, :invocation],
[:lunar, :load_lua!],
[:lunar, :load_module!],
[:lunar, :run, :failure],
[:lunar, :run, :success],
[:lunar, :run],
[:lunar, :set_variable]
])

:ok
end

test "emits [:lunar, :init]" do
Lunar.init()
assert_receive {[:lunar, :init], _ref, %{count: 1}, %{}}
end

test "emits [:lunar, :clone]", %{lunar: lunar} do
Lunar.clone(lunar)
assert_receive {[:lunar, :clone], _ref, %{count: 1}, %{}}
end

test "emits [:lunar, :set_variable]", %{lunar: lunar} do
Lunar.set_variable(lunar, :foo, "bar")
assert_receive {[:lunar, :set_variable], _ref, %{count: 1}, %{key: [:foo], value: "bar"}}
end

test "emits [:lunar, :load_module!]", %{lunar: lunar} do
Lunar.load_module!(lunar, Math)
assert_receive {[:lunar, :load_module!], _ref, %{count: 1}, %{scope: "Math", module_name: Math}}
end

test "emits [:lunar, :load_lua!]", %{lunar: lunar} do
path = Path.join([__DIR__, "support", "hello.lua"])
Lunar.load_lua!(lunar, path)
assert_receive {[:lunar, :load_lua!], _ref, %{count: 1}, %{path: ^path}}
end

@tag capture_log: false
test "emits [:lunar, :run, :success]", %{lunar: lunar} do
Lunar.run(lunar, "return true")
assert_receive {[:lunar, :run, :success], _ref, %{count: 1}, %{}}
end

test "emits [:lunar, :run, :failure]", %{lunar: lunar} do
# Results in a syntax error
Lunar.run(lunar, "1+1=2")

assert_receive {[:lunar, :run, :failure], _ref, %{count: 1},
%{reason: "line 1: luerl_parse syntax error before: 1"}}
end

test "emits [:lunar, :deflua, :invocation]", %{lunar: lunar} do
script = """
return Math.sub(2, 1)
"""

lunar
|> Lunar.load_module!(Math)
|> Lunar.run(script)

assert_receive {[:lunar, :deflua, :invocation], _ref, %{count: 1},
%{args: [2, 1], function_name: :sub, scope: "Math", module_name: Math}}
end
end

describe "clone/1" do
test "sets a new `id`", %{lunar: lunar} do
assert lunar.id != Lunar.clone(lunar).id
end
end

describe "set_variable/3" do
test "sets a variable", %{lunar: lunar} do
name = ["name"]
Expand Down

0 comments on commit 78e254e

Please sign in to comment.