mirror of
https://github.com/Oxalide/vsphere-influxdb-go.git
synced 2023-10-10 11:36:51 +00:00
add vendoring with go dep
This commit is contained in:
431
vendor/github.com/vmware/govmomi/performance/manager.go
generated
vendored
Normal file
431
vendor/github.com/vmware/govmomi/performance/manager.go
generated
vendored
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
Copyright (c) 2017 VMware, 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 performance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
// Manager wraps mo.PerformanceManager.
|
||||
type Manager struct {
|
||||
object.Common
|
||||
|
||||
Sort bool
|
||||
|
||||
pm struct {
|
||||
sync.Mutex
|
||||
*mo.PerformanceManager
|
||||
}
|
||||
|
||||
providerSummary struct {
|
||||
sync.Mutex
|
||||
m map[string]*types.PerfProviderSummary
|
||||
}
|
||||
|
||||
infoByName struct {
|
||||
sync.Mutex
|
||||
m map[string]*types.PerfCounterInfo
|
||||
}
|
||||
|
||||
infoByKey struct {
|
||||
sync.Mutex
|
||||
m map[int32]*types.PerfCounterInfo
|
||||
}
|
||||
}
|
||||
|
||||
// NewManager creates a new Manager instance.
|
||||
func NewManager(client *vim25.Client) *Manager {
|
||||
m := Manager{
|
||||
Common: object.NewCommon(client, *client.ServiceContent.PerfManager),
|
||||
}
|
||||
|
||||
m.pm.PerformanceManager = new(mo.PerformanceManager)
|
||||
|
||||
return &m
|
||||
}
|
||||
|
||||
// IntervalList wraps []types.PerfInterval.
|
||||
type IntervalList []types.PerfInterval
|
||||
|
||||
// Enabled returns a map with Level as the key and enabled PerfInterval.Name(s) as the value.
|
||||
func (l IntervalList) Enabled() map[int32][]string {
|
||||
enabled := make(map[int32][]string)
|
||||
|
||||
for level := int32(0); level <= 4; level++ {
|
||||
var names []string
|
||||
|
||||
for _, interval := range l {
|
||||
if interval.Enabled && interval.Level >= level {
|
||||
names = append(names, interval.Name)
|
||||
}
|
||||
}
|
||||
|
||||
enabled[level] = names
|
||||
}
|
||||
|
||||
return enabled
|
||||
}
|
||||
|
||||
// HistoricalInterval gets the PerformanceManager.HistoricalInterval property and wraps as an IntervalList.
|
||||
func (m *Manager) HistoricalInterval(ctx context.Context) (IntervalList, error) {
|
||||
var pm mo.PerformanceManager
|
||||
|
||||
err := m.Properties(ctx, m.Reference(), []string{"historicalInterval"}, &pm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return IntervalList(pm.HistoricalInterval), nil
|
||||
}
|
||||
|
||||
// CounterInfo gets the PerformanceManager.PerfCounter property.
|
||||
// The property value is only collected once, subsequent calls return the cached value.
|
||||
func (m *Manager) CounterInfo(ctx context.Context) ([]types.PerfCounterInfo, error) {
|
||||
m.pm.Lock()
|
||||
defer m.pm.Unlock()
|
||||
|
||||
if len(m.pm.PerfCounter) == 0 {
|
||||
err := m.Properties(ctx, m.Reference(), []string{"perfCounter"}, m.pm.PerformanceManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return m.pm.PerfCounter, nil
|
||||
}
|
||||
|
||||
// CounterInfoByName converts the PerformanceManager.PerfCounter property to a map,
|
||||
// where key is types.PerfCounterInfo.Name().
|
||||
func (m *Manager) CounterInfoByName(ctx context.Context) (map[string]*types.PerfCounterInfo, error) {
|
||||
m.infoByName.Lock()
|
||||
defer m.infoByName.Unlock()
|
||||
|
||||
if m.infoByName.m != nil {
|
||||
return m.infoByName.m, nil
|
||||
}
|
||||
|
||||
info, err := m.CounterInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.infoByName.m = make(map[string]*types.PerfCounterInfo)
|
||||
|
||||
for i := range info {
|
||||
c := &info[i]
|
||||
|
||||
m.infoByName.m[c.Name()] = c
|
||||
}
|
||||
|
||||
return m.infoByName.m, nil
|
||||
}
|
||||
|
||||
// CounterInfoByKey converts the PerformanceManager.PerfCounter property to a map,
|
||||
// where key is types.PerfCounterInfo.Key.
|
||||
func (m *Manager) CounterInfoByKey(ctx context.Context) (map[int32]*types.PerfCounterInfo, error) {
|
||||
m.infoByKey.Lock()
|
||||
defer m.infoByKey.Unlock()
|
||||
|
||||
if m.infoByKey.m != nil {
|
||||
return m.infoByKey.m, nil
|
||||
}
|
||||
|
||||
info, err := m.CounterInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.infoByKey.m = make(map[int32]*types.PerfCounterInfo)
|
||||
|
||||
for i := range info {
|
||||
c := &info[i]
|
||||
|
||||
m.infoByKey.m[c.Key] = c
|
||||
}
|
||||
|
||||
return m.infoByKey.m, nil
|
||||
}
|
||||
|
||||
// ProviderSummary wraps the QueryPerfProviderSummary method, caching the value based on entity.Type.
|
||||
func (m *Manager) ProviderSummary(ctx context.Context, entity types.ManagedObjectReference) (*types.PerfProviderSummary, error) {
|
||||
m.providerSummary.Lock()
|
||||
defer m.providerSummary.Unlock()
|
||||
|
||||
if m.providerSummary.m == nil {
|
||||
m.providerSummary.m = make(map[string]*types.PerfProviderSummary)
|
||||
}
|
||||
|
||||
s, ok := m.providerSummary.m[entity.Type]
|
||||
if ok {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
req := types.QueryPerfProviderSummary{
|
||||
This: m.Reference(),
|
||||
Entity: entity,
|
||||
}
|
||||
|
||||
res, err := methods.QueryPerfProviderSummary(ctx, m.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s = &res.Returnval
|
||||
|
||||
m.providerSummary.m[entity.Type] = s
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type groupPerfCounterInfo struct {
|
||||
info map[int32]*types.PerfCounterInfo
|
||||
ids []types.PerfMetricId
|
||||
}
|
||||
|
||||
func (d groupPerfCounterInfo) Len() int {
|
||||
return len(d.ids)
|
||||
}
|
||||
|
||||
func (d groupPerfCounterInfo) Less(i, j int) bool {
|
||||
ci := d.ids[i].CounterId
|
||||
cj := d.ids[j].CounterId
|
||||
gi := d.info[ci].GroupInfo.GetElementDescription()
|
||||
gj := d.info[cj].GroupInfo.GetElementDescription()
|
||||
|
||||
return gi.Key < gj.Key
|
||||
}
|
||||
|
||||
func (d groupPerfCounterInfo) Swap(i, j int) {
|
||||
d.ids[i], d.ids[j] = d.ids[j], d.ids[i]
|
||||
}
|
||||
|
||||
// MetricList wraps []types.PerfMetricId
|
||||
type MetricList []types.PerfMetricId
|
||||
|
||||
// ByKey converts MetricList to map, where key is types.PerfMetricId.CounterId / types.PerfCounterInfo.Key
|
||||
func (l MetricList) ByKey() map[int32][]*types.PerfMetricId {
|
||||
ids := make(map[int32][]*types.PerfMetricId, len(l))
|
||||
|
||||
for i := range l {
|
||||
id := &l[i]
|
||||
ids[id.CounterId] = append(ids[id.CounterId], id)
|
||||
}
|
||||
|
||||
return ids
|
||||
}
|
||||
|
||||
// AvailableMetric wraps the QueryAvailablePerfMetric method.
|
||||
// The MetricList is sorted by PerfCounterInfo.GroupInfo.Key if Manager.Sort == true.
|
||||
func (m *Manager) AvailableMetric(ctx context.Context, entity types.ManagedObjectReference, interval int32) (MetricList, error) {
|
||||
req := types.QueryAvailablePerfMetric{
|
||||
This: m.Reference(),
|
||||
Entity: entity.Reference(),
|
||||
IntervalId: interval,
|
||||
}
|
||||
|
||||
res, err := methods.QueryAvailablePerfMetric(ctx, m.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m.Sort {
|
||||
info, err := m.CounterInfoByKey(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Sort(groupPerfCounterInfo{info, res.Returnval})
|
||||
}
|
||||
|
||||
return MetricList(res.Returnval), nil
|
||||
}
|
||||
|
||||
// Query wraps the QueryPerf method.
|
||||
func (m *Manager) Query(ctx context.Context, spec []types.PerfQuerySpec) ([]types.BasePerfEntityMetricBase, error) {
|
||||
req := types.QueryPerf{
|
||||
This: m.Reference(),
|
||||
QuerySpec: spec,
|
||||
}
|
||||
|
||||
res, err := methods.QueryPerf(ctx, m.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
||||
// SampleByName uses the spec param as a template, constructing a []types.PerfQuerySpec for the given metrics and entities
|
||||
// and invoking the Query method.
|
||||
// The spec template can specify instances using the MetricId.Instance field, by default all instances are collected.
|
||||
// The spec template MaxSample defaults to 1.
|
||||
// If the spec template IntervalId is a historical interval and StartTime is not specified,
|
||||
// the StartTime is set to the current time - (IntervalId * MaxSample).
|
||||
func (m *Manager) SampleByName(ctx context.Context, spec types.PerfQuerySpec, metrics []string, entity []types.ManagedObjectReference) ([]types.BasePerfEntityMetricBase, error) {
|
||||
info, err := m.CounterInfoByName(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ids []types.PerfMetricId
|
||||
|
||||
instances := spec.MetricId
|
||||
if len(instances) == 0 {
|
||||
// Default to all instances
|
||||
instances = []types.PerfMetricId{{Instance: "*"}}
|
||||
}
|
||||
|
||||
for _, name := range metrics {
|
||||
counter, ok := info[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("counter %q not found", name)
|
||||
}
|
||||
|
||||
for _, i := range instances {
|
||||
ids = append(ids, types.PerfMetricId{CounterId: counter.Key, Instance: i.Instance})
|
||||
}
|
||||
}
|
||||
|
||||
spec.MetricId = ids
|
||||
|
||||
if spec.MaxSample == 0 {
|
||||
spec.MaxSample = 1
|
||||
}
|
||||
|
||||
if spec.IntervalId >= 60 && spec.StartTime == nil {
|
||||
// Need a StartTime to make use of history
|
||||
now, err := methods.GetCurrentTime(ctx, m.Client())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Go back in time
|
||||
x := spec.IntervalId * -1 * spec.MaxSample
|
||||
t := now.Add(time.Duration(x) * time.Second)
|
||||
spec.StartTime = &t
|
||||
}
|
||||
|
||||
var query []types.PerfQuerySpec
|
||||
|
||||
for _, e := range entity {
|
||||
spec.Entity = e.Reference()
|
||||
query = append(query, spec)
|
||||
}
|
||||
|
||||
return m.Query(ctx, query)
|
||||
}
|
||||
|
||||
// MetricSeries contains the same data as types.PerfMetricIntSeries, but with the CounterId converted to Name.
|
||||
type MetricSeries struct {
|
||||
Name string
|
||||
unit string
|
||||
Instance string
|
||||
Value []int64
|
||||
}
|
||||
|
||||
func (s *MetricSeries) Format(val int64) string {
|
||||
switch types.PerformanceManagerUnit(s.unit) {
|
||||
case types.PerformanceManagerUnitPercent:
|
||||
return strconv.FormatFloat(float64(val)/100.0, 'f', 2, 64)
|
||||
default:
|
||||
return strconv.FormatInt(val, 10)
|
||||
}
|
||||
}
|
||||
|
||||
// ValueCSV converts the Value field to a CSV string
|
||||
func (s *MetricSeries) ValueCSV() string {
|
||||
vals := make([]string, len(s.Value))
|
||||
|
||||
for i := range s.Value {
|
||||
vals[i] = s.Format(s.Value[i])
|
||||
}
|
||||
|
||||
return strings.Join(vals, ",")
|
||||
}
|
||||
|
||||
// EntityMetric contains the same data as types.PerfEntityMetric, but with MetricSeries type for the Value field.
|
||||
type EntityMetric struct {
|
||||
Entity types.ManagedObjectReference
|
||||
|
||||
SampleInfo []types.PerfSampleInfo
|
||||
Value []MetricSeries
|
||||
}
|
||||
|
||||
// SampleInfoCSV converts the SampleInfo field to a CSV string
|
||||
func (m *EntityMetric) SampleInfoCSV() string {
|
||||
vals := make([]string, len(m.SampleInfo)*2)
|
||||
|
||||
i := 0
|
||||
|
||||
for _, s := range m.SampleInfo {
|
||||
vals[i] = s.Timestamp.Format(time.RFC3339)
|
||||
i++
|
||||
vals[i] = strconv.Itoa(int(s.Interval))
|
||||
i++
|
||||
}
|
||||
|
||||
return strings.Join(vals, ",")
|
||||
}
|
||||
|
||||
// ToMetricSeries converts []BasePerfEntityMetricBase to []EntityMetric
|
||||
func (m *Manager) ToMetricSeries(ctx context.Context, series []types.BasePerfEntityMetricBase) ([]EntityMetric, error) {
|
||||
counters, err := m.CounterInfoByKey(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []EntityMetric
|
||||
|
||||
for i := range series {
|
||||
var values []MetricSeries
|
||||
s, ok := series[i].(*types.PerfEntityMetric)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("expected type %T, got: %T", s, series[i]))
|
||||
}
|
||||
|
||||
for j := range s.Value {
|
||||
v := s.Value[j].(*types.PerfMetricIntSeries)
|
||||
|
||||
values = append(values, MetricSeries{
|
||||
Name: counters[v.Id.CounterId].Name(),
|
||||
unit: counters[v.Id.CounterId].UnitInfo.GetElementDescription().Key,
|
||||
Instance: v.Id.Instance,
|
||||
Value: v.Value,
|
||||
})
|
||||
}
|
||||
|
||||
result = append(result, EntityMetric{
|
||||
Entity: s.Entity,
|
||||
SampleInfo: s.SampleInfo,
|
||||
Value: values,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user