Current section
Files
Jump to
Current section
Files
lib/fact/engine.ex
defmodule Fact.EngineMetric do
@moduledoc false
require Logger
use Instream.Series
import(Fact.Influx, only: [write: 2])
import(Map, only: [has_key?: 2])
alias Fact.EngineMetric
alias TimeSupport
@metric_type "stat"
@metric_name "engine_phase"
@metric_tags [
:vsn,
:host,
:name,
:engine,
:metric,
:discover_us,
:convert_us,
:report_us
]
@metric_fields [:convert_us, :discover_us, :report_us, :switch_cmd_us]
series do
database(Application.get_env(:helen, Fact.Influx) |> Keyword.get(:database))
# 'type' maps to the measurement
measurement(@metric_type)
tag(:application, default: "helen")
tag(:env, default: Application.get_env(:helen, :build_env, "dev"))
tag(:host)
tag(:name)
tag(:metric, default: @metric_name)
tag(:engine)
field(:convert_us)
field(:discover_us)
field(:report_us)
field(:switch_cmd_us)
end
def make_point(%{type: @metric_type, metric: _, engine: _} = r) do
filtered = Enum.filter(r, &wanted?/1)
Logger.debug(["filter: ", inspect(filtered, pretty: true)])
tags = Enum.filter(filtered, &tag?/1)
fields = Enum.filter(filtered, &field?/1)
pt = %EngineMetric{}
pt = set_tag(pt, tags, :host)
pt = set_tag(pt, tags, :name)
pt = set_tag(pt, tags, :metric)
pt = set_tag(pt, tags, :engine)
pt = set_field(pt, fields, :convert_us)
pt = set_field(pt, fields, :discover_us)
pt = set_field(pt, fields, :report_us)
pt = set_field(pt, fields, :switch_cmd_us)
%{pt | timestamp: Map.get(r, :mtime, TimeSupport.unix_now(:second))}
end
# trap when the input map doesn't match
def make_point(%{} = r) do
Logger.warn(["no match for ", inspect(r, pretty: true)])
%{}
end
def record(%{record: true} = r) do
db = Application.get_env(:helen, Fact.Influx) |> Keyword.get(:database)
make_point(r) |> write(database: db, async: true, precision: :second)
end
def record(%{}), do: {:not_recorded}
defp field?({k, _v}), do: k in @metric_fields
defp tag?({k, _v}), do: k in @metric_tags
defp wanted?({k, v}) do
keep = k in (@metric_tags ++ @metric_fields)
if keep do
cond do
k in @metric_fields and v == 0 -> false
k in @metric_fields and v > 0 -> true
k not in @metric_fields -> true
true -> false
end
end
end
defp set_tag(m, opts, k)
when is_map(m) and is_list(opts) and is_atom(k) do
v = Keyword.get(opts, k, nil)
if is_nil(v), do: m, else: %{m | tags: %{m.tags | k => v}}
end
def set_field(m, opts, k)
when is_map(m) and is_list(opts) and is_atom(k) do
v = Keyword.get(opts, k, nil)
if is_nil(v), do: m, else: %{m | fields: %{m.fields | k => v}}
end
def valid?(%{} = r) do
type = Map.get(r, :type, nil)
metric = Map.get(r, :metric, nil)
type === @metric_type and metric === @metric_name and has_key?(r, :engine)
end
end