func GetTopNReferers(cli bce.Client, queryCondition *QueryCondition, httpCode string) ([]TopNDetail, error) {
	return getTopN(cli, queryCondition, httpCode, "top_referers")
}
GetTopNReferers - get the top N urls that brought by requested
For details, please refer https://cloud.baidu.com/doc/CDN/s/5jwvyf8zn#topn-referers

PARAMS:
- cli: the client agent which can perform sending request
- queryCondition: the querying conditions
- httpCode: the specified HTTP code, like "200"
RETURNS:
- []TopNDetail: the top N referer urls' detail
- error: nil if success otherwise the specific error
package api
import (
	"strconv"
	"strings"
	"github.com/baidubce/bce-sdk-go/bce"
)
const (
	statisticsObjectKey  = "/v2/stat/query"
	statisticsBillingKey = "/v2/billing"
)
type QueryCondition struct {
	EndTime   string   `json:"endTime,omitempty"`
	StartTime string   `json:"startTime,omitempty"`
	Period    int      `json:"period,omitempty"`
	KeyType   int      `json:"key_type"`
	Key       []string `json:"key,omitempty"`
	GroupBy   string   `json:"groupBy,omitempty"`
}
type DetailBase struct {
	Timestamp string `json:"timestamp"`
	Key       string `json:"key,omitempty"`
}
type NetSite struct {
	Location string `json:"location"`
	Isp      string `json:"isp"`
}
type AvgSpeedRegionData struct {
	*NetSite
	AvgSpeed int64 `json:"avgspeed"`
}
type AvgSpeedDetail struct {
	*DetailBase
	AvgSpeed int64 `json:"avgspeed"`
}
type AvgSpeedRegionDetail struct {
	*DetailBase
	Distribution []AvgSpeedRegionData `json:"distribution"`
}
type PvDetail struct {
	*DetailBase
	Pv  int64 `json:"pv"`
	Qps int64 `json:"qps"`
}
type PVRegionData struct {
	*NetSite
	Pv  int64 `json:"pv"`
	Qps int64 `json:"qps"`
}
type PvRegionDetail struct {
	*DetailBase
	Distribution []PVRegionData `json:"distribution"`
}
type UvDetail struct {
	*DetailBase
	Uv int64 `json:"uv"`
}
type FlowDetail struct {
	*DetailBase
	Flow float64 `json:"flow"`
	Bps  int64   `json:"bps"`
}
type FlowRegionData struct {
	*NetSite
	Flow float64 `json:"flow"`
	Bps  int64   `json:"bps"`
}
type FlowRegionDetail struct {
	*DetailBase
	Distribution []FlowRegionData `json:"distribution"`
}
type HitDetail struct {
	*DetailBase
	HitRate float64 `json:"hitrate"`
}
type KvCounter struct {
	Name  int64 `json:"name"`
	Count int64 `json:"count"`
}
type HttpCodeDetail struct {
	*DetailBase
	Counters []KvCounter `json:"counters"`
}
type HttpCodeRegionData struct {
	*NetSite
	Counters []KvCounter `json:"counters"`
}
type HttpCodeRegionDetail struct {
	*DetailBase
	Distribution []HttpCodeRegionData `json:"distribution"`
}
type TopNCounter struct {
	Name string  `json:"name"`
	Pv   int64   `json:"pv"`
	Flow float64 `json:"flow"`
}
type TopNDetail struct {
	*DetailBase
	TotalPv   int64         `json:"total_pv"`
	TotalFlow float64       `json:"total_flow"`
	Counters  []TopNCounter `json:"counters"`
}
type ErrorKvCounter struct {
	Code     string      `json:"code"`
	Counters []KvCounter `json:"counters"`
}
type ErrorDetail struct {
	*DetailBase
	Counters []ErrorKvCounter `json:"counters"`
}
func GetAvgSpeed(cli bce.Client, queryCondition *QueryCondition) ([]AvgSpeedDetail, error) {
	respObj := &struct {
		Status  string           `json:"status"`
		Count   int64            `json:"count"`
		Details []AvgSpeedDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Metric:         "avg_speed",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetAvgSpeedByRegion(cli bce.Client, queryCondition *QueryCondition, prov string, isp string) ([]AvgSpeedRegionDetail, error) {
	respObj := &struct {
		Status  string                 `json:"status"`
		Count   int64                  `json:"count"`
		Details []AvgSpeedRegionDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Prov   string `json:"prov,omitempty"`
		Isp    string `json:"isp,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Prov:           prov,
		Isp:            isp,
		Metric:         "avg_speed_region",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetPv(cli bce.Client, queryCondition *QueryCondition, level string) ([]PvDetail, error) {
	respObj := &struct {
		Status  string     `json:"status"`
		Count   int64      `json:"count"`
		Details []PvDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Level  string `json:"level,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Level:          level,
		Metric:         "pv",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetSrcPv(cli bce.Client, queryCondition *QueryCondition) ([]PvDetail, error) {
	respObj := &struct {
		Status  string     `json:"status"`
		Count   int64      `json:"count"`
		Details []PvDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Metric:         "pv_src",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetPvByRegion(cli bce.Client, queryCondition *QueryCondition, prov string, isp string) ([]PvRegionDetail, error) {
	respObj := &struct {
		Status  string           `json:"status"`
		Count   int64            `json:"count"`
		Details []PvRegionDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Prov   string `json:"prov,omitempty"`
		Isp    string `json:"isp,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Prov:           prov,
		Isp:            isp,
		Metric:         "pv_region",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetUv(cli bce.Client, queryCondition *QueryCondition) ([]UvDetail, error) {
	respObj := &struct {
		Status  string     `json:"status"`
		Count   int64      `json:"count"`
		Details []UvDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Level  string `json:"level,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Metric:         "uv",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetFlow(cli bce.Client, queryCondition *QueryCondition, level string) ([]FlowDetail, error) {
	respObj := &struct {
		Status  string       `json:"status"`
		Count   int64        `json:"count"`
		Details []FlowDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Level  string `json:"level,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Level:          level,
		Metric:         "flow",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetFlowByProtocol(cli bce.Client, queryCondition *QueryCondition, protocol string) ([]FlowDetail, error) {
	respObj := &struct {
		Status  string       `json:"status"`
		Count   int64        `json:"count"`
		Details []FlowDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Protocol string `json:"protocol,omitempty"`
		Metric   string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Protocol:       protocol,
		Metric:         "flow_protocol",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetFlowByRegion(cli bce.Client, queryCondition *QueryCondition, prov string, isp string) ([]FlowRegionDetail, error) {
	respObj := &struct {
		Status  string             `json:"status"`
		Count   int64              `json:"count"`
		Details []FlowRegionDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Prov   string `json:"prov,omitempty"`
		Isp    string `json:"isp,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Prov:           prov,
		Isp:            isp,
		Metric:         "flow_region",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetSrcFlow(cli bce.Client, queryCondition *QueryCondition) ([]FlowDetail, error) {
	respObj := &struct {
		Status  string       `json:"status"`
		Count   int64        `json:"count"`
		Details []FlowDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Protocol string `json:"protocol,omitempty"`
		Metric   string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Metric:         "src_flow",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func getHit(cli bce.Client, queryCondition *QueryCondition, metric string) ([]HitDetail, error) {
	respObj := &struct {
		Status  string      `json:"status"`
		Count   int64       `json:"count"`
		Details []HitDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Protocol string `json:"protocol,omitempty"`
		Metric   string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Metric:         metric,
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetRealHit(cli bce.Client, queryCondition *QueryCondition) ([]HitDetail, error) {
	return getHit(cli, queryCondition, "real_hit")
}
func GetPvHit(cli bce.Client, queryCondition *QueryCondition) ([]HitDetail, error) {
	return getHit(cli, queryCondition, "pv_hit")
}
func getHttpCode(cli bce.Client, queryCondition *QueryCondition, metric string) ([]HttpCodeDetail, error) {
	respObj := &struct {
		Status  string           `json:"status"`
		Count   int64            `json:"count"`
		Details []HttpCodeDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Protocol string `json:"protocol,omitempty"`
		Metric   string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Metric:         metric,
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetHttpCode(cli bce.Client, queryCondition *QueryCondition) ([]HttpCodeDetail, error) {
	return getHttpCode(cli, queryCondition, "httpcode")
}
func GetSrcHttpCode(cli bce.Client, queryCondition *QueryCondition) ([]HttpCodeDetail, error) {
	return getHttpCode(cli, queryCondition, "src_httpcode")
}
func GetHttpCodeByRegion(cli bce.Client, queryCondition *QueryCondition, prov string, isp string) ([]HttpCodeRegionDetail, error) {
	respObj := &struct {
		Status  string                 `json:"status"`
		Count   int64                  `json:"count"`
		Details []HttpCodeRegionDetail `json:"details"`
	}{}
	err := httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Prov   string `json:"prov,omitempty"`
		Isp    string `json:"isp,omitempty"`
		Metric string `json:"metric"`
	}{
		QueryCondition: queryCondition,
		Prov:           prov,
		Isp:            isp,
		Metric:         "httpcode_region",
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func getTopN(cli bce.Client, queryCondition *QueryCondition, httpCode string, metric string) ([]TopNDetail, error) {
	extra, err := strconv.ParseInt(httpCode, 10, 64)
	if err != nil {
		extra = 0
	}
	respObj := &struct {
		Status  string       `json:"status"`
		Count   int64        `json:"count"`
		Details []TopNDetail `json:"details"`
	}{}
	err = httpRequest(cli, "POST", statisticsObjectKey, nil, &struct {
		*QueryCondition
		Protocol string `json:"protocol,omitempty"`
		Metric   string `json:"metric"`
		Extra    int64  `json:"extra,omitempty"`
	}{
		QueryCondition: queryCondition,
		Metric:         metric,
		Extra:          extra,
	}, respObj)
	if err != nil {
		return nil, err
	}
	return respObj.Details, nil
}
func GetTopNUrls(cli bce.Client, queryCondition *QueryCondition, httpCode string) ([]TopNDetail, error) {
	return getTopN(cli, queryCondition, httpCode, "top_urls")
}