-
Notifications
You must be signed in to change notification settings - Fork 21
/
metric_adapter.ex
185 lines (145 loc) · 5.91 KB
/
metric_adapter.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
defmodule Sanbase.Price.MetricAdapter do
@behaviour Sanbase.Metric.Behaviour
alias Sanbase.Price
@aggregations [:any, :sum, :avg, :min, :max, :last, :first, :median, :ohlc, :count]
@default_aggregation :last
@timeseries_metrics ["price_usd", "price_btc", "volume_usd", "marketcap_usd"]
@histogram_metrics []
@table_metrics []
@metrics @histogram_metrics ++ @timeseries_metrics ++ @table_metrics
# plan related - the plan is upcase string
@min_plan_map Enum.into(@metrics, %{}, fn metric -> {metric, "FREE"} end)
# restriction related - the restriction is atom :free or :restricted
@access_map Enum.into(@metrics, %{}, fn metric -> {metric, :free} end)
@free_metrics Enum.filter(@access_map, fn {_, level} -> level == :free end)
|> Enum.map(&elem(&1, 0))
@restricted_metrics Enum.filter(@access_map, fn {_, level} -> level == :restricted end)
|> Enum.map(&elem(&1, 0))
@required_selectors Enum.into(@metrics, %{}, &{&1, []})
@default_complexity_weight 0.3
@impl Sanbase.Metric.Behaviour
def has_incomplete_data?(_), do: false
@impl Sanbase.Metric.Behaviour
def complexity_weight(_), do: @default_complexity_weight
@impl Sanbase.Metric.Behaviour
def required_selectors(), do: @required_selectors
@impl Sanbase.Metric.Behaviour
def broken_data(_metric, _selector, _from, _to), do: {:ok, []}
@impl Sanbase.Metric.Behaviour
def timeseries_data(metric, %{slug: slug}, from, to, interval, opts) do
Price.timeseries_metric_data(slug, metric, from, to, interval, update_opts(opts))
end
@impl Sanbase.Metric.Behaviour
def timeseries_data_per_slug(metric, %{slug: slug}, from, to, interval, opts) do
Price.timeseries_metric_data_per_slug(slug, metric, from, to, interval, update_opts(opts))
end
@impl Sanbase.Metric.Behaviour
def aggregated_timeseries_data(metric, %{slug: slug}, from, to, opts) do
Price.aggregated_metric_timeseries_data(slug, metric, from, to, update_opts(opts))
end
@impl Sanbase.Metric.Behaviour
def slugs_by_filter(metric, from, to, operator, threshold, opts) do
Price.slugs_by_filter(metric, from, to, operator, threshold, opts)
end
@impl Sanbase.Metric.Behaviour
def slugs_order(metric, from, to, direction, opts) do
Price.slugs_order(metric, from, to, direction, opts)
end
@impl Sanbase.Metric.Behaviour
def first_datetime(_metric, %{slug: slug}) do
Price.first_datetime(slug)
end
@impl Sanbase.Metric.Behaviour
def last_datetime_computed_at(_metric, %{slug: slug}) do
Price.last_datetime_computed_at(slug)
end
@impl Sanbase.Metric.Behaviour
def metadata(metric) do
{:ok,
%{
metric: metric,
internal_metric: metric,
has_incomplete_data: has_incomplete_data?(metric),
min_interval: "1s",
default_aggregation: @default_aggregation,
available_aggregations: @aggregations,
available_selectors: [:slug],
required_selectors: [:slug],
data_type: :timeseries,
is_timebound: false,
complexity_weight: @default_complexity_weight,
docs: docs_links(metric) |> Enum.map(fn link -> %{link: link} end),
is_deprecated: false,
hard_deprecate_after: nil,
is_label_fqn_metric: false
}}
end
@impl Sanbase.Metric.Behaviour
def human_readable_name(metric) do
case metric do
"price_usd" -> {:ok, "Price in USD"}
"price_btc" -> {:ok, "Price in BTC"}
"price_eth" -> {:ok, "Price in ETH"}
"marketcap_usd" -> {:ok, "Marketcap in USD"}
"volume_usd" -> {:ok, "Volume in USd"}
end
end
@impl Sanbase.Metric.Behaviour
def available_aggregations(), do: @aggregations
@impl Sanbase.Metric.Behaviour
def available_timeseries_metrics(), do: @timeseries_metrics
@impl Sanbase.Metric.Behaviour
def available_histogram_metrics(), do: @histogram_metrics
@impl Sanbase.Metric.Behaviour
def available_table_metrics(), do: @table_metrics
@impl Sanbase.Metric.Behaviour
def available_metrics(), do: @metrics
@impl Sanbase.Metric.Behaviour
def available_metrics(%{address: _address}), do: []
def available_metrics(%{contract_address: contract_address}) do
Sanbase.Metric.Utils.available_metrics_for_contract(__MODULE__, contract_address)
end
def available_metrics(%{slug: "TOTAL_ERC20"}), do: @metrics
def available_metrics(%{slug: slug}) do
cache_key = {__MODULE__, :has_price_data?, slug} |> Sanbase.Cache.hash()
cache_key_with_ttl = {cache_key, 600}
case Sanbase.Cache.get_or_store(cache_key_with_ttl, fn -> Price.has_data?(slug) end) do
{:ok, true} -> {:ok, @metrics}
{:ok, false} -> {:ok, []}
{:error, error} -> {:error, error}
end
end
@impl Sanbase.Metric.Behaviour
def available_slugs() do
cache_key = {__MODULE__, :slugs_with_prices} |> Sanbase.Cache.hash()
Sanbase.Cache.get_or_store({cache_key, 600}, fn -> Price.available_slugs() end)
end
@impl Sanbase.Metric.Behaviour
def available_slugs(metric) when metric in @metrics do
available_slugs()
end
@impl Sanbase.Metric.Behaviour
def incomplete_metrics(), do: []
@impl Sanbase.Metric.Behaviour
def free_metrics(), do: @free_metrics
@impl Sanbase.Metric.Behaviour
def restricted_metrics(), do: @restricted_metrics
@impl Sanbase.Metric.Behaviour
def access_map(), do: @access_map
@impl Sanbase.Metric.Behaviour
def min_plan_map(), do: @min_plan_map
# Private functions
defp update_opts(opts) do
Keyword.update(opts, :aggregation, @default_aggregation, &(&1 || @default_aggregation))
end
defp docs_links(metric) do
case metric do
"price_usd" -> ["https://academy.santiment.net/metrics/price"]
"price_btc" -> ["https://academy.santiment.net/metrics/price"]
"price_eth" -> ["https://academy.santiment.net/metrics/price"]
"marketcap_usd" -> ["https://academy.santiment.net/metrics/marketcap"]
"volume_usd" -> ["https://academy.santiment.net/metrics/trading-volume"]
_ -> []
end
end
end