Current section

Files

Jump to
nextroll_erlcloud src erlcloud_mon.erl
Raw

src/erlcloud_mon.erl

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% File: erlcloud_mon.erl
%% Date: 14-Sep-2011
%%
%% @doc AWS CloudWatch erlang binding (the CLI SDK uses "mon_" prefix)
%%
%% @author Zvi Avraham <zvi-AT-nivertech-DOT-com>
%% @copyright 2011 Zvi Avraham
%% @end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(erlcloud_mon).
%%% Library initialization.
-export([configure/2, configure/3, new/2, new/3]).
-export([
list_metrics/5, list_metrics/4,
describe_alarms_for_metric/2,
describe_alarms_for_metric/7,
describe_alarms_for_metric/8,
put_metric_data/3, put_metric_data/2,
put_metric_data/6, put_metric_data/5,
get_metric_statistics/4, get_metric_statistics/9, get_metric_statistics/8,
get_alarm_state/2, get_alarm_state/1,
configure_host/3,
test/0,
test2/0
]).
-include("erlcloud.hrl").
-include("erlcloud_aws.hrl").
-include("erlcloud_mon.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-import(erlcloud_xml, [get_text/2, get_time/2, get_bool/2, get_integer/2,
get_float/2, get_text/1]).
-define(XMLNS_MON, "http://monitoring.amazonaws.com/doc/2010-08-01/").
-define(API_VERSION, "2010-08-01").
-define(FMT(Fmt,Args), lists:flatten(io_lib:format((Fmt),(Args)))).
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - ListMetrics
%% [http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/index.html?API_ListMetrics.html]
%%
%% USAGE:
%%
%% erlcloud_mon:list_metrics("AWS/EC2", "NetworkIn", [{"InstanceType","m1.large"}], "").
%% [[{metric_name,"NetworkIn"},
%% {namespace,"AWS/EC2"},
%% {dimensions,[[{name,"InstanceType"},{value,"m1.large"}]]}]]
%%
%% @end
%%------------------------------------------------------------------------------
-spec list_metrics(
Namespace ::string(),
MetricName ::string(),
DimensionFilter ::[{string(),string()}],
NextToken ::string()
) -> term() | no_return().
list_metrics(
Namespace,
MetricName,
DimensionFilter,
NextToken
) ->
list_metrics(Namespace, MetricName, DimensionFilter, NextToken, default_config()).
-spec list_metrics(
Namespace ::string(),
MetricName ::string(),
DimensionFilter ::[{string(),string()}],
NextToken ::string(),
Config ::aws_config()
) -> term() | no_return().
list_metrics(
Namespace,
MetricName,
DimensionFilter,
NextToken,
#aws_config{} = Config
) ->
Params =
[{"Namespace", Namespace} || Namespace/=""]
++
[{"MetricName", MetricName} || MetricName/=""]
++
[{"NextToken", NextToken} || NextToken/=""]
++
lists:flatten(
[begin
{Name, Value} = lists:nth(N, DimensionFilter),
[{?FMT("Dimensions.member.~b.Name", [N]), Name},
{?FMT("Dimensions.member.~b.Value", [N]), Value}]
end
|| N<-lists:seq(1, length(DimensionFilter))]
),
Doc = mon_query(Config, "ListMetrics", Params),
Members = xmerl_xpath:string("/ListMetricsResponse/ListMetricsResult/Metrics/member", Doc),
[extract_member(Member) || Member <- Members].
extract_member(Node) ->
[
{metric_name, get_text("MetricName", Node)},
{namespace, get_text("Namespace", Node)},
{dimensions,
[extract_dimension(Item) || Item <- xmerl_xpath:string("Dimensions/member", Node)]
}
].
extract_dimension(Node) ->
[
{name, get_text("Name", Node)},
{value, get_text("Value", Node)}
].
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - DescribeAlarmsForMetric
%% [https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarmsForMetric.html]
%%
%% USAGE:
%%
%% erlcloud_mon:describe_alarms_for_metric("AWS/EC2",
%% "NetworkIn").
%% [[{metric_name,"NetworkIn"},
%% {namespace,"AWS/EC2"},
%% {dimensions,[]},
%% {actions_enabled,true},
%% {alarm_actions,[{arn,"arn:aws:sns:us-east-1:123456797777:rgallego_cloudtrail_sns_topic"}]},
%% {alarm_arn,"arn:aws:cloudwatch:us-east-1:123456797777:alarm:rgallego_unauthorized_alarm"},
%% {alarm_configuration_updated_timestamp,{{2018,2,7},
%% {17,38,24}}},
%% {alarm_description,[]},
%% {alarm_name,"rgallego_unauthorized_alarm"},
%% {comparison_operator,"GreaterThanOrEqualToThreshold"},
%% {evaluate_low_sample_count_percentile,[]},
%% {evaluation_periods,1},
%% {extended_statistic,[]},
%% {insufficient_data_actions,[]},
%% {ok_actions,[]},
%% {period,300},
%% {state_reason,"Threshold Crossed: 1 datapoint [2.0 (07/02/18 17:33:00)] was greater than or equal to the threshold (1.0)."},
%% {state_reason_data,"{\"version\":\"1.0\",\"queryDate\":\"2018-02-07T17:38:24.953+0000\",\"startDate\":\"2018-02-07T17:33:00.000+0000\",\"statistic\":\"Sum\",\"period\":300,\"recentDatapoints\":[2.0],\"threshold\":1.0}"},
%% {state_updated_timestamp,{{2018,2,7},{17,38,24}}},
%% {state_value,"ALARM"},
%% {statistic,"Sum"},
%% {threshold,1.0},
%% {treat_missing_data,[]},
%% {unit,[]}]]
%%
%% @end
%%------------------------------------------------------------------------------
-spec describe_alarms_for_metric(
Namespace ::string(),
MetricName ::string()
) -> term().
describe_alarms_for_metric(
Namespace,
MetricName
) ->
describe_alarms_for_metric(Namespace, MetricName, [],
"", undefined, "",
"", default_config()).
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - DescribeAlarmsForMetric
%% [https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarmsForMetric.html]
%%
%% USAGE:
%%
%% erlcloud_mon:describe_alarms_for_metric("AWS/EC2",
%% "NetworkIn",
%% [{"InstanceType","m1.large"}],
%% "p95",
%% 17,
%% "",
%% "Seconds").
%% See describe_alarms_for_metric/2
%%
%% @end
%%------------------------------------------------------------------------------
-spec describe_alarms_for_metric(
Namespace ::string(),
MetricName ::string(),
DimensionFilter ::[{string(),string()}],
ExtendedStatistic ::string(),
Period ::pos_integer(),
Statistic ::statistic(),
Unit ::unit()
) -> term().
describe_alarms_for_metric(
Namespace,
MetricName,
DimensionFilter,
ExtendedStatistic,
Period,
Statistic,
Unit
) ->
describe_alarms_for_metric(Namespace, MetricName, DimensionFilter,
ExtendedStatistic, Period, Statistic,
Unit, default_config()).
-spec describe_alarms_for_metric(
Namespace ::string(),
MetricName ::string(),
DimensionFilter ::[{string(),string()}],
ExtendedStatistic ::string(),
Period ::pos_integer() | undefined,
Statistic ::statistic(),
Unit ::unit(),
Config ::aws_config()
) -> term().
describe_alarms_for_metric(
Namespace,
MetricName,
DimensionFilter,
ExtendedStatistic,
Period,
Statistic,
Unit,
#aws_config{} = Config
) ->
Params =
[{"Namespace", Namespace},
{"MetricName", MetricName}]
++
[{"ExtendedStatistic", ExtendedStatistic} || ExtendedStatistic/=""]
++
[{"Period", Period} || Period/=undefined]
++
[{"Statistic", Statistic} || Statistic/=""]
++
[{"Unit", Unit} || Unit/=""]
++
lists:flatten(
[begin
{Name, Value} = lists:nth(N, DimensionFilter),
[{?FMT("Dimensions.member.~b.Name", [N]), Name},
{?FMT("Dimensions.member.~b.Value", [N]), Value}]
end
|| N<-lists:seq(1, length(DimensionFilter))]
),
Doc = mon_query(Config, "DescribeAlarmsForMetric", Params),
Members = xmerl_xpath:string("/DescribeAlarmsForMetricResponse/DescribeAlarmsForMetricResult/MetricAlarms/member", Doc),
[extract_member_dafm(Member) || Member <- Members].
extract_member_dafm(Node) ->
[
{metric_name, get_text("MetricName", Node)},
{namespace, get_text("Namespace", Node)},
{dimensions,
[extract_dimension_dafm(Item) || Item <- xmerl_xpath:string("Dimensions/member", Node)]
},
{actions_enabled, get_bool("ActionsEnabled", Node)},
{alarm_actions,
[extract_actions_dafm(Item) || Item <- xmerl_xpath:string("AlarmActions/member", Node)]},
{alarm_arn, get_text("AlarmArn", Node)},
{alarm_configuration_updated_timestamp, get_time("AlarmConfigurationUpdatedTimestamp", Node)},
{alarm_description, get_text("AlarmDescription", Node)},
{alarm_name, get_text("AlarmName", Node)},
{comparison_operator, get_text("ComparisonOperator", Node)},
{evaluate_low_sample_count_percentile, get_text("EvaluateLowSampleCountPercentile", Node)},
{evaluation_periods, get_integer("EvaluationPeriods", Node)},
{extended_statistic, get_text("ExtendedStatistic", Node)},
{insufficient_data_actions,
[extract_actions_dafm(Item) || Item <- xmerl_xpath:string("InsufficientDataActions/member", Node)]},
{ok_actions,
[extract_actions_dafm(Item) || Item <- xmerl_xpath:string("OKActions/member", Node)]},
{period, get_integer("Period", Node)},
{state_reason, get_text("StateReason", Node)},
{state_reason_data, get_text("StateReasonData", Node)},
{state_updated_timestamp, get_time("StateUpdatedTimestamp", Node)},
{state_value, get_text("StateValue", Node)},
{statistic, get_text("Statistic", Node)},
{threshold, get_float("Threshold", Node)},
{treat_missing_data, get_text("TreatMissingData", Node)},
{unit, get_text("Unit", Node)}
].
extract_dimension_dafm(Node) ->
[
{name, get_text("Name", Node)},
{value, get_text("Value", Node)}
].
extract_actions_dafm(Node) ->
{arn, get_text(Node)}.
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - PutMetricData
%% [http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/index.html?API_PutMetricData.html]
%% `
%% &MetricData.member.1.MetricName=buffers
%% &MetricData.member.1.Unit=Bytes
%% &MetricData.member.1.Value=231434333
%% &MetricData.member.1.Dimensions.member.1.Name=InstanceID
%% &MetricData.member.1.Dimensions.member.1.Value=i-aaba32d4
%% &MetricData.member.1.Dimensions.member.2.Name=InstanceType
%% &MetricData.member.1.Dimensions.member.2.Value=m1.small
%% &MetricData.member.2.MetricName=latency
%% &MetricData.member.2.Unit=Milliseconds
%% &MetricData.member.2.Value=23
%% &MetricData.member.2.Dimensions.member.1.Name=InstanceID
%% &MetricData.member.2.Dimensions.member.1.Value=i-aaba32d4
%% &MetricData.member.2.Dimensions.member.2.Name=InstanceType
%% &MetricData.member.2.Dimensions.member.2.Value=m1.small
%% '
%% @end
%%------------------------------------------------------------------------------
-spec put_metric_data(
Namespace ::string(),
MetricData ::[metric_datum()]
) -> term() | no_return().
put_metric_data(Namespace, MetricData) ->
put_metric_data(Namespace, MetricData, default_config()).
-spec put_metric_data(
Namespace ::string(),
MetricData ::[metric_datum()],
Config ::aws_config()
) -> term() | no_return().
put_metric_data(Namespace, MetricData, #aws_config{} = Config) ->
Params =
[
{"Namespace", Namespace} |
lists:flatten(
[ params_metric_data(N,MD) || {N,MD} <- lists:zip(lists:seq(1,length(MetricData)), MetricData) ]
)
],
mon_query(Config, "PutMetricData", Params).
%%------------------------------------------------------------------------------
-spec params_metric_data(NM::pos_integer(), MD::metric_datum()) -> [{string(),string()}].
params_metric_data(NM,MD) ->
%% TODO - check case when both Value and statistics specified or both undefined
Prefix = ?FMT("MetricData.member.~b", [NM]),
lists:flatten(
[
[ {Prefix++".MetricName", MD#metric_datum.metric_name} ],
[ {Prefix++".Unit", MD#metric_datum.unit} || MD#metric_datum.unit=/=undefined ],
[ {Prefix++".Timestamp", format_timestamp(MD#metric_datum.timestamp)}|| MD#metric_datum.timestamp=/=undefined ],
[ {Prefix++".Value", float_to_list(MD#metric_datum.value)} || MD#metric_datum.value=/=undefined ],
[ params_stat(Prefix, MD#metric_datum.statistic_values) || MD#metric_datum.statistic_values=/=undefined ],
[ params_dimension(Prefix, ND, Dimension)
|| {ND,Dimension} <- lists:zip(lists:seq(1, length(MD#metric_datum.dimensions)), MD#metric_datum.dimensions)
]
]
).
%%------------------------------------------------------------------------------
%% @doc format datetime as Amazon timestamp
%% @end
%%------------------------------------------------------------------------------
format_timestamp({{Yr, Mo, Da}, {H, M, S}} = Timestamp)
when is_integer(Yr), is_integer(Mo), is_integer(Da),
is_integer(H), is_integer(M), is_integer(S)
->
erlcloud_aws:format_timestamp(Timestamp);
format_timestamp(Timestamp) when is_list(Timestamp) ->
Timestamp.
%%------------------------------------------------------------------------------
-spec params_dimension(Prefix::string(), ND::pos_integer(), Dimension::dimension()) -> [{string(),string()}].
params_dimension(Prefix, ND, Dimension) ->
DimPrefix = ?FMT("~s.Dimensions.member.~b", [Prefix, ND]),
[
{DimPrefix++".Name", Dimension#dimension.name},
{DimPrefix++".Value", Dimension#dimension.value}
].
%%------------------------------------------------------------------------------
%% @doc format statistic value records to URI params
%% @end
%%------------------------------------------------------------------------------
-spec params_stat(Prefix::string(), StatisticValues::statistic_set()) -> [{string(),string()}].
params_stat(Prefix, StatisticValues) ->
[
{Prefix++".StatisticValues.Maximum", float_to_list(StatisticValues#statistic_set.maximum)},
{Prefix++".StatisticValues.Minimum", float_to_list(StatisticValues#statistic_set.minimum)},
{Prefix++".StatisticValues.Sum", float_to_list(StatisticValues#statistic_set.sum)},
{Prefix++".StatisticValues.SampleCount",integer_to_list(StatisticValues#statistic_set.sample_count)}
].
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - PutMetricData
%% [http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/index.html?API_PutMetricData.html]
%% @end
%%------------------------------------------------------------------------------
-spec put_metric_data(
Namespace ::string(),
MetricName ::string(),
Value ::string(),
Unit ::unit(),
Timestamp ::datetime()|string()
) -> term() | no_return().
put_metric_data(Namespace, MetricName, Value, Unit, Timestamp) ->
put_metric_data(Namespace, MetricName, Value, Unit, Timestamp, default_config()).
-spec put_metric_data(
Namespace ::string(),
MetricName ::string(),
Value ::string(),
Unit ::unit(),
Timestamp ::datetime()|string(),
Config ::aws_config()
) -> term() | no_return().
put_metric_data(Namespace, MetricName, Value, Unit, Timestamp, #aws_config{} = Config) ->
Params =
lists:flatten(
[
{"Namespace", Namespace},
{"MetricData.member.1.MetricName", MetricName},
{"MetricData.member.1.Value", Value},
[ {"MetricData.member.1.Unit", Unit} || Unit=/=undefined, Unit=/="" ],
[ {"MetricData.member.1.Timestamp", format_timestamp(Timestamp)} || Timestamp=/=undefined, Timestamp=/="" ]
]
),
mon_simple_query(Config, "PutMetricData", Params).
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - GetMetricStatistics - Easy average version
%% Gets average and max stats at 60 second intervals for
%% the given metric on the given instance for the given interval
%% @end
%%------------------------------------------------------------------------------
-spec get_metric_statistics(
MetricName ::string(),
StartTime ::datetime() | string(),
EndTime ::datetime() | string(),
InstanceId ::string()
) -> term() | no_return().
get_metric_statistics(
MetricName,
StartTime,
EndTime,
InstanceId) ->
get_metric_statistics(
"AWS/EC2",
MetricName,
StartTime,
EndTime,
60,
"",
["Average","Maximum"],
[{"InstanceId", InstanceId}]).
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - GetMetricStatistics
%% [http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/index.html?API_GetMetricStatistics.html]
%%
%% USAGE:
%%
%% erlcloud_mon:get_metric_statistics(
%% "AWS/EC2",
%% "CPUUtilization",
%% {{2016, 06, 29}, {0, 0, 0}},
%% "2016-06-29T00:30:00Z",
%% 60,
%% "Percent",
%% ["Average", "Maximum"],
%% [{"InstanceType", "t2.micro"}]).
%%
%% @end
%%------------------------------------------------------------------------------
-spec get_metric_statistics(
Namespace ::string(),
MetricName ::string(),
StartTime ::datetime() | string(),
EndTime ::datetime() | string(),
Period ::pos_integer(),
Unit ::string(),
Statistics ::[string()],
Dimensions ::[{string(), string()}]
) -> term() | no_return().
get_metric_statistics(
Namespace,
MetricName,
StartTime,
EndTime,
Period,
Unit,
Statistics,
Dimensions
) ->
get_metric_statistics(
Namespace,
MetricName,
StartTime,
EndTime,
Period,
Unit,
Statistics,
Dimensions,
default_config()
).
-spec get_metric_statistics(
Namespace ::string(),
MetricName ::string(),
StartTime ::datetime() | string(),
EndTime ::datetime() | string(),
Period ::pos_integer(),
Unit ::string(),
Statistics ::[string()],
Dimensions ::[{string(), string()}],
Config ::aws_config()
) -> term() | no_return().
get_metric_statistics(
Namespace,
MetricName,
StartTime,
EndTime,
Period,
Unit,
Statistics,
Dimensions,
#aws_config{} = Config
) ->
Params =
lists:flatten([
{"Namespace", Namespace},
{"MetricName", MetricName},
{"StartTime", format_timestamp(StartTime)},
{"EndTime", format_timestamp(EndTime)},
{"Period", Period},
[{"Unit", Unit} || Unit=/=undefined, Unit=/=""]
])
++
lists:flatten(
[begin
Value = lists:nth(N, Statistics),
[{?FMT("Statistics.member.~b", [N]), Value}]
end
|| N<-lists:seq(1, length(Statistics))]
)
++
lists:flatten(
[begin
{Name, Value} = lists:nth(N, Dimensions),
[{?FMT("Dimensions.member.~b.Name", [N]), Name},
{?FMT("Dimensions.member.~b.Value", [N]), Value}]
end
|| N<-lists:seq(1, length(Dimensions))]
),
Doc = mon_query(Config, "GetMetricStatistics", Params),
Members = xmerl_xpath:string("/GetMetricStatisticsResponse/GetMetricStatisticsResult/Datapoints/member", Doc),
Label = get_text("Label", hd(xmerl_xpath:string("/GetMetricStatisticsResponse/GetMetricStatisticsResult", Doc))),
[{"label", Label}, {"datapoints", [extract_metrics(Member, Statistics) || Member <- Members]}].
extract_metrics(Node, Statistics) ->
[
{timestamp, get_time("Timestamp", Node)},
{unit, get_text("Unit", Node)}
]
++
[ {string:to_lower(Statistic), get_text(Statistic, Node)} || Statistic <- Statistics].
%%------------------------------------------------------------------------------
%% @doc CloudWatch API - check alarm state using DescribeAlarms query
%% [https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html]
%% @end
%%------------------------------------------------------------------------------
-spec get_alarm_state(
AlarmName ::string()
) -> string() | no_return().
get_alarm_state(AlarmName) ->
get_alarm_state(AlarmName, default_config()).
-spec get_alarm_state(
AlarmName ::string(),
Config ::aws_config()
) -> string() | no_return().
get_alarm_state(AlarmName, #aws_config{} = Config) ->
Params = [{"AlarmNames.member.1", AlarmName}],
Doc = mon_query(Config, "DescribeAlarms", Params),
[Member] = xmerl_xpath:string(
"/DescribeAlarmsResponse/DescribeAlarmsResult/MetricAlarms/member",
Doc),
get_text("StateValue", Member).
%%------------------------------------------------------------------------------
mon_simple_query(Config, Action, Params) ->
mon_query(Config, Action, Params),
ok.
mon_query(Config, Action, Params) ->
mon_query(Config, Action, Params, ?API_VERSION).
mon_query(Config, Action, Params, ApiVersion) ->
QParams = [{"Action", Action}, {"Version", ApiVersion}|Params],
case erlcloud_aws:aws_request_xml4(get,
Config#aws_config.mon_protocol,
Config#aws_config.mon_host,
Config#aws_config.mon_port,
"/",
QParams,
"monitoring",
Config)
of
{ok, Body} ->
Body;
{error, Reason} ->
erlang:error({aws_error, Reason})
end.
configure_host(Host, Port, Protocol) ->
Config = default_config(),
NewConfig = Config#aws_config{mon_host=Host,
mon_port=Port,
mon_protocol=Protocol},
put(aws_config, NewConfig).
-spec new(string(), string()) -> aws_config().
new(AccessKeyID, SecretAccessKey) ->
#aws_config{access_key_id=AccessKeyID,
secret_access_key=SecretAccessKey}.
-spec new(string(), string(), string()) -> aws_config().
new(AccessKeyID, SecretAccessKey, Host) ->
#aws_config{access_key_id=AccessKeyID,
secret_access_key=SecretAccessKey,
mon_host=Host}.
-spec configure(string(), string()) -> ok.
configure(AccessKeyID, SecretAccessKey) ->
put(aws_config, new(AccessKeyID, SecretAccessKey)),
ok.
-spec configure(string(), string(), string()) -> ok.
configure(AccessKeyID, SecretAccessKey, Host) ->
put(aws_config, new(AccessKeyID, SecretAccessKey, Host)),
ok.
default_config() ->
case get(aws_config) of
undefined ->
DefaultConfig = erlcloud_aws:default_config(),
{ok, Region} = erlcloud_aws:region(DefaultConfig),
RegionHost = endpoint(Region),
Config = DefaultConfig#aws_config{mon_host = RegionHost},
put(aws_config, Config),
Config;
Config ->
Config
end.
%%%===================================================================
%%% Internal Functions
%%%===================================================================
endpoint("us-east-1") -> "monitoring.us-east-1.amazonaws.com";
endpoint("us-west-1") -> "monitoring.us-west-1.amazonaws.com";
endpoint("us-west-2") -> "monitoring.us-west-2.amazonaws.com";
endpoint("ap-northeast-1") -> "monitoring.ap-northeast-1.amazonaws.com";
endpoint("ap-southeast-1") -> "monitoring.ap-southeast-1.amazonaws.com";
endpoint("eu-west-1") -> "monitoring.eu-west-1.amazonaws.com".
%%------------------------------------------------------------------------------
%% tests
%% TODO : convert into e-unit tests
%%------------------------------------------------------------------------------
test() ->
M1 = #metric_datum{
metric_name = "zvi",
dimensions = [],
statistic_values = undefined,
timestamp = undefined,
unit = "Count",
value = 10.0
},
M2 = #metric_datum{
metric_name = "zvi",
dimensions = [],
statistic_values = #statistic_set{minimum=18.0, maximum=21.4, sum=67.7, sample_count=15},
timestamp = undefined,
unit = "Count",
value = undefined
},
put_metric_data("my", [M1, M2]).
%put_metric_data("my", [M2]).
test2() ->
put_metric_data("my", "zvi", "13", "Count", "").