@@ -23,30 +23,43 @@ import (
23
23
"time"
24
24
25
25
"github.com/apache/thrift/lib/go/thrift"
26
+ "github.com/go-openapi/loads"
27
+ "github.com/go-openapi/swag"
26
28
"github.com/gorilla/mux"
29
+ "github.com/pkg/errors"
27
30
tchanThrift "github.com/uber/tchannel-go/thrift"
28
31
29
32
"github.com/uber/jaeger/cmd/collector/app"
33
+ "github.com/uber/jaeger/swagger-gen/models"
34
+ "github.com/uber/jaeger/swagger-gen/restapi"
35
+ "github.com/uber/jaeger/swagger-gen/restapi/operations"
30
36
"github.com/uber/jaeger/thrift-gen/zipkincore"
31
37
)
32
38
33
39
// APIHandler handles all HTTP calls to the collector
34
40
type APIHandler struct {
35
41
zipkinSpansHandler app.ZipkinSpansHandler
42
+ zipkinV2API * operations.ZipkinAPI
36
43
}
37
44
38
45
// NewAPIHandler returns a new APIHandler
39
46
func NewAPIHandler (
40
47
zipkinSpansHandler app.ZipkinSpansHandler ,
41
- ) * APIHandler {
48
+ ) (* APIHandler , error ) {
49
+ swaggerSpec , err := loads .Analyzed (restapi .SwaggerJSON , "" )
50
+ if err != nil {
51
+ return nil , errors .Wrapf (err , "Failed to create zipkin swagger" )
52
+ }
42
53
return & APIHandler {
43
54
zipkinSpansHandler : zipkinSpansHandler ,
44
- }
55
+ zipkinV2API : operations .NewZipkinAPI (swaggerSpec ),
56
+ }, nil
45
57
}
46
58
47
59
// RegisterRoutes registers Zipkin routes
48
60
func (aH * APIHandler ) RegisterRoutes (router * mux.Router ) {
49
61
router .HandleFunc ("/api/v1/spans" , aH .saveSpans ).Methods (http .MethodPost )
62
+ router .HandleFunc ("/api/v2/spans" , aH .saveSpansV2 ).Methods (http .MethodPost )
50
63
}
51
64
52
65
func (aH * APIHandler ) saveSpans (w http.ResponseWriter , r * http.Request ) {
@@ -84,15 +97,56 @@ func (aH *APIHandler) saveSpans(w http.ResponseWriter, r *http.Request) {
84
97
return
85
98
}
86
99
100
+ if err := aH .saveThriftSpans (tSpans ); err != nil {
101
+ http .Error (w , fmt .Sprintf ("Cannot submit Zipkin batch: %v" , err ), http .StatusInternalServerError )
102
+ return
103
+ }
104
+
105
+ w .WriteHeader (http .StatusAccepted )
106
+ }
107
+
108
+ func (aH * APIHandler ) saveSpansV2 (w http.ResponseWriter , r * http.Request ) {
109
+ bRead := r .Body
110
+ defer r .Body .Close ()
111
+
112
+ bodyBytes , err := ioutil .ReadAll (bRead )
113
+ if err != nil {
114
+ http .Error (w , fmt .Sprintf (app .UnableToReadBodyErrFormat , err ), http .StatusInternalServerError )
115
+ return
116
+ }
117
+
118
+ var spans * models.ListOfSpans = & models.ListOfSpans {}
119
+ if err = swag .ReadJSON (bodyBytes , spans ); err != nil {
120
+ http .Error (w , fmt .Sprintf (app .UnableToReadBodyErrFormat , err ), http .StatusBadRequest )
121
+ return
122
+ }
123
+ if err = spans .Validate (aH .zipkinV2API .Formats ()); err != nil {
124
+ http .Error (w , fmt .Sprintf (app .UnableToReadBodyErrFormat , err ), http .StatusBadRequest )
125
+ return
126
+ }
127
+
128
+ tSpans , err := spansV2ToThrift (spans )
129
+ if err != nil {
130
+ http .Error (w , fmt .Sprintf (app .UnableToReadBodyErrFormat , err ), http .StatusBadRequest )
131
+ return
132
+ }
133
+
134
+ if err := aH .saveThriftSpans (tSpans ); err != nil {
135
+ http .Error (w , fmt .Sprintf ("Cannot submit Zipkin batch: %v" , err ), http .StatusInternalServerError )
136
+ return
137
+ }
138
+
139
+ w .WriteHeader (operations .PostSpansAcceptedCode )
140
+ }
141
+
142
+ func (aH * APIHandler ) saveThriftSpans (tSpans []* zipkincore.Span ) error {
87
143
if len (tSpans ) > 0 {
88
144
ctx , _ := tchanThrift .NewContext (time .Minute )
89
- if _ , err = aH .zipkinSpansHandler .SubmitZipkinBatch (ctx , tSpans ); err != nil {
90
- http .Error (w , fmt .Sprintf ("Cannot submit Zipkin batch: %v" , err ), http .StatusInternalServerError )
91
- return
145
+ if _ , err := aH .zipkinSpansHandler .SubmitZipkinBatch (ctx , tSpans ); err != nil {
146
+ return err
92
147
}
93
148
}
94
-
95
- w .WriteHeader (http .StatusAccepted )
149
+ return nil
96
150
}
97
151
98
152
func deserializeThrift (b []byte ) ([]* zipkincore.Span , error ) {
0 commit comments