// Copyright 2017 Xiaomi, Inc. // // 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 judge import ( "container/list" "sync" "github.com/didi/nightingale/v5/vos" ) type SafeLinkedList struct { sync.RWMutex L *list.List } func (ll *SafeLinkedList) Front() *list.Element { ll.RLock() defer ll.RUnlock() return ll.L.Front() } func (ll *SafeLinkedList) Len() int { ll.RLock() defer ll.RUnlock() return ll.L.Len() } func (ll *SafeLinkedList) PushFrontAndMaintain(v *vos.MetricPoint, maintainDuration int64) { ll.Lock() defer ll.Unlock() sz := ll.L.Len() lastPointTs := ll.L.Front().Value.(*vos.MetricPoint).Time earliestTs := v.Time - maintainDuration if sz > 0 { // 新push上来的数据有可能重复了,或者timestamp不对,这种数据要丢掉 if v.Time <= lastPointTs { return } } ll.L.PushFront(v) sz++ for i := 0; i < sz; i++ { if ll.L.Back().Value.(*vos.MetricPoint).Time >= earliestTs { break } //最前面的点已经不在告警策略时间周期内,丢弃掉 ll.L.Remove(ll.L.Back()) } } func (ll *SafeLinkedList) HistoryPoints(smallestTime int64) []*vos.HPoint { size := ll.Len() if size == 0 { return []*vos.HPoint{} } firstElement := ll.Front() firstItem := firstElement.Value.(*vos.MetricPoint) vs := make([]*vos.HPoint, 0) if firstItem.Time < smallestTime { return vs } v := &vos.HPoint{ Timestamp: firstItem.Time, Value: vos.JsonFloat(firstItem.Value), } vs = append(vs, v) currentElement := firstElement for i := 1; i < size; i++ { nextElement := currentElement.Next() if nextElement == nil { return vs } item := nextElement.Value.(*vos.MetricPoint) if item.Time < smallestTime { return vs } v := &vos.HPoint{ Timestamp: item.Time, Value: vos.JsonFloat(item.Value), } vs = append(vs, v) currentElement = nextElement } return vs } // func (ll *SafeLinkedList) QueryDataByTS(start, end int64) []*vos.HPoint { // size := ll.Len() // if size == 0 { // return []*vos.HPoint{} // } // firstElement := ll.Front() // firstItem := firstElement.Value.(*vos.MetricPoint) // var vs []*vos.HPoint // if firstItem.Time < start { // //最新的点也比起始时间旧,直接返回 // return vs // } // v := &vos.HPoint{ // Timestamp: firstItem.Time, // Value: vos.JsonFloat(firstItem.Value), // } // vs = append(vs, v) // currentElement := firstElement // for { // nextElement := currentElement.Next() // if nextElement == nil { // return vs // } // if nextElement.Value.(*vos.MetricPoint).Time < start { // return vs // } // if nextElement.Value.(*vos.MetricPoint).Time > end { // currentElement = nextElement // continue // } // v := &vos.HPoint{ // Timestamp: nextElement.Value.(*vos.MetricPoint).Time, // Value: vos.JsonFloat(nextElement.Value.(*vos.MetricPoint).Value), // } // vs = append(vs, v) // currentElement = nextElement // } // return vs // }