youtubebeat/vendor/github.com/elastic/beats/metricbeat/module/kubernetes/event/event.go

172 lines
5.3 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file 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.
package event
import (
"fmt"
"time"
"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/common/cfgwarn"
"github.com/elastic/beats/libbeat/common/kubernetes"
"github.com/elastic/beats/libbeat/common/safemapstr"
"github.com/elastic/beats/metricbeat/mb"
)
// init registers the MetricSet with the central registry.
// The New method will be called after the setup of the module and before starting to fetch data
func init() {
if err := mb.Registry.AddMetricSet("kubernetes", "event", New); err != nil {
panic(err)
}
}
// MetricSet type defines all fields of the MetricSet
// The event MetricSet listens to events from Kubernetes API server and streams them to the output.
// MetricSet implements the mb.PushMetricSet interface, and therefore does not rely on polling.
type MetricSet struct {
mb.BaseMetricSet
watcher kubernetes.Watcher
}
// New create a new instance of the MetricSet
// Part of new is also setting up the configuration by processing additional
// configuration entries if needed.
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
cfgwarn.Beta("The kubernetes event metricset is beta")
config := defaultKubernetesEventsConfig()
err := base.Module().UnpackConfig(&config)
if err != nil {
return nil, fmt.Errorf("fail to unpack the kubernetes event configuration: %s", err)
}
client, err := kubernetes.GetKubernetesClient(config.InCluster, config.KubeConfig)
if err != nil {
return nil, fmt.Errorf("fail to get kubernetes client: %s", err.Error())
}
watcher, err := kubernetes.NewWatcher(client, &kubernetes.Event{}, kubernetes.WatchOptions{
SyncTimeout: config.SyncPeriod,
Namespace: config.Namespace,
})
if err != nil {
return nil, fmt.Errorf("fail to init kubernetes watcher: %s", err.Error())
}
return &MetricSet{
BaseMetricSet: base,
watcher: watcher,
}, nil
}
// Run method provides the Kubernetes event watcher with a reporter with which events can be reported.
func (m *MetricSet) Run(reporter mb.PushReporter) {
now := time.Now()
handler := kubernetes.ResourceEventHandlerFuncs{
AddFunc: func(obj kubernetes.Resource) {
reporter.Event(generateMapStrFromEvent(obj.(*kubernetes.Event)))
},
UpdateFunc: func(obj kubernetes.Resource) {
reporter.Event(generateMapStrFromEvent(obj.(*kubernetes.Event)))
},
// ignore events that are deleted
DeleteFunc: nil,
}
m.watcher.AddEventHandler(kubernetes.FilteringResourceEventHandler{
// skip events happened before watch
FilterFunc: func(obj kubernetes.Resource) bool {
eve := obj.(*kubernetes.Event)
if kubernetes.Time(eve.LastTimestamp).Before(now) {
return false
}
return true
},
Handler: handler,
})
// start event watcher
m.watcher.Start()
<-reporter.Done()
m.watcher.Stop()
return
}
func generateMapStrFromEvent(eve *kubernetes.Event) common.MapStr {
eventMeta := common.MapStr{
"timestamp": common.MapStr{
"created": kubernetes.Time(eve.Metadata.CreationTimestamp).UTC(),
},
"name": eve.Metadata.GetName(),
"namespace": eve.Metadata.GetNamespace(),
"self_link": eve.Metadata.GetSelfLink(),
"generate_name": eve.Metadata.GetGenerateName(),
"uid": eve.Metadata.GetUid(),
"resource_version": eve.Metadata.GetResourceVersion(),
}
if len(eve.Metadata.Labels) != 0 {
labels := make(common.MapStr, len(eve.Metadata.Labels))
for k, v := range eve.Metadata.Labels {
safemapstr.Put(labels, k, v)
}
eventMeta["labels"] = labels
}
if len(eve.Metadata.Annotations) != 0 {
annotations := make(common.MapStr, len(eve.Metadata.Annotations))
for k, v := range eve.Metadata.Annotations {
safemapstr.Put(annotations, k, v)
}
eventMeta["annotations"] = annotations
}
output := common.MapStr{
"message": eve.GetMessage(),
"reason": eve.GetReason(),
"type": eve.GetType(),
"count": eve.GetCount(),
"involved_object": common.MapStr{
"api_version": eve.GetInvolvedObject().GetApiVersion(),
"resource_version": eve.GetInvolvedObject().GetResourceVersion(),
"name": eve.GetInvolvedObject().GetName(),
"kind": eve.GetInvolvedObject().GetKind(),
"uid": eve.GetInvolvedObject().GetUid(),
},
"metadata": eventMeta,
}
tsMap := make(common.MapStr)
if eve.FirstTimestamp != nil {
tsMap["first_occurrence"] = kubernetes.Time(eve.FirstTimestamp).UTC()
}
if eve.LastTimestamp != nil {
tsMap["last_occurrence"] = kubernetes.Time(eve.LastTimestamp).UTC()
}
if len(tsMap) != 0 {
output["timestamp"] = tsMap
}
return output
}