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)