1package main 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7) 8 9type Response struct { 10 PathExpression string `yaml:"pathExpression"` 11 Data []Metric `yaml:"data"` 12} 13 14type Metric struct { 15 MetricName string `yaml:"metricName"` 16 Step int `yaml:"step"` 17 StartTime int `yaml:"startTime"` 18 Values []float64 `yaml:"values"` 19} 20 21type metricForJson struct { 22 MetricName string 23 Values []string 24} 25 26func (m *Metric) MarshalJSON() ([]byte, error) { 27 m2 := metricForJson{ 28 MetricName: m.MetricName, 29 Values: make([]string, len(m.Values)), 30 } 31 32 for i, v := range m.Values { 33 m2.Values[i] = fmt.Sprintf("%v", v) 34 } 35 36 return json.Marshal(m2) 37} 38 39type responseFormat int 40 41const ( 42 jsonFormat responseFormat = iota 43 pickleFormat 44 protoV2Format 45 protoV3Format 46) 47 48func getFormat(req *http.Request) (responseFormat, error) { 49 format := req.FormValue("format") 50 if format == "" { 51 format = "json" 52 } 53 54 formatCode, ok := knownFormats[format] 55 if !ok { 56 return formatCode, fmt.Errorf("unknown format") 57 } 58 59 return formatCode, nil 60} 61 62var knownFormats = map[string]responseFormat{ 63 "json": jsonFormat, 64 "pickle": pickleFormat, 65 "protobuf": protoV2Format, 66 "protobuf3": protoV2Format, 67 "carbonapi_v2_pb": protoV2Format, 68 "carbonapi_v3_pb": protoV3Format, 69} 70 71func (r responseFormat) String() string { 72 switch r { 73 case jsonFormat: 74 return "json" 75 case pickleFormat: 76 return "pickle" 77 case protoV2Format: 78 return "carbonapi_v2_pb" 79 default: 80 return "unknown" 81 } 82} 83 84func copyResponse(src Response) Response { 85 dst := Response{ 86 PathExpression: src.PathExpression, 87 Data: make([]Metric, len(src.Data)), 88 } 89 90 for i := range src.Data { 91 dst.Data[i] = Metric{ 92 MetricName: src.Data[i].MetricName, 93 Values: make([]float64, len(src.Data[i].Values)), 94 StartTime: src.Data[i].StartTime, 95 Step: src.Data[i].Step, 96 } 97 98 for j := range src.Data[i].Values { 99 dst.Data[i].Values[j] = src.Data[i].Values[j] 100 } 101 } 102 103 return dst 104} 105 106func copyMap(src map[string]Response) map[string]Response { 107 dst := make(map[string]Response) 108 109 for k, v := range src { 110 dst[k] = copyResponse(v) 111 } 112 113 return dst 114} 115 116const ( 117 contentTypeJSON = "application/json" 118 contentTypeProtobuf = "application/x-protobuf" 119 contentTypeJavaScript = "text/javascript" 120 contentTypeRaw = "text/plain" 121 contentTypePickle = "application/pickle" 122 contentTypePNG = "image/png" 123 contentTypeCSV = "text/csv" 124 contentTypeSVG = "image/svg+xml" 125) 126