Show alert annotations (#833)
* Show annotations * Update bindata.go * Fix the versions of elm modules
This commit is contained in:
parent
6a69491ecf
commit
eff5341dec
|
@ -4,28 +4,44 @@ alerts1='[
|
|||
"alertname": "DiskRunningFull",
|
||||
"dev": "sda1",
|
||||
"instance": "example1"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"info": "The disk sda1 is running full",
|
||||
"summary": "please check the instance example1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"labels": {
|
||||
"alertname": "DiskRunningFull",
|
||||
"dev": "sda2",
|
||||
"instance": "example1"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"info": "The disk sda2 is running full",
|
||||
"summary": "please check the instance example1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"labels": {
|
||||
"alertname": "DiskRunningFull",
|
||||
"dev": "sda1",
|
||||
"instance": "example2"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"info": "The disk sda1 is running full",
|
||||
"summary": "please check the instance example2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"labels": {
|
||||
"alertname": "DiskRunningFull",
|
||||
"dev": "sdb2",
|
||||
"instance": "example2"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"info": "The disk sdb2 is running full",
|
||||
"summary": "please check the instance example2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"labels": {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
FROM node:latest
|
||||
|
||||
RUN npm install -g elm elm-format elm-test
|
||||
RUN npm install -g elm@0.18.0 elm-format@0.6.1-alpha elm-test@0.18.3
|
||||
|
|
|
@ -16,47 +16,23 @@ fetchAlerts filter =
|
|||
Utils.Api.send (Utils.Api.get url alertsDecoder)
|
||||
|
||||
|
||||
|
||||
-- Decoders
|
||||
-- Once the API returns the newly created silence, this can go away and we
|
||||
-- re-use the silence decoder.
|
||||
|
||||
|
||||
alertsDecoder : Json.Decoder (List Alert)
|
||||
alertsDecoder =
|
||||
Json.at [ "data" ] (Json.list alertDecoder)
|
||||
Json.list alertDecoder
|
||||
-- populate alerts with ids:
|
||||
|> Json.map (List.indexedMap (toString >> (|>)))
|
||||
|> field "data"
|
||||
|
||||
|
||||
unwrapWithDefault : a -> Maybe a -> Json.Decoder a
|
||||
unwrapWithDefault default val =
|
||||
case val of
|
||||
Just a ->
|
||||
Json.succeed a
|
||||
|
||||
Nothing ->
|
||||
Json.succeed default
|
||||
|
||||
|
||||
alertDecoder : Json.Decoder Alert
|
||||
{-| TODO: decode alert id when provided
|
||||
-}
|
||||
alertDecoder : Json.Decoder (String -> Alert)
|
||||
alertDecoder =
|
||||
Json.map6 Alert
|
||||
(Json.maybe (field "annotations" (Json.keyValuePairs Json.string)) |> andThen (unwrapWithDefault []))
|
||||
Json.map5 Alert
|
||||
(Json.maybe (field "annotations" (Json.keyValuePairs Json.string))
|
||||
|> andThen (Maybe.withDefault [] >> Json.succeed)
|
||||
)
|
||||
(field "labels" (Json.keyValuePairs Json.string))
|
||||
(Json.maybe (field "silenced" Json.string))
|
||||
(decodeSilenced)
|
||||
(Json.maybe (Json.at [ "status", "silencedBy", "0" ] Json.string))
|
||||
(field "startsAt" iso8601Time)
|
||||
(field "generatorURL" Json.string)
|
||||
|
||||
|
||||
decodeSilenced : Decoder Bool
|
||||
decodeSilenced =
|
||||
Json.maybe (field "silenced" Json.string)
|
||||
|> andThen
|
||||
(\val ->
|
||||
case val of
|
||||
Just _ ->
|
||||
Json.succeed True
|
||||
|
||||
Nothing ->
|
||||
Json.succeed False
|
||||
)
|
||||
|
|
|
@ -11,9 +11,9 @@ type alias Alert =
|
|||
{ annotations : Labels
|
||||
, labels : Labels
|
||||
, silenceId : Maybe String
|
||||
, silenced : Bool
|
||||
, startsAt : Time
|
||||
, generatorUrl : String
|
||||
, id : String
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ import Html.Events exposing (onClick)
|
|||
import Types exposing (Msg(CreateSilenceFromAlert, Noop, MsgForAlertList))
|
||||
import Utils.Date
|
||||
import Views.FilterBar.Types as FilterBarTypes
|
||||
import Views.AlertList.Types exposing (AlertListMsg(MsgForFilterBar))
|
||||
import Views.AlertList.Types exposing (AlertListMsg(MsgForFilterBar, SetActive))
|
||||
import Utils.Filter
|
||||
import Time exposing (Time)
|
||||
|
||||
|
||||
view : List ( String, String ) -> Alert -> Html Msg
|
||||
view labels alert =
|
||||
view : List ( String, String ) -> Maybe String -> Alert -> Html Msg
|
||||
view labels maybeActiveId alert =
|
||||
let
|
||||
-- remove the grouping labels, and bring the alertname to front
|
||||
ungroupedLabels =
|
||||
|
@ -25,11 +25,20 @@ view labels alert =
|
|||
li
|
||||
[ class "align-items-start list-group-item border-0 alert-list-item p-0 mb-4"
|
||||
]
|
||||
[ div [ class "w-100 mb-2 d-flex align-items-start" ]
|
||||
[ div
|
||||
[ class "w-100 mb-2 d-flex align-items-start" ]
|
||||
[ dateView alert.startsAt
|
||||
, if List.length alert.annotations > 0 then
|
||||
annotationsButton maybeActiveId alert
|
||||
else
|
||||
text ""
|
||||
, generatorUrlButton alert.generatorUrl
|
||||
, silenceButton alert
|
||||
]
|
||||
, if maybeActiveId == Just alert.id then
|
||||
table [ class "table w-100 mb-1" ] (List.map annotation alert.annotations)
|
||||
else
|
||||
text ""
|
||||
, div [] (List.map labelButton ungroupedLabels)
|
||||
]
|
||||
|
||||
|
@ -43,6 +52,30 @@ dateView time =
|
|||
]
|
||||
|
||||
|
||||
annotationsButton : Maybe String -> Alert -> Html Msg
|
||||
annotationsButton maybeActiveId alert =
|
||||
if maybeActiveId == Just alert.id then
|
||||
button
|
||||
[ onClick (SetActive Nothing |> MsgForAlertList)
|
||||
, class "btn btn-outline-info border-0 active"
|
||||
]
|
||||
[ i [ class "fa fa-minus mr-2" ] [], text "Info" ]
|
||||
else
|
||||
button
|
||||
[ onClick (SetActive (Just alert.id) |> MsgForAlertList)
|
||||
, class "btn btn-outline-info border-0"
|
||||
]
|
||||
[ i [ class "fa fa-plus mr-2" ] [], text "Info" ]
|
||||
|
||||
|
||||
annotation : ( String, String ) -> Html Msg
|
||||
annotation ( key, value ) =
|
||||
tr []
|
||||
[ th [ class "text-nowrap" ] [ text (key ++ ":") ]
|
||||
, td [ class "w-100" ] [ text value ]
|
||||
]
|
||||
|
||||
|
||||
labelButton : ( String, String ) -> Html Msg
|
||||
labelButton ( key, value ) =
|
||||
button
|
||||
|
|
|
@ -12,6 +12,7 @@ type AlertListMsg
|
|||
| MsgForFilterBar FilterBar.Msg
|
||||
| MsgForGroupBar GroupBar.Msg
|
||||
| ToggleSilenced Bool
|
||||
| SetActive (Maybe String)
|
||||
| SetTab Tab
|
||||
|
||||
|
||||
|
@ -25,6 +26,7 @@ type alias Model =
|
|||
, groupBar : GroupBar.Model
|
||||
, filterBar : FilterBar.Model
|
||||
, tab : Tab
|
||||
, activeId : Maybe String
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,4 +36,5 @@ initAlertList =
|
|||
, groupBar = GroupBar.initGroupBar
|
||||
, filterBar = FilterBar.initFilterBar
|
||||
, tab = FilterTab
|
||||
, activeId = Nothing
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ update msg ({ groupBar, filterBar } as model) filter =
|
|||
newFilterBar =
|
||||
FilterBar.setMatchers filter filterBar
|
||||
in
|
||||
( { model | alerts = Loading, filterBar = newFilterBar, groupBar = newGroupBar }
|
||||
( { model | alerts = Loading, filterBar = newFilterBar, groupBar = newGroupBar, activeId = Nothing }
|
||||
, Api.fetchAlerts filter |> Cmd.map (AlertsFetched >> MsgForAlertList)
|
||||
)
|
||||
|
||||
|
@ -67,3 +67,6 @@ update msg ({ groupBar, filterBar } as model) filter =
|
|||
GroupBar.update "/#/alerts" filter msg groupBar
|
||||
in
|
||||
( { model | groupBar = newGroupBar }, Cmd.map (MsgForGroupBar >> MsgForAlertList) cmd )
|
||||
|
||||
SetActive maybeId ->
|
||||
( { model | activeId = maybeId }, Cmd.none )
|
||||
|
|
|
@ -36,7 +36,7 @@ renderSilenced maybeShowSilenced =
|
|||
|
||||
|
||||
view : Model -> Filter -> Html Msg
|
||||
view { alerts, groupBar, filterBar, tab } filter =
|
||||
view { alerts, groupBar, filterBar, tab, activeId } filter =
|
||||
div []
|
||||
[ div
|
||||
[ class "card mb-5" ]
|
||||
|
@ -58,7 +58,7 @@ view { alerts, groupBar, filterBar, tab } filter =
|
|||
]
|
||||
, case alerts of
|
||||
Success alerts ->
|
||||
alertGroups filter groupBar alerts
|
||||
alertGroups activeId filter groupBar alerts
|
||||
|
||||
Loading ->
|
||||
Utils.Views.loading
|
||||
|
@ -71,8 +71,8 @@ view { alerts, groupBar, filterBar, tab } filter =
|
|||
]
|
||||
|
||||
|
||||
alertGroups : Filter -> GroupBar.Model -> List Alert -> Html Msg
|
||||
alertGroups filter groupBar alerts =
|
||||
alertGroups : Maybe String -> Filter -> GroupBar.Model -> List Alert -> Html Msg
|
||||
alertGroups activeId filter groupBar alerts =
|
||||
let
|
||||
grouped =
|
||||
alerts
|
||||
|
@ -86,14 +86,14 @@ alertGroups filter groupBar alerts =
|
|||
|> List.filterMap
|
||||
(\labels ->
|
||||
Maybe.map
|
||||
(alertList labels filter)
|
||||
(alertList activeId labels filter)
|
||||
(Dict.get labels grouped)
|
||||
)
|
||||
|> div []
|
||||
|
||||
|
||||
alertList : Labels -> Filter -> List Alert -> Html Msg
|
||||
alertList labels filter alerts =
|
||||
alertList : Maybe String -> Labels -> Filter -> List Alert -> Html Msg
|
||||
alertList activeId labels filter alerts =
|
||||
div []
|
||||
[ div []
|
||||
(case labels of
|
||||
|
@ -111,5 +111,5 @@ alertList labels filter alerts =
|
|||
, if List.isEmpty alerts then
|
||||
div [] [ text "no alerts found" ]
|
||||
else
|
||||
ul [ class "list-group mb-4" ] (List.map (AlertView.view labels) alerts)
|
||||
ul [ class "list-group mb-4" ] (List.map (AlertView.view labels activeId) alerts)
|
||||
]
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue