Files
gocommon/azure/monitor.go

203 lines
3.6 KiB
Go

package azure
import (
"bytes"
"encoding/json"
"fmt"
"io"
"math"
"net/http"
"net/url"
)
type CounterCurcuit struct {
curcuit []float64
cursor int
}
func (cc *CounterCurcuit) Append(val float64) {
cc.curcuit[cc.cursor] = val
cc.cursor++
}
func (cc *CounterCurcuit) Stat() (min float64, max float64, sum float64, count int) {
if cc.cursor == 0 {
return 0, 0, 0, 0
}
min = math.MaxFloat64
max = -math.MaxFloat64
sum = float64(0)
if cc.cursor < len(cc.curcuit) {
count = cc.cursor
for i := 0; i < cc.cursor; i++ {
if min > cc.curcuit[i] {
min = cc.curcuit[i]
}
if max < cc.curcuit[i] {
max = cc.curcuit[i]
}
sum += cc.curcuit[i]
}
return
}
count = len(cc.curcuit)
for _, v := range cc.curcuit {
if min > v {
min = v
}
if max < v {
max = v
}
sum += v
}
return
}
func MakeCounterCurcuit(length int) *CounterCurcuit {
return &CounterCurcuit{
curcuit: make([]float64, length),
cursor: 0,
}
}
type Float64Counter struct {
Min float64 `json:"min"`
Max float64 `json:"max"`
Sum float64 `json:"sum"`
Count int `json:"count"`
}
var DefaultFloat64Counter = Float64Counter{
Min: math.MaxFloat64,
Max: -math.MaxFloat64,
Sum: 0,
Count: 0,
}
func (c *Float64Counter) Valid() bool {
return c.Count > 0
}
func (c *Float64Counter) Add(val float64) {
if c.Max < val {
c.Max = val
}
if c.Min > val {
c.Min = val
}
c.Sum += val
c.Count++
}
func (c *Float64Counter) SingleMin() Float64Counter {
return Float64Counter{
Min: c.Min,
Max: c.Min,
Sum: c.Min,
Count: 1,
}
}
func (c *Float64Counter) SingleMax() Float64Counter {
return Float64Counter{
Min: c.Max,
Max: c.Max,
Sum: c.Max,
Count: 1,
}
}
func (c *Float64Counter) AddInt(val int) {
fval := float64(val)
if c.Max < fval {
c.Max = fval
}
if c.Min > fval {
c.Min = fval
}
c.Sum += fval
c.Count++
}
type MetricSeries struct {
Float64Counter
DimValues []string `json:"dimValues"`
}
type MetructBaseData struct {
Metric string `json:"metric"`
Namespace string `json:"namespace"`
DimNames []string `json:"dimNames"`
Series []MetricSeries `json:"series"`
}
type MetricData struct {
BaseData MetructBaseData `json:"baseData"`
}
type MetricDocument struct {
Time string `json:"time"`
Data MetricData `json:"data"`
}
func MakeMetricDocument(timestamp string, namespace string, metric string, dimNames []string) MetricDocument {
output := MetricDocument{Time: timestamp}
output.Data.BaseData.DimNames = dimNames
output.Data.BaseData.Metric = metric
output.Data.BaseData.Namespace = namespace
return output
}
type Monitor struct {
*accessToken
tenantId string
}
func NewMonitor(tenantId string) *Monitor {
return &Monitor{
accessToken: &accessToken{
url: fmt.Sprintf("https://login.microsoftonline.com/%s/oauth2/token", tenantId),
values: url.Values{
"grant_type": {"client_credentials"},
"client_id": {microsoftAppId()},
"resource": {"https://monitoring.azure.com/"},
"client_secret": {microsoftAppPassword()},
},
},
tenantId: tenantId,
}
}
func (m Monitor) PostMetrics(url string, docs ...MetricDocument) error {
// https://docs.microsoft.com/ko-kr/rest/api/monitor/metrics%20(data%20plane)/create
token, err := m.getAuthoizationToken()
if err != nil {
return err
}
for _, doc := range docs {
bt, _ := json.Marshal(doc)
req, _ := http.NewRequest("POST", url, bytes.NewReader(bt))
req.Header.Add("Authorization", token)
req.Header.Add("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}
return nil
}