blob: 65ce1a416f0df38cd1c08c75d32b945eafa0b30e [file] [log] [blame]
%% -------------------------------------------------------------------
%%
%% derived from riaknostic - automated diagnostic tools for Riak
%%
%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
%%
%% This file is provided to you under the Apache License,
%% Version 2.0 (the "License"); you may not use this file
%% except in compliance with the License. You may obtain
%% a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied. See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%
%% -------------------------------------------------------------------
%%
%% File renamed from riaknostic_check.erl to weatherreport_check.erl
%% and modified to work with Apache CouchDB
%%
%% Copyright (c) 2014 Cloudant
%%
%% -------------------------------------------------------------------
%% @doc <p>Enforces a common API among all diagnostic modules and
%% provides some automation around their execution.</p>
%% <h2>Behaviour Specification</h2>
%%
%% <h3>description/0</h3>
%% <pre>-spec description() -> iodata().</pre>
%% <p>A short description of what the diagnostic does, which will be
%% printed when the script is given the <code>-l</code> flag.</p>
%%
%% <h3>valid/0</h3>
%% <pre>-spec valid() -> boolean().</pre>
%% <p>Whether the diagnostic is valid to run. For example, some checks
%% require connectivity to the cluster node and hence call {@link
%% weatherreport_node:can_connect/0. weatherreport_node:can_connect()}.</p>
%%
%% <h3>check/0</h3>
%% <pre>-spec check() -> [{atom(), term()}].</pre>
%% <p>Runs the diagnostic, returning a list of pairs, where the first
%% is a severity level and the second is any term that is understood
%% by the <code>format/1</code> callback.</p>
%%
%% <h3>format/1</h3>
%% <pre>-spec format(term()) -> iodata() | {io:format(), [term()]}.</pre>
%% <p>Formats terms that were returned from <code>check/0</code> for
%% output to the console. Valid return values are an iolist (string,
%% binary, etc) or a pair of a format string and a list of terms, as
%% you would pass to {@link io:format/2. io:format/2}.</p>
%% @end
-module(weatherreport_check).
-export([behaviour_info/1]).
-export([
check/2,
modules/0,
print/1
]).
%% @doc The behaviour definition for diagnostic modules.
-spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
behaviour_info(callbacks) ->
[
{description, 0},
{valid, 0},
{check, 1},
{format, 1}
];
behaviour_info(_) ->
undefined.
%% @doc Runs the diagnostic in the given module, if it is valid. Returns a
%% list of messages that will be printed later using print/1.
-spec check(Module :: module(), list()) -> [{atom(), module(), term()}].
check(Module, Opts) ->
case Module:valid() of
true ->
[{Level, Module, Message} || {Level, Message} <- Module:check(Opts)];
_ ->
[]
end.
%% @doc Collects a list of diagnostic modules included in the
%% weatherreport application.
-spec modules() -> [module()].
modules() ->
{ok, Mods} = application:get_key(weatherreport, modules),
[
M
|| M <- Mods,
Attr <- M:module_info(attributes),
{behaviour, [?MODULE]} =:= Attr orelse {behavior, [?MODULE]} =:= Attr
].
%% @doc Formats and prints the given message. The diagnostic
%% module's format/1 function will be called to provide a
%% human-readable message. It should return an iolist() or a 2-tuple
%% consisting of a format string and a list of terms.
-spec print({Node :: atom(), Level :: atom(), Module :: module(), Data :: term()}) -> ok.
print({Node, Level, Mod, Data}) ->
case Mod:format(Data) of
{Format, Terms} ->
weatherreport_log:log(Node, Level, Format, Terms);
String ->
weatherreport_log:log(Node, Level, String)
end.