mirror of
https://github.com/kubernetes/client-go.git
synced 2026-06-30 05:58:43 +00:00
events: add AnnotatedEventRecorder interface
Add a separate AnnotatedEventRecorder interface with an AnnotatedEventf method that allows attaching annotations to events at creation time. Implement it in recorderImpl, FakeRecorder, and EventRecorderAdapter. Add a Verbose option to FakeRecorder that optionally includes action, object kind/apiVersion, and annotations in event output. The default format is unchanged. Signed-off-by: Adrian Fernandez De La Torre <adri1197@gmail.com> Kubernetes-commit: 31fe350b2b2065b49752adb4f68f1ea1c282058e
This commit is contained in:
committed by
Kubernetes Publisher
parent
bdc99a38a9
commit
e86b6659d9
@@ -41,9 +41,14 @@ type recorderImpl struct {
|
||||
}
|
||||
|
||||
var _ EventRecorder = &recorderImpl{}
|
||||
var _ AnnotatedEventRecorder = &recorderImpl{}
|
||||
|
||||
func (recorder *recorderImpl) Eventf(regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{}) {
|
||||
recorder.eventf(klog.Background(), regarding, related, eventtype, reason, action, note, args...)
|
||||
recorder.eventf(klog.Background(), regarding, related, nil, eventtype, reason, action, note, args...)
|
||||
}
|
||||
|
||||
func (recorder *recorderImpl) AnnotatedEventf(regarding runtime.Object, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{}) {
|
||||
recorder.eventf(klog.Background(), regarding, related, annotations, eventtype, reason, action, note, args...)
|
||||
}
|
||||
|
||||
type recorderImplLogger struct {
|
||||
@@ -54,14 +59,18 @@ type recorderImplLogger struct {
|
||||
var _ EventRecorderLogger = &recorderImplLogger{}
|
||||
|
||||
func (recorder *recorderImplLogger) Eventf(regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{}) {
|
||||
recorder.eventf(recorder.logger, regarding, related, eventtype, reason, action, note, args...)
|
||||
recorder.eventf(recorder.logger, regarding, related, nil, eventtype, reason, action, note, args...)
|
||||
}
|
||||
|
||||
func (recorder *recorderImplLogger) AnnotatedEventf(regarding runtime.Object, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{}) {
|
||||
recorder.eventf(recorder.logger, regarding, related, annotations, eventtype, reason, action, note, args...)
|
||||
}
|
||||
|
||||
func (recorder *recorderImplLogger) WithLogger(logger klog.Logger) EventRecorderLogger {
|
||||
return &recorderImplLogger{recorderImpl: recorder.recorderImpl, logger: logger}
|
||||
}
|
||||
|
||||
func (recorder *recorderImpl) eventf(logger klog.Logger, regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{}) {
|
||||
func (recorder *recorderImpl) eventf(logger klog.Logger, regarding runtime.Object, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{}) {
|
||||
timestamp := metav1.MicroTime{Time: time.Now()}
|
||||
message := fmt.Sprintf(note, args...)
|
||||
refRegarding, err := reference.GetReference(recorder.scheme, regarding)
|
||||
@@ -81,14 +90,14 @@ func (recorder *recorderImpl) eventf(logger klog.Logger, regarding runtime.Objec
|
||||
logger.Error(nil, "Unsupported event type", "eventType", eventtype)
|
||||
return
|
||||
}
|
||||
event := recorder.makeEvent(refRegarding, refRelated, timestamp, eventtype, reason, message, recorder.reportingController, recorder.reportingInstance, action)
|
||||
event := recorder.makeEvent(refRegarding, refRelated, timestamp, annotations, eventtype, reason, message, recorder.reportingController, recorder.reportingInstance, action)
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
recorder.Action(watch.Added, event)
|
||||
}()
|
||||
}
|
||||
|
||||
func (recorder *recorderImpl) makeEvent(refRegarding *v1.ObjectReference, refRelated *v1.ObjectReference, timestamp metav1.MicroTime, eventtype, reason, message string, reportingController string, reportingInstance string, action string) *eventsv1.Event {
|
||||
func (recorder *recorderImpl) makeEvent(refRegarding *v1.ObjectReference, refRelated *v1.ObjectReference, timestamp metav1.MicroTime, annotations map[string]string, eventtype, reason, message string, reportingController string, reportingInstance string, action string) *eventsv1.Event {
|
||||
t := metav1.Time{Time: recorder.clock.Now()}
|
||||
namespace := refRegarding.Namespace
|
||||
if namespace == "" {
|
||||
@@ -96,8 +105,9 @@ func (recorder *recorderImpl) makeEvent(refRegarding *v1.ObjectReference, refRel
|
||||
}
|
||||
return &eventsv1.Event{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: util.GenerateEventName(refRegarding.Name, t.UnixNano()),
|
||||
Namespace: namespace,
|
||||
Name: util.GenerateEventName(refRegarding.Name, t.UnixNano()),
|
||||
Namespace: namespace,
|
||||
Annotations: annotations,
|
||||
},
|
||||
EventTime: timestamp,
|
||||
Series: nil,
|
||||
|
||||
@@ -299,7 +299,7 @@ func TestFinishSeries(t *testing.T) {
|
||||
cache := map[eventKey]*eventsv1.Event{}
|
||||
eventBroadcaster := newBroadcaster(&testEvents, 0, cache).(*eventBroadcasterImpl)
|
||||
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, "k8s.io/kube-foo").(*recorderImplLogger)
|
||||
cachedEvent := recorder.makeEvent(regarding, related, metav1.MicroTime{Time: time.Now()}, v1.EventTypeNormal, "test", "some verbose message: 1", "eventTest", "eventTest-"+hostname, "started")
|
||||
cachedEvent := recorder.makeEvent(regarding, related, metav1.MicroTime{Time: time.Now()}, nil, v1.EventTypeNormal, "test", "some verbose message: 1", "eventTest", "eventTest-"+hostname, "started")
|
||||
nonFinishedEvent := cachedEvent.DeepCopy()
|
||||
nonFinishedEvent.ReportingController = "nonFinished-controller"
|
||||
cachedEvent.Series = &eventsv1.EventSeries{
|
||||
@@ -386,7 +386,7 @@ func TestRefreshExistingEventSeries(t *testing.T) {
|
||||
cache := map[eventKey]*eventsv1.Event{}
|
||||
eventBroadcaster := newBroadcaster(&testEvents, 0, cache).(*eventBroadcasterImpl)
|
||||
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, "k8s.io/kube-foo").(*recorderImplLogger)
|
||||
cachedEvent := recorder.makeEvent(regarding, related, metav1.MicroTime{Time: time.Now()}, v1.EventTypeNormal, "test", "some verbose message: 1", "eventTest", "eventTest-"+hostname, "started")
|
||||
cachedEvent := recorder.makeEvent(regarding, related, metav1.MicroTime{Time: time.Now()}, nil, v1.EventTypeNormal, "test", "some verbose message: 1", "eventTest", "eventTest-"+hostname, "started")
|
||||
cachedEvent.Series = &eventsv1.EventSeries{
|
||||
Count: 10,
|
||||
LastObservedTime: LastObservedTime,
|
||||
|
||||
@@ -27,26 +27,71 @@ import (
|
||||
// when created manually and not by NewFakeRecorder, however all events may be
|
||||
// thrown away in this case.
|
||||
type FakeRecorder struct {
|
||||
Events chan string
|
||||
Events chan string
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
var _ EventRecorderLogger = &FakeRecorder{}
|
||||
var _ AnnotatedEventRecorder = &FakeRecorder{}
|
||||
|
||||
// Eventf emits an event
|
||||
func (f *FakeRecorder) Eventf(regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{}) {
|
||||
if f.Events != nil {
|
||||
f.Events <- fmt.Sprintf(eventtype+" "+reason+" "+note, args...)
|
||||
}
|
||||
f.writeEvent(regarding, related, nil, eventtype, reason, action, note, args...)
|
||||
}
|
||||
|
||||
// AnnotatedEventf emits an event like Eventf, but with annotations attached
|
||||
func (f *FakeRecorder) AnnotatedEventf(regarding runtime.Object, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{}) {
|
||||
f.writeEvent(regarding, related, annotations, eventtype, reason, action, note, args...)
|
||||
}
|
||||
|
||||
func (f *FakeRecorder) WithLogger(logger klog.Logger) EventRecorderLogger {
|
||||
return f
|
||||
}
|
||||
|
||||
// writeEvent constructs a string from the event parameters and sends
|
||||
// it to the Events channel
|
||||
func (f *FakeRecorder) writeEvent(regarding runtime.Object, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{}) {
|
||||
if f.Events != nil {
|
||||
msg := fmt.Sprintf(eventtype+" "+reason+" "+note, args...)
|
||||
if f.Verbose {
|
||||
msg = eventtype + " " + reason + " " + action + " " + fmt.Sprintf(note, args...) +
|
||||
objectString(regarding) + objectString(related) + annotationsString(annotations)
|
||||
}
|
||||
f.Events <- msg
|
||||
}
|
||||
}
|
||||
|
||||
// annotationsString returns a formatted string of the annotations map,
|
||||
// or empty string if none
|
||||
func annotationsString(annotations map[string]string) string {
|
||||
annotationString := ""
|
||||
if len(annotations) > 0 {
|
||||
annotationString = " " + fmt.Sprint(annotations)
|
||||
}
|
||||
return annotationString
|
||||
}
|
||||
|
||||
// objectString returns a formatted string with the object's kind and
|
||||
// apiVersion
|
||||
func objectString(object runtime.Object) string {
|
||||
objectString := ""
|
||||
if object != nil {
|
||||
gvk := object.GetObjectKind().GroupVersionKind()
|
||||
if !gvk.Empty() {
|
||||
objectString = fmt.Sprintf(" {kind=%s,apiVersion=%s}",
|
||||
gvk.Kind,
|
||||
gvk.GroupVersion(),
|
||||
)
|
||||
}
|
||||
}
|
||||
return objectString
|
||||
}
|
||||
|
||||
// NewFakeRecorder creates new fake event recorder with event channel with
|
||||
// buffer of given size.
|
||||
func NewFakeRecorder(bufferSize int) *FakeRecorder {
|
||||
return &FakeRecorder{
|
||||
Events: make(chan string, bufferSize),
|
||||
Events: make(chan string, bufferSize),
|
||||
Verbose: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
|
||||
type EventRecorder = internalevents.EventRecorder
|
||||
type EventRecorderLogger = internalevents.EventRecorderLogger
|
||||
type AnnotatedEventRecorder = internalevents.AnnotatedEventRecorder
|
||||
|
||||
// EventBroadcaster knows how to receive events and send them to any EventSink, watcher, or log.
|
||||
type EventBroadcaster interface {
|
||||
|
||||
@@ -43,6 +43,15 @@ type EventRecorder interface {
|
||||
Eventf(regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{})
|
||||
}
|
||||
|
||||
// AnnotatedEventRecorder is an optional extension of EventRecorder that
|
||||
// supports attaching annotations to events at creation time.
|
||||
// Annotations are intended for low-frequency correlation metadata, not as a general purpose structured-data channel.
|
||||
// Kubernetes events are best-effort, supplemental observability data and may be dropped, deduped or aggregated at any
|
||||
// point in pipeline. Do not rely on annotations for event-driven control flow.
|
||||
type AnnotatedEventRecorder interface {
|
||||
AnnotatedEventf(regarding runtime.Object, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{})
|
||||
}
|
||||
|
||||
// EventRecorderLogger extends EventRecorder such that a logger can
|
||||
// be set for methods in EventRecorder. Normally, those methods
|
||||
// uses the global default logger to record errors and debug messages.
|
||||
|
||||
@@ -176,6 +176,12 @@ func (a *EventRecorderAdapter) Eventf(regarding, _ runtime.Object, eventtype, re
|
||||
a.recorder.Eventf(regarding, eventtype, reason, note, args...)
|
||||
}
|
||||
|
||||
// AnnotatedEventf is a wrapper around v1 AnnotatedEventf
|
||||
func (a *EventRecorderAdapter) AnnotatedEventf(regarding, _ runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...interface{}) {
|
||||
//nolint:forbidigo // Legacy usage
|
||||
a.recorder.AnnotatedEventf(regarding, annotations, eventtype, reason, note, args...)
|
||||
}
|
||||
|
||||
func (a *EventRecorderAdapter) WithLogger(logger klog.Logger) internalevents.EventRecorderLogger {
|
||||
return &EventRecorderAdapter{
|
||||
recorder: a.recorder.WithLogger(logger),
|
||||
|
||||
Reference in New Issue
Block a user