/
handler.go
116 lines (91 loc) · 3.39 KB
/
handler.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
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0
package debug
import (
"context"
"sync"
"time"
"github.com/go-logr/logr"
"k8s.io/client-go/util/workqueue"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
)
type loggingQueue struct {
mu sync.RWMutex
done bool
log logr.Logger
workqueue.RateLimitingInterface
}
func newLoggingQueue(log logr.Logger, queue workqueue.RateLimitingInterface) *loggingQueue {
return &loggingQueue{log: log, RateLimitingInterface: queue}
}
func (q *loggingQueue) Add(item interface{}) {
q.mu.RLock()
defer q.mu.RUnlock()
q.log.Info("Add", "Item", item, "Done", q.done)
q.RateLimitingInterface.Add(item)
}
func (q *loggingQueue) AddRateLimited(item interface{}) {
q.mu.RLock()
defer q.mu.RUnlock()
q.log.Info("AddRateLimited", "Item", item, "Done", q.done)
q.RateLimitingInterface.AddRateLimited(item)
}
func (q *loggingQueue) AddAfter(item interface{}, duration time.Duration) {
q.mu.RLock()
defer q.mu.RUnlock()
q.log.Info("AddAfter", "Item", item, "Duration", duration, "Done", q.done)
q.RateLimitingInterface.AddAfter(item, duration)
}
func (q *loggingQueue) Finish() {
q.mu.Lock()
defer q.mu.Unlock()
q.done = true
}
type debugHandler struct {
log logr.Logger
handler handler.EventHandler
objectValue func(client.Object) any
}
func (d *debugHandler) Create(ctx context.Context, evt event.CreateEvent, queue workqueue.RateLimitingInterface) {
log := d.log.WithValues("Event", "Create", "Object", d.objectValue(evt.Object))
log.Info("Handling Event")
lQueue := newLoggingQueue(log.WithName("Queue"), queue)
defer lQueue.Finish()
d.handler.Create(ctx, evt, lQueue)
}
func (d *debugHandler) Update(ctx context.Context, evt event.UpdateEvent, queue workqueue.RateLimitingInterface) {
log := d.log.WithValues("Event", "Update", "ObjectOld", d.objectValue(evt.ObjectOld), "ObjectNew", d.objectValue(evt.ObjectNew))
log.Info("Handling Event")
lQueue := newLoggingQueue(log.WithName("Queue"), queue)
defer lQueue.Finish()
d.handler.Update(ctx, evt, lQueue)
}
func (d *debugHandler) Delete(ctx context.Context, evt event.DeleteEvent, queue workqueue.RateLimitingInterface) {
log := d.log.WithValues("Event", "Delete", "Object", d.objectValue(evt.Object))
log.Info("Handling Event")
lQueue := newLoggingQueue(log.WithName("Queue"), queue)
defer lQueue.Finish()
d.handler.Delete(ctx, evt, lQueue)
}
func (d *debugHandler) Generic(ctx context.Context, evt event.GenericEvent, queue workqueue.RateLimitingInterface) {
log := d.log.WithValues("Event", "Generic", "Object", d.objectValue(evt.Object))
log.Info("Handling Event")
lQueue := newLoggingQueue(log.WithName("Queue"), queue)
defer lQueue.Finish()
d.handler.Generic(ctx, evt, lQueue)
}
// Handler allows debugging a handler.EventHandler by wrapping it and logging each action it does.
//
// Caution: This has a heavy toll on runtime performance and should *not* be used in production code.
// Use only for debugging handlers and remove once done.
func Handler(name string, handler handler.EventHandler, opts ...HandlerOption) handler.EventHandler {
o := (&HandlerOptions{}).ApplyOptions(opts)
setHandlerOptionsDefaults(o)
return &debugHandler{
log: o.Log.WithName(name),
handler: handler,
objectValue: o.ObjectValue,
}
}