You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/05/13 14:49:58 UTC

[skywalking-kubernetes-event-exporter] 01/01: Add Console exporter, source filter

This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch enhance
in repository https://gitbox.apache.org/repos/asf/skywalking-kubernetes-event-exporter.git

commit dfd605022755bf08185f592583ec65d18389ccdf
Author: kezhenxu94 <ke...@apache.org>
AuthorDate: Thu May 13 22:49:21 2021 +0800

    Add Console exporter, source filter
---
 README.md                                         |   4 +
 assets/default-config.yaml                        |   9 +-
 configs/config.go                                 |  17 ++-
 docs/exporters.md                                 |  14 +++
 assets/default-config.yaml => examples/debug.yaml |  14 +--
 pkg/exporter/console.go                           | 121 ++++++++++++++++++++++
 pkg/exporter/skywalking.go                        |   5 +-
 7 files changed, 168 insertions(+), 16 deletions(-)

diff --git a/README.md b/README.md
index eccc635..fd90561 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,10 @@ specified in the command line interface nor config map created in Kubernetes.
 All available configuration items and their documentations can be found
 in [the default configuration file](assets/default-config.yaml).
 
+## Exporters
+
+The available exporters are listed [here](docs/exporters.md).
+
 ## Deployments
 
 Go to [the /deployments/release](deployments/release) directory, modify according to your needs, and
diff --git a/assets/default-config.yaml b/assets/default-config.yaml
index 11bde2a..27753d3 100644
--- a/assets/default-config.yaml
+++ b/assets/default-config.yaml
@@ -17,14 +17,15 @@
 #
 
 filters:
-  - reason: ""     # filter events of the specified reason, regular expression like "Killing|Killed" is supported.
+  - reason: "Started|Killing"     # filter events of the specified reason, regular expression like "Killing|Killed" is supported.
     message: ""    # filter events of the specified message, regular expression like "Pulling container.*" is supported.
     minCount: 1    # filter events whose count is >= the specified value.
     type: ""       # filter events of the specified type, regular expression like "Normal|Error" is supported.
     action: ""     # filter events of the specified action, regular expression is supported.
-    kind: ""       # filter events of the specified kind, regular expression like "Pod|Service" is supported.
-    namespace: ""  # filter events from the specified namespace, regular expression like "default|bookinfo" is supported, empty means all namespaces.
-    name: ""       # filter events from the specified namespace, regular expression like ".*bookinfo.*" is supported.
+    kind: "Pod|Service"       # filter events of the specified kind, regular expression like "Pod|Service" is supported.
+    namespace: "default"  # filter events from the specified namespace, regular expression like "default|bookinfo" is supported, empty means all namespaces.
+    name: ""       # filter events of the specified involved object name, regular expression like ".*bookinfo.*" is supported.
+    service: "[^\\s]{1,}"  # filter events belonging to services whose name is not empty.
     exporters:     # events satisfy this filter can be exported into several exporters that are defined in the `exporters` section below.
       - skywalking
 
