-
Notifications
You must be signed in to change notification settings - Fork 217
/
tracked_resources.go
104 lines (90 loc) · 3.21 KB
/
tracked_resources.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
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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 resources
import (
"fmt"
"strings"
"sync"
"time"
)
// TrackedResource is a utility struct to keep track of application resource usage.
type TrackedResource struct {
// TrackedResourceMap is a two-level map for aggregated resource usage.
// The top-level key is the instance type, and the value is a map:
// resource type (CPU, memory, etc.) -> aggregated used time (in seconds) of the resource type.
TrackedResourceMap map[string]map[string]int64
sync.RWMutex
}
// NewTrackedResource creates a new instance of TrackedResource.
func NewTrackedResource() *TrackedResource {
return &TrackedResource{TrackedResourceMap: make(map[string]map[string]int64)}
}
// NewTrackedResourceFromMap creates NewTrackedResource from the given map.
// Using for Testing purpose only.
func NewTrackedResourceFromMap(m map[string]map[string]int64) *TrackedResource {
if m == nil {
return NewTrackedResource()
}
return &TrackedResource{TrackedResourceMap: m}
}
func (tr *TrackedResource) String() string {
tr.RLock()
defer tr.RUnlock()
var resourceUsage []string
for instanceType, resourceTypeMap := range tr.TrackedResourceMap {
for resourceType, usageTime := range resourceTypeMap {
resourceUsage = append(resourceUsage, fmt.Sprintf("%s:%s=%d", instanceType, resourceType, usageTime))
}
}
return fmt.Sprintf("TrackedResource{%s}", strings.Join(resourceUsage, ","))
}
// Clone creates a deep copy of TrackedResource.
func (tr *TrackedResource) Clone() *TrackedResource {
if tr == nil {
return nil
}
ret := NewTrackedResource()
tr.RLock()
defer tr.RUnlock()
for k, v := range tr.TrackedResourceMap {
dest := make(map[string]int64)
for key, element := range v {
dest[key] = element
}
ret.TrackedResourceMap[k] = dest
}
return ret
}
// AggregateTrackedResource aggregates resource usage to TrackedResourceMap[instType].
// The time the given resource used is the delta between the resource createTime and currentTime.
func (tr *TrackedResource) AggregateTrackedResource(instType string,
resource *Resource, bindTime time.Time) {
if resource == nil {
return
}
tr.Lock()
defer tr.Unlock()
releaseTime := time.Now()
timeDiff := int64(releaseTime.Sub(bindTime).Seconds())
aggregatedResourceTime, ok := tr.TrackedResourceMap[instType]
if !ok {
aggregatedResourceTime = map[string]int64{}
}
for key, element := range resource.Resources {
aggregatedResourceTime[key] += int64(element) * timeDiff
}
tr.TrackedResourceMap[instType] = aggregatedResourceTime
}