数据结构的定义是什么(数据结构指的是什么)
664
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
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小时内删除侵权内容。