diff --git a/plugins/outputs/groundwork/README.md b/plugins/outputs/groundwork/README.md index 0d3129caaf0c2..9d7d443aab53f 100644 --- a/plugins/outputs/groundwork/README.md +++ b/plugins/outputs/groundwork/README.md @@ -26,10 +26,15 @@ This plugin writes to a [GroundWork Monitor][1] instance. Plugin only supports G ## The name of the tag that contains the hostname. # resource_tag = "host" + + ## The name of the tag that contains the host group name. + # group_tag = "group" ``` ## List of tags used by the plugin +* group - to define the name of the group you want to monitor, can be changed with config. +* host - to define the name of the host you want to monitor, can be changed with config. * service - to define the name of the service you want to monitor. * status - to define the status of the service. Supported statuses: "SERVICE_OK", "SERVICE_WARNING", "SERVICE_UNSCHEDULED_CRITICAL", "SERVICE_PENDING", "SERVICE_SCHEDULED_CRITICAL", "SERVICE_UNKNOWN". * message - to provide any message you want. diff --git a/plugins/outputs/groundwork/groundwork.go b/plugins/outputs/groundwork/groundwork.go index cdd686ed71928..a14feb92200a4 100644 --- a/plugins/outputs/groundwork/groundwork.go +++ b/plugins/outputs/groundwork/groundwork.go @@ -38,6 +38,11 @@ const sampleConfig = ` # resource_tag = "host" ` +type metricMeta struct { + group string + resource string +} + type Groundwork struct { Server string `toml:"url"` AgentID string `toml:"agent_id"` @@ -45,6 +50,7 @@ type Groundwork struct { Password string `toml:"password"` DefaultHost string `toml:"default_host"` DefaultServiceState string `toml:"default_service_state"` + GroupTag string `toml:"group_tag"` ResourceTag string `toml:"resource_tag"` Log telegraf.Logger `toml:"-"` client clients.GWClient @@ -123,14 +129,39 @@ func (g *Groundwork) Close() error { } func (g *Groundwork) Write(metrics []telegraf.Metric) error { + groupMap := make(map[string][]transit.ResourceRef) resourceToServicesMap := make(map[string][]transit.MonitoredService) for _, metric := range metrics { - resource, service, err := g.parseMetric(metric) + meta, service, err := g.parseMetric(metric) if err != nil { g.Log.Errorf("%v", err) continue } + resource := meta.resource resourceToServicesMap[resource] = append(resourceToServicesMap[resource], *service) + + group := meta.group + if len(group) != 0 { + resRef := transit.ResourceRef{ + Name: resource, + Type: transit.ResourceTypeHost, + } + if refs, ok := groupMap[group]; ok { + refs = append(refs, resRef) + groupMap[group] = refs + } else { + groupMap[group] = []transit.ResourceRef{resRef} + } + } + } + + groups := make([]transit.ResourceGroup, 0, len(groupMap)) + for groupName, refs := range groupMap { + groups = append(groups, transit.ResourceGroup{ + GroupName: groupName, + Resources: refs, + Type: transit.HostGroup, + }) } var resources []transit.MonitoredResource @@ -163,7 +194,7 @@ func (g *Groundwork) Write(metrics []telegraf.Metric) error { Version: transit.ModelVersion, }, Resources: resources, - Groups: nil, + Groups: groups, }) if err != nil { @@ -185,6 +216,7 @@ func (g *Groundwork) Description() string { func init() { outputs.Add("groundwork", func() telegraf.Output { return &Groundwork{ + GroupTag: "group", ResourceTag: "host", DefaultHost: "telegraf", DefaultServiceState: string(transit.ServiceOk), @@ -192,7 +224,9 @@ func init() { }) } -func (g *Groundwork) parseMetric(metric telegraf.Metric) (string, *transit.MonitoredService, error) { +func (g *Groundwork) parseMetric(metric telegraf.Metric) (metricMeta, *transit.MonitoredService, error) { + group, _ := metric.GetTag(g.GroupTag) + resource := g.DefaultHost if value, present := metric.GetTag(g.ResourceTag); present { resource = value @@ -302,7 +336,7 @@ func (g *Groundwork) parseMetric(metric telegraf.Metric) (string, *transit.Monit serviceObject.Status = serviceStatus } - return resource, &serviceObject, nil + return metricMeta{resource: resource, group: group}, &serviceObject, nil } func validStatus(status string) bool { diff --git a/plugins/outputs/groundwork/groundwork_test.go b/plugins/outputs/groundwork/groundwork_test.go index b27f85d225599..e37a80913cfbf 100644 --- a/plugins/outputs/groundwork/groundwork_test.go +++ b/plugins/outputs/groundwork/groundwork_test.go @@ -23,30 +23,26 @@ const ( func TestWrite(t *testing.T) { // Generate test metric with default name to test Write logic floatMetric := testutil.TestMetric(1.0, "Float") + floatMetric.AddTag("host", "Host01") + floatMetric.AddTag("group", "Group01") // Simulate Groundwork server that should receive custom metrics server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) require.NoError(t, err) - // Decode body to use in assertations below + // Decode body to use in assertions below var obj groundworkObject err = json.Unmarshal(body, &obj) require.NoError(t, err) // Check if server gets valid metrics object - require.Equal(t, obj.Context.AgentID, defaultTestAgentID) - require.Equal(t, obj.Resources[0].Name, defaultHost) - require.Equal( - t, - obj.Resources[0].Services[0].Name, - "Float", - ) - require.Equal( - t, - obj.Resources[0].Services[0].Metrics[0].Value.DoubleValue, - 1.0, - ) + require.Equal(t, defaultTestAgentID, obj.Context.AgentID) + require.Equal(t, "Host01", obj.Resources[0].Name) + require.Equal(t, "Float", obj.Resources[0].Services[0].Name) + require.Equal(t, 1.0, obj.Resources[0].Services[0].Metrics[0].Value.DoubleValue) + require.Equal(t, "Group01", obj.Groups[0].GroupName) + require.Equal(t, "Host01", obj.Groups[0].Resources[0].Name) _, err = fmt.Fprintln(w, `OK`) require.NoError(t, err) @@ -55,6 +51,8 @@ func TestWrite(t *testing.T) { i := Groundwork{ Server: server.URL, AgentID: defaultTestAgentID, + GroupTag: "group", + ResourceTag: "host", DefaultHost: "telegraf", client: clients.GWClient{ AppName: "telegraf", @@ -87,4 +85,12 @@ type groundworkObject struct { } } `json:"services"` } `json:"resources"` + Groups []struct { + Type string `json:"type"` + GroupName string `json:"groupName"` + Resources []struct { + Name string `json:"name"` + Type string `json:"type"` + } `json:"resources"` + } `json:"groups"` }