调用云监控接口添加监控数据 – Go语言版
调用云监控接口添加监控数据 – 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 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 } |
- 点赞
- 收藏
- 关注作者
评论(0)