Skip to content

Commit

Permalink
Improve available_selectors in getMetric's metadata
Browse files Browse the repository at this point in the history
If a metric is available in multiple modules, combine the available
metrics when reporting in the API.
  • Loading branch information
IvanIvanoff committed Dec 13, 2024
1 parent 354a350 commit 8463d14
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 3 deletions.
3 changes: 2 additions & 1 deletion lib/sanbase/available_metrics/available_metrics.ex
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ defmodule Sanbase.AvailableMetrics do
metrics
|> Enum.map(fn metric ->
{:ok, m} = Sanbase.Metric.metadata(metric)
{:ok, available_selectors} = Sanbase.Metric.available_selectors(metric)

%{
metric: m.metric,
Expand All @@ -79,7 +80,7 @@ defmodule Sanbase.AvailableMetrics do
frequency_seconds: Sanbase.DateTimeUtils.str_to_sec(m.min_interval),
sanbase_access: "free",
sanapi_access: "free",
available_selectors: m.available_selectors,
available_selectors: available_selectors,
required_selectors: m.required_selectors,
access: Map.get(access_map, metric)
}
Expand Down
2 changes: 2 additions & 0 deletions lib/sanbase/metric/behaviour.ex
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ defmodule Sanbase.Metric.Behaviour do

@type available_label_fqns_result :: {:ok, list(String.t())} | {:error, String.t()}

@type available_selectors_result :: {:ok, list(atom())} | {:error, String.t()}

@type has_incomplete_data_result :: boolean()

@type complexity_weight_result :: number()
Expand Down
32 changes: 31 additions & 1 deletion lib/sanbase/metric/metric.ex
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,33 @@ defmodule Sanbase.Metric do
end
end

@doc ~s"""
Get the list of available selectors for a metric.
This is a separate function as it combines the available selectors from multiple
modules that implement the metric.
Most notably, social metrics from CH are precomptued only for slugs, while the
SocialData.MetricAdapter implements it for text, founders, etc.
"""
@spec available_selectors(metric) :: Type.available_selectors_result()
def available_selectors(metric) do
case get_module(metric, return_all_modules: true) do
nil ->
metric_not_available_error(metric)

module_or_modules ->
available_selectors =
module_or_modules
|> List.wrap()
|> Enum.flat_map(fn module ->
{:ok, metadata} = apply(module, :metadata, [metric])
metadata.available_selectors
end)
|> Enum.uniq()

{:ok, available_selectors}
end
end

@doc ~s"""
Get the first datetime for which a given metric is available for a given slug
"""
Expand Down Expand Up @@ -851,7 +878,10 @@ defmodule Sanbase.Metric do
end

true ->
metric_to_single_module(metric, opts)
case Keyword.get(opts, :return_all_modules, false) do
false -> metric_to_single_module(metric, opts)
true -> Map.get(Helper.metric_to_modules_map(), metric)
end
end
end

Expand Down
10 changes: 10 additions & 0 deletions lib/sanbase_web/graphql/resolvers/metric/metric_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ defmodule SanbaseWeb.Graphql.Resolvers.MetricResolver do
end
end

def get_available_selectors(_root, _args, %{source: %{metric: metric}}) do
case Metric.available_selectors(metric) do
{:ok, selectors} ->
{:ok, selectors}

{:error, error} ->
{:error, handle_graphql_error("available_selectors", %{metric: metric}, error)}
end
end

def timeseries_data_complexity(_root, args, resolution) do
# Explicitly set `child_complexity` to 2 as this would be the
# value if both `datetime` and `value` fields are queried.
Expand Down
4 changes: 3 additions & 1 deletion lib/sanbase_web/graphql/schema/types/metric_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,9 @@ defmodule SanbaseWeb.Graphql.MetricTypes do
Every metric has `availableSelectors` in its metadata, showing exactly
which of the selectors can be used.
"""
field(:available_selectors, list_of(:selector_name))
field :available_selectors, list_of(:selector_name) do
resolve(&MetricResolver.get_available_selectors/3)
end

@desc ~s"""
The list of required selectors for the metric. It is used to show the list
Expand Down

0 comments on commit 8463d14

Please sign in to comment.