This repository has been archived by the owner on Aug 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsentry-kubernetes.go
134 lines (114 loc) · 3.09 KB
/
sentry-kubernetes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"flag"
"fmt"
"os"
"time"
"github.com/getsentry/sentry-go"
api "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // external cluster config
"k8s.io/client-go/rest"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/client-go/tools/cache"
)
var debugFlag = flag.Bool("debug", false, "Enable debug logging --debug true")
func main() {
flag.Parse()
config, err := rest.InClusterConfig()
// create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
dsn := os.Getenv("DSN")
if dsn == "" {
fmt.Println("Missing DSN ENV token")
os.Exit(1)
}
namespace := os.Getenv("namespace")
if namespace == "" {
namespace = api.NamespaceAll
}
env := os.Getenv("ENV")
err = sentry.Init(sentry.ClientOptions{
Dsn: dsn,
Environment: env,
})
if err != nil {
fmt.Println("unable to connect to sentry")
os.Exit(1)
}
fmt.Println("Starting go-sentry-kubernetes")
debug(fmt.Sprintf("Using ENV: %s\n", env))
if err != nil {
panic(err.Error())
}
watchlist := cache.NewListWatchFromClient(
clientset.Core().RESTClient(),
"pods",
namespace,
fields.Everything(),
)
_, controller := cache.NewInformer(
watchlist,
&api.Pod{},
time.Second*0,
cache.ResourceEventHandlerFuncs{
UpdateFunc: handleEvent,
},
)
queue := make(chan struct{})
go controller.Run(queue)
select {}
}
func debug(msg string) {
if *debugFlag {
fmt.Println(msg)
}
}
func handleEvent(_, obj interface{}) {
pod := obj.(*api.Pod)
statuses := pod.Status.ContainerStatuses
for _, status := range statuses {
if status.LastTerminationState != (api.ContainerState{}) {
exitCode := status.LastTerminationState.Terminated.ExitCode
codeStr := fmt.Sprintf("%d", exitCode)
containerMessage := ""
containerReason := ""
if status.LastTerminationState.Terminated != nil && exitCode != 0 {
containerMessage = status.LastTerminationState.Terminated.Message
}
if status.LastTerminationState.Terminated.Reason == "Completed" {
// break
}
if status.LastTerminationState.Terminated.Reason != "" {
if containerMessage != "" {
containerMessage += " - "
}
containerMessage += status.LastTerminationState.Terminated.Reason
}
if containerMessage == "Error" {
containerReason = containerMessage
containerMessage = fmt.Sprintf("Pod: %s %s %s", pod.ObjectMeta.Name, "exited with code: ", codeStr)
}
if containerMessage == "OOMKilled" {
containerReason = containerMessage
containerMessage = fmt.Sprintf("Pod: %s %s", pod.ObjectMeta.Name, "OOMKilled")
}
evt := sentry.NewEvent()
evt.Message = containerMessage
evt.Release = status.Image
evt.Platform = "kubernetes"
evt.Level = sentry.LevelError
evt.Extra["name"] = pod.Name
evt.Extra["reason"] = containerReason
evt.Extra["nodeName"] = pod.Spec.NodeName
evt.Extra["exitCode"] = codeStr
evt.Extra["container"] = pod.Spec.Containers[0].Name
evt.Extra["namespace"] = pod.ObjectMeta.Namespace
evt.Extra["restartCount"] = status.RestartCount
sentry.CaptureEvent(evt)
}
}
}