|
|
@@ -191,10 +191,7 @@ do_start_client(
|
|
|
ClientConfig,
|
|
|
Config = #{
|
|
|
egress := #{
|
|
|
- measurement := Measurement,
|
|
|
- timestamp := Timestamp,
|
|
|
- tags := Tags,
|
|
|
- fields := Fields
|
|
|
+ write_syntax := Lines
|
|
|
}
|
|
|
}
|
|
|
) ->
|
|
|
@@ -204,10 +201,7 @@ do_start_client(
|
|
|
true ->
|
|
|
State = #{
|
|
|
client => Client,
|
|
|
- measurement => emqx_plugin_libs_rule:preproc_tmpl(Measurement),
|
|
|
- timestamp => emqx_plugin_libs_rule:preproc_tmpl(Timestamp),
|
|
|
- tags => to_tags_config(Tags),
|
|
|
- fields => to_fields_config(Fields)
|
|
|
+ write_syntax => to_config(Lines)
|
|
|
},
|
|
|
?SLOG(info, #{
|
|
|
msg => "starting influxdb connector success",
|
|
|
@@ -306,46 +300,65 @@ ssl_config(SSL = #{enable := true}) ->
|
|
|
%% Query
|
|
|
|
|
|
do_query(InstId, {send_message, Data}, AfterQuery, State = #{client := Client}) ->
|
|
|
- case data_to_point(Data, State) of
|
|
|
- {ok, Point} ->
|
|
|
- case influxdb:write(Client, [Point]) of
|
|
|
- ok ->
|
|
|
- ?SLOG(debug, #{
|
|
|
- msg => "influxdb write point success",
|
|
|
- connector => InstId,
|
|
|
- point => Point
|
|
|
- }),
|
|
|
- emqx_resource:query_success(AfterQuery);
|
|
|
- {error, Reason} ->
|
|
|
- ?SLOG(error, #{
|
|
|
- msg => "influxdb write point failed",
|
|
|
- connector => InstId,
|
|
|
- reason => Reason
|
|
|
- }),
|
|
|
- emqx_resource:query_failed(AfterQuery)
|
|
|
- end;
|
|
|
- {error, Reason} ->
|
|
|
+ {Points, Errs} = data_to_points(Data, State),
|
|
|
+ lists:foreach(
|
|
|
+ fun({error, Reason}) ->
|
|
|
?SLOG(error, #{
|
|
|
msg => "influxdb trans point failed",
|
|
|
connector => InstId,
|
|
|
reason => Reason
|
|
|
+ })
|
|
|
+ end,
|
|
|
+ Errs
|
|
|
+ ),
|
|
|
+ case influxdb:write(Client, Points) of
|
|
|
+ ok ->
|
|
|
+ ?SLOG(debug, #{
|
|
|
+ msg => "influxdb write point success",
|
|
|
+ connector => InstId,
|
|
|
+ points => Points
|
|
|
}),
|
|
|
- {error, Reason}
|
|
|
+ emqx_resource:query_success(AfterQuery);
|
|
|
+ {error, Reason} ->
|
|
|
+ ?SLOG(error, #{
|
|
|
+ msg => "influxdb write point failed",
|
|
|
+ connector => InstId,
|
|
|
+ reason => Reason
|
|
|
+ }),
|
|
|
+ emqx_resource:query_failed(AfterQuery)
|
|
|
end.
|
|
|
|
|
|
%% -------------------------------------------------------------------------------------------------
|
|
|
%% Tags & Fields Config Trans
|
|
|
|
|
|
-to_tags_config(Tags) ->
|
|
|
- maps:fold(fun to_maps_config/3, #{}, Tags).
|
|
|
+to_config(Lines) ->
|
|
|
+ to_config(Lines, []).
|
|
|
|
|
|
-to_fields_config(Fields) ->
|
|
|
- maps:fold(fun to_maps_config/3, #{}, Fields).
|
|
|
+to_config([], Acc) ->
|
|
|
+ lists:reverse(Acc);
|
|
|
+to_config(
|
|
|
+ [
|
|
|
+ #{
|
|
|
+ measurement := Measurement,
|
|
|
+ timestamp := Timestamp,
|
|
|
+ tags := Tags,
|
|
|
+ fields := Fields
|
|
|
+ }
|
|
|
+ | Rest
|
|
|
+ ],
|
|
|
+ Acc
|
|
|
+) ->
|
|
|
+ Res = #{
|
|
|
+ measurement => emqx_plugin_libs_rule:preproc_tmpl(Measurement),
|
|
|
+ timestamp => emqx_plugin_libs_rule:preproc_tmpl(Timestamp),
|
|
|
+ tags => to_kv_config(Tags),
|
|
|
+ fields => to_kv_config(Fields)
|
|
|
+ },
|
|
|
+ to_config(Rest, [Res | Acc]).
|
|
|
+
|
|
|
+to_kv_config(KVfields) ->
|
|
|
+ maps:fold(fun to_maps_config/3, #{}, proplists:to_map(KVfields)).
|
|
|
|
|
|
-to_maps_config(K, [IntType, V], Res) when IntType == <<"int">> orelse IntType == <<"uint">> ->
|
|
|
- NK = emqx_plugin_libs_rule:preproc_tmpl(bin(K)),
|
|
|
- NV = emqx_plugin_libs_rule:preproc_tmpl(bin(V)),
|
|
|
- Res#{NK => {binary_to_atom(IntType, utf8), NV}};
|
|
|
to_maps_config(K, V, Res) ->
|
|
|
NK = emqx_plugin_libs_rule:preproc_tmpl(bin(K)),
|
|
|
NV = emqx_plugin_libs_rule:preproc_tmpl(bin(V)),
|
|
|
@@ -353,14 +366,24 @@ to_maps_config(K, V, Res) ->
|
|
|
|
|
|
%% -------------------------------------------------------------------------------------------------
|
|
|
%% Tags & Fields Data Trans
|
|
|
-data_to_point(
|
|
|
+data_to_points(Data, #{write_syntax := Lines}) ->
|
|
|
+ lines_to_points(Data, Lines, [], []).
|
|
|
+
|
|
|
+lines_to_points(_, [], Points, Errs) ->
|
|
|
+ {Points, Errs};
|
|
|
+lines_to_points(
|
|
|
Data,
|
|
|
- #{
|
|
|
- measurement := Measurement,
|
|
|
- timestamp := Timestamp,
|
|
|
- tags := Tags,
|
|
|
- fields := Fields
|
|
|
- }
|
|
|
+ [
|
|
|
+ #{
|
|
|
+ measurement := Measurement,
|
|
|
+ timestamp := Timestamp,
|
|
|
+ tags := Tags,
|
|
|
+ fields := Fields
|
|
|
+ }
|
|
|
+ | Rest
|
|
|
+ ],
|
|
|
+ ResAcc,
|
|
|
+ ErrAcc
|
|
|
) ->
|
|
|
TransOptions = #{return => rawlist, var_trans => fun data_filter/1},
|
|
|
case emqx_plugin_libs_rule:proc_tmpl(Timestamp, Data, TransOptions) of
|
|
|
@@ -373,24 +396,11 @@ data_to_point(
|
|
|
tags => EncodeTags,
|
|
|
fields => EncodeFields
|
|
|
},
|
|
|
- {ok, Point};
|
|
|
+ lines_to_points(Data, Rest, [Point | ResAcc], ErrAcc);
|
|
|
BadTimestamp ->
|
|
|
- {error, {bad_timestamp, BadTimestamp}}
|
|
|
+ lines_to_points(Data, Rest, ResAcc, [{error, {bad_timestamp, BadTimestamp}} | ErrAcc])
|
|
|
end.
|
|
|
|
|
|
-maps_config_to_data(K, {IntType, V}, {Data, Res}) when IntType == int orelse IntType == uint ->
|
|
|
- KTransOptions = #{return => full_binary},
|
|
|
- VTransOptions = #{return => rawlist, var_trans => fun data_filter/1},
|
|
|
- NK = emqx_plugin_libs_rule:proc_tmpl(K, Data, KTransOptions),
|
|
|
- NV = emqx_plugin_libs_rule:proc_tmpl(V, Data, VTransOptions),
|
|
|
- case {NK, NV} of
|
|
|
- {[undefined], _} ->
|
|
|
- {Data, Res};
|
|
|
- {_, [undefined]} ->
|
|
|
- {Data, Res};
|
|
|
- {_, [IntV]} when is_integer(IntV) ->
|
|
|
- {Data, Res#{NK => {IntType, IntV}}}
|
|
|
- end;
|
|
|
maps_config_to_data(K, V, {Data, Res}) ->
|
|
|
KTransOptions = #{return => full_binary},
|
|
|
VTransOptions = #{return => rawlist, var_trans => fun data_filter/1},
|
|
|
@@ -402,9 +412,38 @@ maps_config_to_data(K, V, {Data, Res}) ->
|
|
|
{_, [undefined]} ->
|
|
|
{Data, Res};
|
|
|
_ ->
|
|
|
- {Data, Res#{NK => NV}}
|
|
|
+ {Data, Res#{NK => value_type(NV)}}
|
|
|
end.
|
|
|
|
|
|
+value_type([Int, <<"i">>]) when
|
|
|
+ is_integer(Int)
|
|
|
+->
|
|
|
+ {int, Int};
|
|
|
+value_type([UInt, <<"u">>]) ->
|
|
|
+ {uint, UInt};
|
|
|
+value_type([<<"t">>]) ->
|
|
|
+ 't';
|
|
|
+value_type([<<"T">>]) ->
|
|
|
+ 'T';
|
|
|
+value_type([<<"true">>]) ->
|
|
|
+ 'true';
|
|
|
+value_type([<<"TRUE">>]) ->
|
|
|
+ 'TRUE';
|
|
|
+value_type([<<"True">>]) ->
|
|
|
+ 'True';
|
|
|
+value_type([<<"f">>]) ->
|
|
|
+ 'f';
|
|
|
+value_type([<<"F">>]) ->
|
|
|
+ 'F';
|
|
|
+value_type([<<"false">>]) ->
|
|
|
+ 'false';
|
|
|
+value_type([<<"FALSE">>]) ->
|
|
|
+ 'FALSE';
|
|
|
+value_type([<<"False">>]) ->
|
|
|
+ 'False';
|
|
|
+value_type(Val) ->
|
|
|
+ Val.
|
|
|
+
|
|
|
data_filter(undefined) -> undefined;
|
|
|
data_filter(Int) when is_integer(Int) -> Int;
|
|
|
data_filter(Number) when is_number(Number) -> Number;
|