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 }