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

举报
云监控问答号 发表于 2017/11/20 19:08:16 2017/11/20
【摘要】 调用云监控接口添加监控数据 – Go语言版 当原有业务上云后,借助云监控平台,可以通过调用云监控接口,将原有业务系统指标数据上报给云监控服务,实现统筹监控、及时告警的效果。 1 添加监控数据流程 获取AK/SK、项目编号、服务名称(云监控在认证中使用的名称是CES)等准备工作可以参看第5节。 2 通过AK/SK

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


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

1       添加监控数据流程

    image.png


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

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

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

image.png

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

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

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

image.png


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

4       添加监控数据

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

image.png

SendMetricData函数实现以下功能:

1.    序列化指标数据

2.    生成请求(方法“POST”urlbuffer

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


}

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。