Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow exporting number of RPC calls per method #67

Merged
merged 3 commits into from
Feb 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 0.5.6
* Feature that allows measuring number of RPC calls via an adapter https://github.com/mana-ethereum/ethereumex/pull/67

# 0.5.5
* Allow request counter resetting (https://github.com/mana-ethereum/ethereumex/pull/65)

Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ config :ethereumex,
ipc_path: "/path/to/ipc"
```

If you want to count the number of RPC calls per RPC method,
set adapter in the configuration. The adapter needs to implement `increment/3`
where the first argument is the key, the second is an integer and the third are optional keyword options you
want to pass to your adapter on each increment call.

```elixir
config :ethereumex,
adapter: Datadog
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add an example of the adapter in README?

the first argument is the key

Also, can you please clarify it? It looks like the first argument is the method name, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added some text, pls check if it's better.... was struggling a bit :D

adapter_options: []
```
An example of an adapter would be [Statix](https://github.com/lexmag/statix/blob/v1.2.1/lib/statix.ex#L288-L290).
Adapter options could be `[sample_rate: 1.0, tags: ["foo", "bar"]]`.

The IPC client type mode opens a pool of connection workers (default is 5 and 2, respectively). You can configure the pool size.
```elixir
config :ethereumex,
Expand Down
10 changes: 6 additions & 4 deletions lib/ethereumex/client/base_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -487,20 +487,22 @@ defmodule Ethereumex.Client.BaseClient do
end

defp prepare_request(params) when is_list(params) do
id = Counter.increment(:rpc_counter)
id = Counter.get(:rpc_counter)

params =
params
|> Enum.with_index()
|> Enum.with_index(1)
|> Enum.map(fn {req_data, index} ->
Map.put(req_data, "id", index + id)
end)

_ = Counter.increment(:rpc_counter, id + Enum.count(params))
_ = Counter.increment(:rpc_counter, id + Enum.count(params), "eth_batch")

params
end

defp prepare_request(params), do: Map.put(params, "id", Counter.increment(:rpc_counter))
defp prepare_request(params),
do: Map.put(params, "id", Counter.increment(:rpc_counter, params["method"]))

defp request(params, opts) do
__MODULE__.single_request(params, opts)
Expand Down
54 changes: 36 additions & 18 deletions lib/ethereumex/counter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,59 @@ defmodule Ethereumex.Counter do
:ok
end

@spec increment(atom()) :: integer()
def increment(key) do
do_increment(Application.get_env(:ethereumex, :id_reset), key)
@spec get(atom()) :: integer()
def get(key) do
case :ets.lookup(@tab, key) do
[] -> 1
[{^key, num}] -> num
end
end

@spec increment(atom(), integer()) :: integer()
def increment(key, count) do
do_increment(Application.get_env(:ethereumex, :id_reset), key, count)
@spec increment(atom(), String.t()) :: integer()
def increment(key, method) do
do_increment(Application.get_env(:ethereumex, :id_reset), key, method)
end

@spec do_increment(binary() | nil, atom()) :: integer()
defp do_increment(true, key) do
@spec increment(atom(), integer(), String.t()) :: integer()
def increment(key, count, method) do
do_increment(Application.get_env(:ethereumex, :id_reset), key, count, method)
end

@spec do_increment(binary() | nil, atom(), String.t()) :: integer()
defp do_increment(true, key, method) do
:ets.insert(@tab, {key, 0})
inc(key)
inc(key, method, Application.get_env(:ethereumex, :adapter))
end

defp do_increment(_, key) do
inc(key)
defp do_increment(_, key, method) do
inc(key, method, Application.get_env(:ethereumex, :adapter))
end

@spec do_increment(boolean() | nil, atom(), integer()) :: integer()
defp do_increment(true, key, count) do
@spec do_increment(boolean() | nil, atom(), integer(), String.t()) :: integer()
defp do_increment(true, key, count, method) do
:ets.insert(@tab, {key, 0})
inc(key, count)
inc(key, count, method, Application.get_env(:ethereumex, :adapter))
end

defp do_increment(_, key, count, method) do
inc(key, count, method, Application.get_env(:ethereumex, :adapter))
end

defp do_increment(_, key, count) do
inc(key, count)
defp inc(key, _, nil) do
:ets.update_counter(@tab, key, {2, 1}, {key, 0})
end

defp inc(key) do
defp inc(key, method, adapter) do
_ = adapter.increment(method, 1, Application.get_env(:ethereumex, :adapter_options) || [])
:ets.update_counter(@tab, key, {2, 1}, {key, 0})
end

defp inc(key, count) do
defp inc(key, count, _, nil) do
:ets.update_counter(@tab, key, {2, count}, {key, 0})
end

defp inc(key, count, method, adapter) do
_ = adapter.increment(method, 1, Application.get_env(:ethereumex, :adapter_options) || [])
:ets.update_counter(@tab, key, {2, count}, {key, 0})
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Ethereumex.Mixfile do
def project do
[
app: :ethereumex,
version: "0.5.5",
version: "0.5.6",
elixir: "~> 1.7",
description: "Elixir JSON-RPC client for the Ethereum blockchain",
package: [
Expand Down
14 changes: 7 additions & 7 deletions test/ethereumex/counter_reset_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ defmodule Ethereumex.ResetLockTest do
end

test "incrementing twice returns correct locked binary" do
1 = Counter.increment(:test_11)
1 = Counter.increment(:test_11)
1 = Counter.increment(:test_11, "method_11")
1 = Counter.increment(:test_11, "method_11")
end

test "incrementing twice and updating with a count returns correct locked binary" do
1 = Counter.increment(:test_22)
2 = Counter.increment(:test_22, 2)
1 = Counter.increment(:test_22, "method_22")
2 = Counter.increment(:test_22, 2, "method_22")
end

test "incrementing twice, updating with a count and incrementing again returns correct locked binary" do
1 = Counter.increment(:test_33)
2 = Counter.increment(:test_33, 2)
1 = Counter.increment(:test_33)
1 = Counter.increment(:test_33, "method_33")
2 = Counter.increment(:test_33, 2, "method_33")
1 = Counter.increment(:test_33, "method_33")
end
end
43 changes: 34 additions & 9 deletions test/ethereumex/counter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,46 @@ defmodule Ethereumex.CounterTest do
use ExUnit.Case
alias Ethereumex.Counter

setup_all do
on_exit(fn ->
Application.put_env(:ethereumex, :adapter, nil)
Application.put_env(:ethereumex, :adapter_options, nil)
end)

:ok
end

test "incrementing twice returns correct number" do
1 = Counter.increment(:test_1)
2 = Counter.increment(:test_1)
1 = Counter.increment(:test_1, "method_1")
2 = Counter.increment(:test_1, "method_1")
end

test "incrementing twice and updating with a count returns correct number" do
1 = Counter.increment(:test_2)
2 = Counter.increment(:test_2)
4 = Counter.increment(:test_2, 2)
1 = Counter.increment(:test_2, "method_2")
2 = Counter.increment(:test_2, "method_2")
4 = Counter.increment(:test_2, 2, ["method_2"])
end

test "incrementing twice, updating with a count and incrementing again returns correct number" do
1 = Counter.increment(:test_3)
2 = Counter.increment(:test_3)
4 = Counter.increment(:test_3, 2)
5 = Counter.increment(:test_3)
1 = Counter.increment(:test_3, "method_3")
2 = Counter.increment(:test_3, "method_3")
4 = Counter.increment(:test_3, 2, ["method_3"])
5 = Counter.increment(:test_3, "method_3")
end

test "an adapter gets called with increment/2" do
:ok = Application.put_env(:ethereumex, :adapter, __MODULE__.Adapter)
1 = Counter.increment(:test_4, "method_4")
assert_receive({"method_4", 1, []})
3 = Counter.increment(:test_4, 2, "eth_batch")
assert_receive({"eth_batch", 1, []})

:ok = Application.put_env(:ethereumex, :adapter_options, sample_rate: 0.5)
5 = Counter.increment(:test_4, 2, "eth_batch")
assert_receive({"eth_batch", 1, [sample_rate: 0.5]})
end

defmodule Adapter do
def increment(method, count, options), do: Kernel.send(self(), {method, count, options})
end
end