mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
rebase: update K8s packages to v0.32.1
Update K8s packages in go.mod to v0.32.1 Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
339
vendor/github.com/google/cadvisor/events/handler.go
generated
vendored
Normal file
339
vendor/github.com/google/cadvisor/events/handler.go
generated
vendored
Normal file
@ -0,0 +1,339 @@
|
||||
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed 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 events
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/utils"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
type byTimestamp []*info.Event
|
||||
|
||||
// functions necessary to implement the sort interface on the Events struct
|
||||
func (e byTimestamp) Len() int {
|
||||
return len(e)
|
||||
}
|
||||
|
||||
func (e byTimestamp) Swap(i, j int) {
|
||||
e[i], e[j] = e[j], e[i]
|
||||
}
|
||||
|
||||
func (e byTimestamp) Less(i, j int) bool {
|
||||
return e[i].Timestamp.Before(e[j].Timestamp)
|
||||
}
|
||||
|
||||
type EventChannel struct {
|
||||
// Watch ID. Can be used by the caller to request cancellation of watch events.
|
||||
watchID int
|
||||
// Channel on which the caller can receive watch events.
|
||||
channel chan *info.Event
|
||||
}
|
||||
|
||||
// Request holds a set of parameters by which Event objects may be screened.
|
||||
// The caller may want events that occurred within a specific timeframe
|
||||
// or of a certain type, which may be specified in the *Request object
|
||||
// they pass to an EventManager function
|
||||
type Request struct {
|
||||
// events falling before StartTime do not satisfy the request. StartTime
|
||||
// must be left blank in calls to WatchEvents
|
||||
StartTime time.Time
|
||||
// events falling after EndTime do not satisfy the request. EndTime
|
||||
// must be left blank in calls to WatchEvents
|
||||
EndTime time.Time
|
||||
// EventType is a map that specifies the type(s) of events wanted
|
||||
EventType map[info.EventType]bool
|
||||
// allows the caller to put a limit on how many
|
||||
// events to receive. If there are more events than MaxEventsReturned
|
||||
// then the most chronologically recent events in the time period
|
||||
// specified are returned. Must be >= 1
|
||||
MaxEventsReturned int
|
||||
// the absolute container name for which the event occurred
|
||||
ContainerName string
|
||||
// if IncludeSubcontainers is false, only events occurring in the specific
|
||||
// container, and not the subcontainers, will be returned
|
||||
IncludeSubcontainers bool
|
||||
}
|
||||
|
||||
// EventManager is implemented by Events. It provides two ways to monitor
|
||||
// events and one way to add events
|
||||
type EventManager interface {
|
||||
// WatchEvents() allows a caller to register for receiving events based on the specified request.
|
||||
// On successful registration, an EventChannel object is returned.
|
||||
WatchEvents(request *Request) (*EventChannel, error)
|
||||
// GetEvents() returns all detected events based on the filters specified in request.
|
||||
GetEvents(request *Request) ([]*info.Event, error)
|
||||
// AddEvent allows the caller to add an event to an EventManager
|
||||
// object
|
||||
AddEvent(event *info.Event) error
|
||||
// Cancels a previously requested watch event.
|
||||
StopWatch(watchID int)
|
||||
}
|
||||
|
||||
// events provides an implementation for the EventManager interface.
|
||||
type events struct {
|
||||
// eventStore holds the events by event type.
|
||||
eventStore map[info.EventType]*utils.TimedStore
|
||||
// map of registered watchers keyed by watch id.
|
||||
watchers map[int]*watch
|
||||
// lock guarding the eventStore.
|
||||
eventsLock sync.RWMutex
|
||||
// lock guarding watchers.
|
||||
watcherLock sync.RWMutex
|
||||
// last allocated watch id.
|
||||
lastID int
|
||||
// Event storage policy.
|
||||
storagePolicy StoragePolicy
|
||||
}
|
||||
|
||||
// initialized by a call to WatchEvents(), a watch struct will then be added
|
||||
// to the events slice of *watch objects. When AddEvent() finds an event that
|
||||
// satisfies the request parameter of a watch object in events.watchers,
|
||||
// it will send that event out over the watch object's channel. The caller that
|
||||
// called WatchEvents will receive the event over the channel provided to
|
||||
// WatchEvents
|
||||
type watch struct {
|
||||
// request parameters passed in by the caller of WatchEvents()
|
||||
request *Request
|
||||
// a channel used to send event back to the caller.
|
||||
eventChannel *EventChannel
|
||||
}
|
||||
|
||||
func NewEventChannel(watchID int) *EventChannel {
|
||||
return &EventChannel{
|
||||
watchID: watchID,
|
||||
channel: make(chan *info.Event, 10),
|
||||
}
|
||||
}
|
||||
|
||||
// Policy specifying how many events to store.
|
||||
// MaxAge is the max duration for which to keep events.
|
||||
// MaxNumEvents is the max number of events to keep (-1 for no limit).
|
||||
type StoragePolicy struct {
|
||||
// Defaults limites, used if a per-event limit is not set.
|
||||
DefaultMaxAge time.Duration
|
||||
DefaultMaxNumEvents int
|
||||
|
||||
// Per-event type limits.
|
||||
PerTypeMaxAge map[info.EventType]time.Duration
|
||||
PerTypeMaxNumEvents map[info.EventType]int
|
||||
}
|
||||
|
||||
func DefaultStoragePolicy() StoragePolicy {
|
||||
return StoragePolicy{
|
||||
DefaultMaxAge: 24 * time.Hour,
|
||||
DefaultMaxNumEvents: 100000,
|
||||
PerTypeMaxAge: make(map[info.EventType]time.Duration),
|
||||
PerTypeMaxNumEvents: make(map[info.EventType]int),
|
||||
}
|
||||
}
|
||||
|
||||
// returns a pointer to an initialized Events object.
|
||||
func NewEventManager(storagePolicy StoragePolicy) EventManager {
|
||||
return &events{
|
||||
eventStore: make(map[info.EventType]*utils.TimedStore),
|
||||
watchers: make(map[int]*watch),
|
||||
storagePolicy: storagePolicy,
|
||||
}
|
||||
}
|
||||
|
||||
// returns a pointer to an initialized Request object
|
||||
func NewRequest() *Request {
|
||||
return &Request{
|
||||
EventType: map[info.EventType]bool{},
|
||||
IncludeSubcontainers: false,
|
||||
MaxEventsReturned: 10,
|
||||
}
|
||||
}
|
||||
|
||||
// returns a pointer to an initialized watch object
|
||||
func newWatch(request *Request, eventChannel *EventChannel) *watch {
|
||||
return &watch{
|
||||
request: request,
|
||||
eventChannel: eventChannel,
|
||||
}
|
||||
}
|
||||
|
||||
func (ch *EventChannel) GetChannel() chan *info.Event {
|
||||
return ch.channel
|
||||
}
|
||||
|
||||
func (ch *EventChannel) GetWatchId() int {
|
||||
return ch.watchID
|
||||
}
|
||||
|
||||
// sorts and returns up to the last MaxEventsReturned chronological elements
|
||||
func getMaxEventsReturned(request *Request, eSlice []*info.Event) []*info.Event {
|
||||
sort.Sort(byTimestamp(eSlice))
|
||||
n := request.MaxEventsReturned
|
||||
if n >= len(eSlice) || n <= 0 {
|
||||
return eSlice
|
||||
}
|
||||
return eSlice[len(eSlice)-n:]
|
||||
}
|
||||
|
||||
// If the request wants all subcontainers, this returns if the request's
|
||||
// container path is a prefix of the event container path. Otherwise,
|
||||
// it checks that the container paths of the event and request are
|
||||
// equivalent
|
||||
func isSubcontainer(request *Request, event *info.Event) bool {
|
||||
if request.IncludeSubcontainers {
|
||||
return request.ContainerName == "/" || strings.HasPrefix(event.ContainerName+"/", request.ContainerName+"/")
|
||||
}
|
||||
return event.ContainerName == request.ContainerName
|
||||
}
|
||||
|
||||
// determines if an event occurs within the time set in the request object and is the right type
|
||||
func checkIfEventSatisfiesRequest(request *Request, event *info.Event) bool {
|
||||
startTime := request.StartTime
|
||||
endTime := request.EndTime
|
||||
eventTime := event.Timestamp
|
||||
if !startTime.IsZero() {
|
||||
if startTime.After(eventTime) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if !endTime.IsZero() {
|
||||
if endTime.Before(eventTime) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if !request.EventType[event.EventType] {
|
||||
return false
|
||||
}
|
||||
if request.ContainerName != "" {
|
||||
return isSubcontainer(request, event)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// method of Events object that screens Event objects found in the eventStore
|
||||
// attribute and if they fit the parameters passed by the Request object,
|
||||
// adds it to a slice of *Event objects that is returned. If both MaxEventsReturned
|
||||
// and StartTime/EndTime are specified in the request object, then only
|
||||
// up to the most recent MaxEventsReturned events in that time range are returned.
|
||||
func (e *events) GetEvents(request *Request) ([]*info.Event, error) {
|
||||
returnEventList := []*info.Event{}
|
||||
e.eventsLock.RLock()
|
||||
defer e.eventsLock.RUnlock()
|
||||
for eventType, fetch := range request.EventType {
|
||||
if !fetch {
|
||||
continue
|
||||
}
|
||||
evs, ok := e.eventStore[eventType]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
res := evs.InTimeRange(request.StartTime, request.EndTime, request.MaxEventsReturned)
|
||||
for _, in := range res {
|
||||
e := in.(*info.Event)
|
||||
if checkIfEventSatisfiesRequest(request, e) {
|
||||
returnEventList = append(returnEventList, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
returnEventList = getMaxEventsReturned(request, returnEventList)
|
||||
return returnEventList, nil
|
||||
}
|
||||
|
||||
// method of Events object that maintains an *Event channel passed by the user.
|
||||
// When an event is added by AddEvents that satisfies the parameters in the passed
|
||||
// Request object it is fed to the channel. The StartTime and EndTime of the watch
|
||||
// request should be uninitialized because the purpose is to watch indefinitely
|
||||
// for events that will happen in the future
|
||||
func (e *events) WatchEvents(request *Request) (*EventChannel, error) {
|
||||
if !request.StartTime.IsZero() || !request.EndTime.IsZero() {
|
||||
return nil, errors.New(
|
||||
"for a call to watch, request.StartTime and request.EndTime must be uninitialized")
|
||||
}
|
||||
e.watcherLock.Lock()
|
||||
defer e.watcherLock.Unlock()
|
||||
newID := e.lastID + 1
|
||||
returnEventChannel := NewEventChannel(newID)
|
||||
newWatcher := newWatch(request, returnEventChannel)
|
||||
e.watchers[newID] = newWatcher
|
||||
e.lastID = newID
|
||||
return returnEventChannel, nil
|
||||
}
|
||||
|
||||
// helper function to update the event manager's eventStore
|
||||
func (e *events) updateEventStore(event *info.Event) {
|
||||
e.eventsLock.Lock()
|
||||
defer e.eventsLock.Unlock()
|
||||
if _, ok := e.eventStore[event.EventType]; !ok {
|
||||
maxNumEvents := e.storagePolicy.DefaultMaxNumEvents
|
||||
if numEvents, ok := e.storagePolicy.PerTypeMaxNumEvents[event.EventType]; ok {
|
||||
maxNumEvents = numEvents
|
||||
}
|
||||
if maxNumEvents == 0 {
|
||||
// Event storage is disabled for event.EventType
|
||||
return
|
||||
}
|
||||
|
||||
maxAge := e.storagePolicy.DefaultMaxAge
|
||||
if age, ok := e.storagePolicy.PerTypeMaxAge[event.EventType]; ok {
|
||||
maxAge = age
|
||||
}
|
||||
|
||||
e.eventStore[event.EventType] = utils.NewTimedStore(maxAge, maxNumEvents)
|
||||
}
|
||||
e.eventStore[event.EventType].Add(event.Timestamp, event)
|
||||
}
|
||||
|
||||
func (e *events) findValidWatchers(event *info.Event) []*watch {
|
||||
watchesToSend := make([]*watch, 0)
|
||||
for _, watcher := range e.watchers {
|
||||
watchRequest := watcher.request
|
||||
if checkIfEventSatisfiesRequest(watchRequest, event) {
|
||||
watchesToSend = append(watchesToSend, watcher)
|
||||
}
|
||||
}
|
||||
return watchesToSend
|
||||
}
|
||||
|
||||
// method of Events object that adds the argument Event object to the
|
||||
// eventStore. It also feeds the event to a set of watch channels
|
||||
// held by the manager if it satisfies the request keys of the channels
|
||||
func (e *events) AddEvent(event *info.Event) error {
|
||||
e.updateEventStore(event)
|
||||
e.watcherLock.RLock()
|
||||
defer e.watcherLock.RUnlock()
|
||||
watchesToSend := e.findValidWatchers(event)
|
||||
for _, watchObject := range watchesToSend {
|
||||
watchObject.eventChannel.GetChannel() <- event
|
||||
}
|
||||
klog.V(4).Infof("Added event %v", event)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Removes a watch instance from the EventManager's watchers map
|
||||
func (e *events) StopWatch(watchID int) {
|
||||
e.watcherLock.Lock()
|
||||
defer e.watcherLock.Unlock()
|
||||
_, ok := e.watchers[watchID]
|
||||
if !ok {
|
||||
klog.Errorf("Could not find watcher instance %v", watchID)
|
||||
}
|
||||
close(e.watchers[watchID].eventChannel.GetChannel())
|
||||
delete(e.watchers, watchID)
|
||||
}
|
Reference in New Issue
Block a user