调用云监控接口添加监控数据 – Go语言版

网友投稿 704 2022-05-30

调用云监控接口添加监控数据 – Go语言版

当原有业务上云后,借助云监控平台,可以通过调用云监控接口,将原有业务系统指标数据上报给云监控服务,实现统筹监控、及时告警的效果。

1       添加监控数据流程

获取AK/SK、项目编号、服务名称(云监控在认证中使用的名称是CES)等准备工作可以参看第5节。

2       通过AK/SK获取HTTPS请求头

通过自己的AK/SK,调用golang自身的加密算法获取HTTPS请求头认证信息,是调用云监控接口比较麻烦的地方。这里可以直接使用下面的函数生成:

关于上图中的GetAuthorization定义在示例代码signer.go中,具体参看第5节。

3       定义添加监控数据的结构体

向云监控添加监控数据的结构体定义可以直接使用以下定义:

这里的数据格式具体参考第5节,其中各字段的说明一定要按照文档要求,否则请求会作为非法请求被拒绝。

4       添加监控数据

通过调用以下函数完成添加监控数据。

SendMetricData函数实现以下功能:

1.    序列化指标数据

2.    生成请求(方法“POST”、url、buffer)

3.    调用singer.go中的认证方法,完成AK/SK认证

4.    执行请求

5       参考

Ø  AK/SK、项目编号参考:http://support.huaweicloud.com/api-ces/zh-cn_topic_0022485056.html

Ø  云监控接口参考:http://support.huaweicloud.com/api-ces/zh-cn_topic_0032831274.html

Ø  添加监控数据结构体字段参考:http://support.huaweicloud.com/api-ces/zh-cn_topic_0032831274.html

Ø  singer.go文件参考:

package utils

import (

"bytes"

"crypto/hmac"

"crypto/sha256"

"encoding/hex"

"errors"

"io/ioutil"

"net/http"

"net/url"

"sort"

"strings"

"time"

)

const (

COMMA          string = ","

SEMICOLON      string = ";"

COLON          string = ":"

EQUALSIGN      string = "="

BLANK          string = " "

SLASH          string = "/"

LINE_SEPARATOR string = "\n"

BasicDateFormat      = "20060102T150405Z"

BasicDateFormatShort = "20060102"

TerminationString    = "sdk_request"

Algorithm            = "SDK-HMAC-SHA256"

PreSKString          = "SDK"

HeaderXDate          = "x-sdk-date"

HeaderDate           = "date"

HeaderHost           = "host"

HeaderAuthorization  = "Authorization"

HeaderProjectId      = "X-Project-Id"

HeaderAuthToken      = "X-Auth-Token"

HeaderConnection  = "connection"

HeaderUserAgent   = "user-agent"

HeaderContentType = "content-type"

)

type Signer struct {

AccessKey string

SecretKey string

Region    string

Service   string

reqTime   time.Time

}

func *** igner(serviceName string) *Signer {

return &Signer{

AccessKey: GetConfig().AccessKey,

SecretKey: GetConfig().SecretKey,

Region:    GetConfig().RegionId,

Service:   serviceName,

}

}

func (sig *Signer) getReqTime(req *http.Request) (reqTime time.Time, err error) {

if timeStr := req.Header.Get(HeaderXDate); len(timeStr) > 0 {

return time.Parse(BasicDateFormat, timeStr)

} else {

return time.Time{}, errors.New("No x-sdk-date in request.")

}

}

func CanonicalRequest(req *http.Request) (string, error) {

data, err := requestPayload(req)

if err != nil {

return "", err

}

hexencode, err := hexEncodeSHA256Hash(data)

if err != nil {

return "", err

}

result := bytes.Buffer{}

result.WriteString(req.Method)

result.WriteString(LINE_SEPARATOR)

result.WriteString(canonicalURI(req))

result.WriteString(LINE_SEPARATOR)

result.WriteString(canonicalQueryString(req))

result.WriteString(LINE_SEPARATOR)

result.WriteString(canonicalHeaders(req))

result.WriteString(LINE_SEPARATOR)

result.WriteString(signedHeaders(req))

result.WriteString(LINE_SEPARATOR)

result.WriteString(hexencode)

return result.String(), nil

}

// RequestPayload

func requestPayload(r *http.Request) ([]byte, error) {

if r.Body == nil {

return []byte(""), nil

}

b, err := ioutil.ReadAll(r.Body)

if err == nil {

r.Body = ioutil.NopCloser(bytes.NewBuffer(b))

}

return b, err

}

// hexEncodeSHA256Hash returns hexcode of sha256

func hexEncodeSHA256Hash(body []byte) (string, error) {

hash := sha256.New()

if body == nil {

body = []byte("")

}

_, err := hash.Write(body)

return hex.EncodeToString(hash.Sum(nil)), err

}

// CanonicalURI returns request uri

func canonicalURI(r *http.Request) string {

pattens := strings.Split(r.URL.Path, SLASH)

var uri []string

for _, v := range pattens {

switch v {

case "":

continue

case ".":

continue

case "..":

if len(uri) > 0 {

uri = uri[:len(uri)-1]

}

default:

uri = append(uri, url.QueryEscape(v))

}

}

urlpath := SLASH + strings.Join(uri, SLASH)

urlpath = strings.Replace(urlpath, "+", "%20", -1)

if ok := strings.HasSuffix(urlpath, SLASH); ok {

return urlpath

} else {

return urlpath + SLASH

}

}

