@@ -7,23 +7,23 @@ import (
7
7
"github.com/keptn-contrib/prometheus-service/utils/prometheus"
8
8
"gopkg.in/yaml.v2"
9
9
"log"
10
- "math"
11
10
"net/url"
12
11
"strings"
13
12
14
13
cloudevents "github.com/cloudevents/sdk-go/v2"
15
14
"github.com/keptn-contrib/prometheus-service/utils"
15
+
16
16
keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0"
17
17
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18
18
"k8s.io/client-go/kubernetes"
19
19
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
20
- "k8s.io/client-go/rest"
21
20
)
22
21
23
22
// GetSliEventHandler is responsible for processing configure monitoring events
24
23
type GetSliEventHandler struct {
25
24
event cloudevents.Event
26
25
keptnHandler * keptnv2.Keptn
26
+ kubeClient * kubernetes.Clientset
27
27
}
28
28
29
29
type prometheusCredentials struct {
@@ -47,33 +47,82 @@ func (eh GetSliEventHandler) HandleEvent() error {
47
47
48
48
// send started event
49
49
_ , err = eh .keptnHandler .SendTaskStartedEvent (eventData , utils .ServiceName )
50
-
51
50
if err != nil {
52
- errMsg := fmt .Sprintf ( "Failed to send task started CloudEvent (%s), aborting... " , err . Error () )
53
- log .Println (errMsg )
51
+ errMsg := fmt .Errorf ( "failed to send task started CloudEvent: %w " , err )
52
+ log .Println (errMsg . Error () )
54
53
return err
55
54
}
56
55
57
- // create SLI Results
58
- var sliResults []* keptnv2.SLIResult
56
+ // helper function to log an error and send an appropriate finished event
57
+ sendFinishedErrorEvent := func (err error ) error {
58
+ log .Printf ("sending errored finished event: %s" , err .Error ())
59
59
60
- // 2: try to fetch metrics into sliResults
61
- if sliResults , err = retrieveMetrics (eventData , eh .keptnHandler ); err != nil {
62
- // failed to fetch metrics, send a finished event with the error
63
- _ , err = eh .keptnHandler .SendTaskFinishedEvent (& keptnv2.EventData {
60
+ _ , sendError := eh .keptnHandler .SendTaskFinishedEvent (& keptnv2.EventData {
64
61
Status : keptnv2 .StatusErrored ,
65
62
Result : keptnv2 .ResultFailed ,
66
63
Message : err .Error (),
67
64
}, utils .ServiceName )
68
65
69
- return err
66
+ // TODO: Maybe log error to console
67
+
68
+ return sendError
69
+ }
70
+
71
+ // get prometheus API URL for the provided Project from Kubernetes Config Map
72
+ prometheusAPIURL , err := getPrometheusAPIURL (eventData .Project , eh .kubeClient .CoreV1 ())
73
+ if err != nil {
74
+ return sendFinishedErrorEvent (fmt .Errorf ("unable to get prometheus api URL: %w" , err ))
75
+ }
76
+
77
+ // create a new Prometheus Handler
78
+ prometheusHandler := prometheus .NewPrometheusHandler (
79
+ prometheusAPIURL ,
80
+ & eventData .EventData ,
81
+ eventData .Deployment , // "canary", "primary" or "" (or "direct" or "user_managed")
82
+ eventData .Labels ,
83
+ eventData .GetSLI .CustomFilters ,
84
+ )
85
+
86
+ // get SLI queries (from SLI.yaml)
87
+ projectCustomQueries , err := getCustomQueries (eh .keptnHandler , eventData .Project , eventData .Stage , eventData .Service )
88
+ if err != nil {
89
+ return sendFinishedErrorEvent (
90
+ fmt .Errorf ("unable to retrieve custom queries for project %s: %w" , eventData .Project , err ),
91
+ )
92
+ }
93
+
94
+ // only apply queries if they contain anything
95
+ if projectCustomQueries != nil {
96
+ prometheusHandler .CustomQueries = projectCustomQueries
97
+ }
98
+
99
+ // retrieve metrics from prometheus
100
+ sliResults := retrieveMetrics (prometheusHandler , eventData )
101
+
102
+ // If we hand any problem retrieving an SLI value, we set the result of the overall .finished event
103
+ // to Warning, if all fail ResultFailed is set for the event
104
+ finalSLIEventResult := keptnv2 .ResultPass
105
+
106
+ if len (sliResults ) > 0 {
107
+ sliResultsFailed := 0
108
+ for _ , sliResult := range sliResults {
109
+ if ! sliResult .Success {
110
+ sliResultsFailed ++
111
+ }
112
+ }
113
+
114
+ if sliResultsFailed > 0 && sliResultsFailed < len (sliResults ) {
115
+ finalSLIEventResult = keptnv2 .ResultWarning
116
+ } else if sliResultsFailed == len (sliResults ) {
117
+ finalSLIEventResult = keptnv2 .ResultFailed
118
+ }
70
119
}
71
120
72
121
// construct finished event data
73
122
getSliFinishedEventData := & keptnv2.GetSLIFinishedEventData {
74
123
EventData : keptnv2.EventData {
75
124
Status : keptnv2 .StatusSucceeded ,
76
- Result : keptnv2 . ResultPass ,
125
+ Result : finalSLIEventResult ,
77
126
},
78
127
GetSLI : keptnv2.GetSLIFinished {
79
128
IndicatorValues : sliResults ,
@@ -82,9 +131,12 @@ func (eh GetSliEventHandler) HandleEvent() error {
82
131
},
83
132
}
84
133
85
- // send get-sli.finished event with SLI DAta
86
- _ , err = eh .keptnHandler .SendTaskFinishedEvent (getSliFinishedEventData , utils .ServiceName )
134
+ if getSliFinishedEventData .EventData .Result == keptnv2 .ResultFailed {
135
+ getSliFinishedEventData .EventData .Message = "unable to retrieve metrics"
136
+ }
87
137
138
+ // send get-sli.finished event with SLI DATA
139
+ _ , err = eh .keptnHandler .SendTaskFinishedEvent (getSliFinishedEventData , utils .ServiceName )
88
140
if err != nil {
89
141
errMsg := fmt .Sprintf ("Failed to send task finished CloudEvent (%s), aborting..." , err .Error ())
90
142
log .Println (errMsg )
@@ -94,48 +146,9 @@ func (eh GetSliEventHandler) HandleEvent() error {
94
146
return nil
95
147
}
96
148
97
- func retrieveMetrics (eventData * keptnv2. GetSLITriggeredEventData , keptnHandler * keptnv2.Keptn ) ( []* keptnv2.SLIResult , error ) {
149
+ func retrieveMetrics (prometheusHandler * prometheus. Handler , eventData * keptnv2.GetSLITriggeredEventData ) []* keptnv2.SLIResult {
98
150
log .Printf ("Retrieving Prometheus metrics" )
99
151
100
- clusterConfig , err := rest .InClusterConfig ()
101
- if err != nil {
102
- log .Println ("could not create Kubernetes cluster config" )
103
- return nil , errors .New ("could not create Kubernetes client" )
104
- }
105
-
106
- kubeClient , err := kubernetes .NewForConfig (clusterConfig )
107
- if err != nil {
108
- log .Println ("could not create Kubernetes client" )
109
- return nil , errors .New ("could not create Kubernetes client" )
110
- }
111
-
112
- // get prometheus API URL for the provided Project from Kubernetes Config Map
113
- prometheusAPIURL , err := getPrometheusAPIURL (eventData .Project , kubeClient .CoreV1 ())
114
- if err != nil {
115
- return nil , err
116
- }
117
-
118
- // Create a new Prometheus Handler
119
- prometheusHandler := prometheus .NewPrometheusHandler (
120
- prometheusAPIURL ,
121
- & eventData .EventData ,
122
- eventData .Deployment , // "canary", "primary" or "" (or "direct" or "user_managed")
123
- eventData .Labels ,
124
- eventData .GetSLI .CustomFilters ,
125
- )
126
-
127
- // get SLI queries (from SLI.yaml)
128
- projectCustomQueries , err := getCustomQueries (keptnHandler , eventData .Project , eventData .Stage , eventData .Service )
129
- if err != nil {
130
- log .Println ("retrieveMetrics: Failed to get custom queries for project " + eventData .Project )
131
- log .Println (err .Error ())
132
- return nil , err
133
- }
134
-
135
- if projectCustomQueries != nil {
136
- prometheusHandler .CustomQueries = projectCustomQueries
137
- }
138
-
139
152
var sliResults []* keptnv2.SLIResult
140
153
141
154
for _ , indicator := range eventData .GetSLI .Indicators {
@@ -148,13 +161,6 @@ func retrieveMetrics(eventData *keptnv2.GetSLITriggeredEventData, keptnHandler *
148
161
Success : false ,
149
162
Message : err .Error (),
150
163
})
151
- } else if math .IsNaN (sliValue ) {
152
- sliResults = append (sliResults , & keptnv2.SLIResult {
153
- Metric : indicator ,
154
- Value : 0 ,
155
- Success : false ,
156
- Message : "SLI value is NaN" ,
157
- })
158
164
} else {
159
165
sliResults = append (sliResults , & keptnv2.SLIResult {
160
166
Metric : indicator ,
@@ -163,7 +169,8 @@ func retrieveMetrics(eventData *keptnv2.GetSLITriggeredEventData, keptnHandler *
163
169
})
164
170
}
165
171
}
166
- return sliResults , nil
172
+
173
+ return sliResults
167
174
}
168
175
169
176
func getCustomQueries (keptnHandler * keptnv2.Keptn , project string , stage string , service string ) (map [string ]string , error ) {
0 commit comments