diff --git a/configs/config.go b/configs/config.go
index 04558dd..7243776 100644
--- a/configs/config.go
+++ b/configs/config.go
@@ -21,7 +21,9 @@ package configs
 
 import (
 	"regexp"
+	"strings"
 
+	"github.com/apache/skywalking-kubernetes-event-exporter/pkg/k8s"
 	"gopkg.in/yaml.v3"
 	v1 "k8s.io/api/core/v1"
 
@@ -46,6 +48,8 @@ type FilterConfig struct {
 	namespaceRegExp *regexp.Regexp
 	Name            string `yaml:"name"`
 	nameRegExp      *regexp.Regexp
+	Service         string `yaml:"service"`
+	serviceRegExp   *regexp.Regexp
 
 	Exporters []string `yaml:"exporters"`
 }
@@ -60,6 +64,7 @@ func (filter *FilterConfig) Init() {
 	filter.kindRegExp = regexp.MustCompile(filter.Kind)
 	filter.namespaceRegExp = regexp.MustCompile(filter.Namespace)
 	filter.nameRegExp = regexp.MustCompile(filter.Name)
+	filter.serviceRegExp = regexp.MustCompile(filter.Service)
 }
 
 // Filter the given event with this filter instance.
@@ -83,15 +88,21 @@ func (filter *FilterConfig) Filter(event *v1.Event) bool {
 	if filter.Action != "" && !filter.actionRegExp.MatchString(event.Action) {
 		return true
 	}
-	if filter.Kind != "" && !filter.kindRegExp.MatchString(event.Kind) {
+	if filter.Kind != "" && !filter.kindRegExp.MatchString(event.InvolvedObject.Kind) {
 		return true
 	}
-	if filter.Namespace != "" && !filter.namespaceRegExp.MatchString(event.Namespace) {
+	if filter.Namespace != "" && !filter.namespaceRegExp.MatchString(event.InvolvedObject.Namespace) {
 		return true
 	}
-	if filter.Name != "" && !filter.nameRegExp.MatchString(event.Name) {
+	if filter.Name != "" && !filter.nameRegExp.MatchString(event.InvolvedObject.Name) {
 		return true
 	}
+	if filter.Service != "" {
+		context := k8s.Registry.GetContext(event)
+		if svcName := strings.TrimSpace(context.Service.Name); !filter.serviceRegExp.MatchString(svcName) {
+			return true
+		}
+	}
 	return false
 }
 
diff --git a/docs/exporters.md b/docs/exporters.md
new file mode 100644
index 0000000..b0fedd3
--- /dev/null
+++ b/docs/exporters.md
@@ -0,0 +1,14 @@
+# Exporters
+
+## SkyWalking
+
+[SkyWalking Exporter](../pkg/exporter/skywalking.go) exports the events into Apache SkyWalking OAP server.
+
+The configurations of SkyWalking Exporter can be found [here](../assets/default-config.yaml).
+
+## Console
+
+[Console Exporter](../pkg/exporter/console.go) exports the events into console logs, this exporter is typically used for
+debugging.
+
+The configurations of Console Exporter can be found [here](../assets/default-config.yaml).
diff --git a/assets/default-config.yaml b/examples/debug.yaml
similarity index 71%
copy from assets/default-config.yaml
copy to examples/debug.yaml
index 11bde2a..603867d 100644
--- a/assets/default-config.yaml
+++ b/examples/debug.yaml
@@ -17,19 +17,20 @@
 #
 
 filters:
-  - reason: ""     # filter events of the specified reason, regular expression like "Killing|Killed" is supported.
+  - reason: "Started|Killing"     # filter events of the specified reason, regular expression like "Killing|Killed" is supported.
     message: ""    # filter events of the specified message, regular expression like "Pulling container.*" is supported.
     minCount: 1    # filter events whose count is >= the specified value.
     type: ""       # filter events of the specified type, regular expression like "Normal|Error" is supported.
     action: ""     # filter events of the specified action, regular expression is supported.
-    kind: ""       # filter events of the specified kind, regular expression like "Pod|Service" is supported.
-    namespace: ""  # filter events from the specified namespace, regular expression like "default|bookinfo" is supported, empty means all namespaces.
-    name: ""       # filter events from the specified namespace, regular expression like ".*bookinfo.*" is supported.
+    kind: "Pod|Service"       # filter events of the specified kind, regular expression like "Pod|Service" is supported.
+    namespace: "default"  # filter events from the specified namespace, regular expression like "default|bookinfo" is supported, empty means all namespaces.
+    name: ""       # filter events of the specified involved object name, regular expression like ".*bookinfo.*" is supported.
+    service: "[^\\s]{1,}"  # filter events belonging to services whose name is not empty.
     exporters:     # events satisfy this filter can be exported into several exporters that are defined in the `exporters` section below.
-      - skywalking
+      - console
 
 exporters:         # defines and configures the exporters that can be used in the `filters` section above.
-  skywalking:      # the exporter name, which is declared in the struct type `Exporter`'s Name function.
+  console:      # the exporter name, which is declared in the struct type `Exporter`'s Name function.
     # Below are exporter-specific configurations, different exporter may have different configuration contents.
     template:      # the event template of SkyWalking exporter, it can be composed of metadata like Event, Pod, and Service.
       source:
@@ -37,4 +38,3 @@ exporters:         # defines and configures the exporters that can be used in th
         serviceInstance: "{{ .Pod.Name }}"
         endpoint: ""
       message: "{{ .Event.Message }}" # this is default, just to demonstrate the context
-    address: "127.0.0.1:11800" # the SkyWalking backend address where this exporter will export to.
diff --git a/pkg/exporter/console.go b/pkg/exporter/console.go
new file mode 100644
index 0000000..05a5b1f
--- /dev/null
+++ b/pkg/exporter/console.go
@@ -0,0 +1,121 @@
+/*
+ * Licensed to Apache Software Foundation (ASF) under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Apache Software Foundation (ASF) 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 exporter
+
+import (
+	"encoding/json"
+	"fmt"
+	sw "skywalking.apache.org/repo/goapi/collect/event/v3"
+
+	k8score "k8s.io/api/core/v1"
+
+	"github.com/apache/skywalking-kubernetes-event-exporter/configs"
+	"github.com/apache/skywalking-kubernetes-event-exporter/internal/pkg/logger"
+	"github.com/apache/skywalking-kubernetes-event-exporter/pkg/event"
+)
+
+// Console Exporter exports the events into console logs, this exporter is typically
+// used for debugging.
+type Console struct {
+	config  ConsoleConfig
+	stopper chan struct{}
+}
+
+type ConsoleConfig struct {
+	Template *EventTemplate `mapstructure:"template"`
+}
+
+func init() {
+	s := &Console{
+		stopper: make(chan struct{}),
+	}
+	RegisterExporter(s.Name(), s)
+}
+
+func (exporter *Console) Init() error {
+	config := ConsoleConfig{}
+
+	if c := configs.GlobalConfig.Exporters[exporter.Name()]; c == nil {
+		return fmt.Errorf("configs of %+v exporter cannot be empty", exporter.Name())
+	} else if marshal, err := json.Marshal(c); err != nil {
+		return err
+	} else if err := json.Unmarshal(marshal, &config); err != nil {
+		return err
+	}
+
+	if err := config.Template.Init(); err != nil {
+		return err
+	}
+
+	exporter.config = config
+
+	return nil
+}
+
+func (exporter *Console) Name() string {
+	return "console"
+}
+
+func (exporter *Console) Export(events chan *k8score.Event) {
+	logger.Log.Debugf("exporting events into %+v", exporter.Name())
+
+	func() {
+		for {
+			select {
+			case <-exporter.stopper:
+				drain(events)
+				return
+			case kEvent := <-events:
+				if kEvent == event.Stopper {
+					return
+				}
+				logger.Log.Debugf("exporting event to %v: %v", exporter.Name(), kEvent)
+
+				t := sw.Type_Normal
+				if kEvent.Type == "Warning" {
+					t = sw.Type_Error
+				}
+				swEvent := &sw.Event{
+					Uuid:      string(kEvent.UID),
+					Source:    &sw.Source{},
+					Name:      kEvent.Reason,
+					Type:      t,
+					Message:   kEvent.Message,
+					StartTime: kEvent.FirstTimestamp.UnixNano() / 1000000,
+					EndTime:   kEvent.LastTimestamp.Unix() / 1000000,
+				}
+				if exporter.config.Template != nil {
+					exporter.config.Template.render(swEvent, kEvent)
+					logger.Log.Debugf("rendered event is: %+v", swEvent)
+				}
+				if bytes, err := json.Marshal(swEvent); err != nil {
+					logger.Log.Errorf("failed to send event to %+v, %+v", exporter.Name(), err)
+				} else {
+					logger.Log.Infoln(string(bytes))
+				}
+			}
+		}
+	}()
+}
+
+func (exporter *Console) Stop() {
+	exporter.stopper <- struct{}{}
+	close(exporter.stopper)
+}
diff --git a/pkg/exporter/skywalking.go b/pkg/exporter/skywalking.go
index 015408b..7319bf4 100644
--- a/pkg/exporter/skywalking.go
+++ b/pkg/exporter/skywalking.go
@@ -39,6 +39,7 @@ import (
 	"github.com/apache/skywalking-kubernetes-event-exporter/pkg/event"
 )
 
+// SkyWalking Exporter exports the events into Apache SkyWalking OAP server.
 type SkyWalking struct {
 	config     SkyWalkingConfig
 	client     sw.EventServiceClient
@@ -138,7 +139,7 @@ func (exporter *SkyWalking) Export(events chan *k8score.Event) {
 					EndTime:   kEvent.LastTimestamp.Unix() / 1000000,
 				}
 				if exporter.config.Template != nil {
-					exporter.config.Template.Render(swEvent, kEvent)
+					exporter.config.Template.render(swEvent, kEvent)
 					logger.Log.Debugf("rendered event is: %+v", swEvent)
 				}
 				if err := stream.Send(swEvent); err != nil {
@@ -149,7 +150,7 @@ func (exporter *SkyWalking) Export(events chan *k8score.Event) {
 	}()
 }
 
-func (tmplt *EventTemplate) Render(swEvent *sw.Event, kEvent *k8score.Event) {
+func (tmplt *EventTemplate) render(swEvent *sw.Event, kEvent *k8score.Event) {
 	templateCtx := k8s.Registry.GetContext(kEvent)
 
 	logger.Log.Debugf("template context %+v", templateCtx)