// CanonicalQueryString

func canonicalQueryString(r *http.Request) string {

var a []string

for key, value := range r.URL.Query() {

k := url.QueryEscape(key)

for _, v := range value {

var kv string

if v == "" {

kv = k + "="

} else {

kv = k + "=" + url.QueryEscape(v)

}

a = append(a, strings.Replace(kv, "+", "%20", -1))

}

}

sort.Strings(a)

return strings.Join(a, "&")

}

// CanonicalHeaders

调用云监控接口添加监控数据 – Go语言版

func canonicalHeaders(r *http.Request) string {

var a []string

for key, value := range r.Header {

sort.Strings(value)

var q []string

for _, v := range value {

q = append(q, trimString(v))

}

a = append(a, strings.ToLower(key)+":"+strings.Join(q, ","))

}

a = append(a, HeaderHost+":"+r.Host)

sort.Strings(a)

return strings.Join(a, "\n") + LINE_SEPARATOR

}

func trimString(s string) string {

var trimedString []byte

inQuote := false

var lastChar byte

s = strings.TrimSpace(s)

for _, v := range []byte(s) {

if byte(v) == byte('"') {

inQuote = !inQuote

}

if lastChar == byte(' ') && byte(v) == byte(' ') && !inQuote {

continue

}

trimedString = append(trimedString, v)

lastChar = v

}

return string(trimedString)

}

// Return the Credential Scope. See http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html

func credentialScope(t time.Time, regionName, serviceName string) string {

result := bytes.Buffer{}

result.WriteString(t.UTC().Format(BasicDateFormatShort))

result.WriteString(SLASH)

result.WriteString(regionName)

result.WriteString(SLASH)

result.WriteString(serviceName)

result.WriteString(SLASH)

result.WriteString(TerminationString)

return result.String()

}

// Create a "String to Sign". See http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html

func stringToSign(canonicalRequest, credentialScope string, t time.Time) string {

hash := sha256.New()

hash.Write([]byte(canonicalRequest))

result := bytes.Buffer{}

result.WriteString(Algorithm)

result.WriteString(LINE_SEPARATOR)

result.WriteString(t.UTC().Format(BasicDateFormat))

result.WriteString(LINE_SEPARATOR)

result.WriteString(credentialScope)

result.WriteString(LINE_SEPARATOR)

result.WriteString(hex.EncodeToString(hash.Sum(nil)))

return result.String()

}

// Generate a "signing key" to sign the "String To Sign". See http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html

func generateSigningKey(secretKey, regionName, serviceName string, t time.Time) ([]byte, error) {

key := []byte(PreSKString + secretKey)

var err error

dateStamp := t.UTC().Format(BasicDateFormatShort)

data := []string{dateStamp, regionName, serviceName, TerminationString}

for _, d := range data {

key, err = hmacsha256(key, d)

if err != nil {

return nil, err

}

}

return key, nil

}

// Create the HWS Signature. See http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html

func signStringToSign(stringToSign string, signingKey []byte) (string, error) {

hm, err := hmacsha256(signingKey, stringToSign)

if err != nil {

return "", err

}

return hex.EncodeToString(hm), nil

}

func hmacsha256(key []byte, data string) ([]byte, error) {

h := hmac.New(sha256.New, []byte(key))

if _, err := h.Write([]byte(data)); err != nil {

return nil, err

}

return h.Sum(nil), nil

}

// SignedHeaders

func signedHeaders(r *http.Request) string {

var a []string

for key := range r.Header {

a = append(a, strings.ToLower(key))

}

a = append(a, HeaderHost)

sort.Strings(a)

return strings.Join(a, SEMICOLON)

}

// Get the finalized value for the "Authorization" header. The signature parameter is the output from SignStringToSign

func AuthHeaderValue(signature, accessKey, credentialScope, signedHeaders string) string {

result := bytes.Buffer{}

result.WriteString(Algorithm)

result.WriteString(" Credential=")

result.WriteString(accessKey)

result.WriteString(SLASH)

result.WriteString(credentialScope)

result.WriteString(", SignedHeaders=")

result.WriteString(signedHeaders)

result.WriteString(", Signature=")

result.WriteString(signature)

return result.String()

}

func (sig *Signer) GetAuthorization(req *http.Request) (string, error) {

var authorization string

if req == nil {

return authorization, errors.New("Verify failed, req is nil.")

}

reqTime, err := sig.getReqTime(req)

if err != nil {

return authorization, err

}

sig.reqTime = reqTime

canonicalRequest, err := CanonicalRequest(req)

if err != nil {

return authorization, err

}

credentialScope := credentialScope(sig.reqTime, sig.Region, sig.Service)

stringToSign := stringToSign(canonicalRequest, credentialScope, sig.reqTime)

key, err := generateSigningKey(sig.SecretKey, sig.Region, sig.Service, sig.reqTime)

if err != nil {

return authorization, err

}

signature, err := signStringToSign(stringToSign, key)

if err != nil {

return authorization, err

}

signedHeaders := signedHeaders(req)

authValue := AuthHeaderValue(signature, sig.AccessKey, credentialScope, signedHeaders)

return authValue, nil

}

Go语言 云监控

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:测试用例(包含测经典试点全集图解,强烈建议保存收藏)
下一篇:Atlas 200DK 开发环境搭建
相关文章