選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

259 行
7.1 KiB

  1. // Copyright 2017, OpenCensus Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package zipkin
  15. import (
  16. "encoding/json"
  17. "io/ioutil"
  18. "net/http"
  19. "reflect"
  20. "strings"
  21. "testing"
  22. "time"
  23. "github.com/openzipkin/zipkin-go/model"
  24. httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
  25. "go.opencensus.io/trace"
  26. )
  27. type roundTripper func(*http.Request) (*http.Response, error)
  28. func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
  29. return r(req)
  30. }
  31. func TestExport(t *testing.T) {
  32. // Since Zipkin reports in microsecond resolution let's round our Timestamp,
  33. // so when deserializing Zipkin data in this test we can properly compare.
  34. now := time.Now().Round(time.Microsecond)
  35. tests := []struct {
  36. span *trace.SpanData
  37. want model.SpanModel
  38. }{
  39. {
  40. span: &trace.SpanData{
  41. SpanContext: trace.SpanContext{
  42. TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
  43. SpanID: trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
  44. TraceOptions: 1,
  45. },
  46. Name: "name",
  47. SpanKind: trace.SpanKindClient,
  48. StartTime: now,
  49. EndTime: now.Add(24 * time.Hour),
  50. Attributes: map[string]interface{}{
  51. "stringkey": "value",
  52. "intkey": int64(42),
  53. "boolkey1": true,
  54. "boolkey2": false,
  55. "doublekey": float64(123.456),
  56. },
  57. MessageEvents: []trace.MessageEvent{
  58. {
  59. Time: now,
  60. EventType: trace.MessageEventTypeSent,
  61. MessageID: 12,
  62. UncompressedByteSize: 99,
  63. CompressedByteSize: 98,
  64. },
  65. },
  66. Annotations: []trace.Annotation{
  67. {
  68. Time: now,
  69. Message: "Annotation",
  70. Attributes: map[string]interface{}{
  71. "stringkey": "value",
  72. "intkey": int64(42),
  73. "boolkey1": true,
  74. "boolkey2": false,
  75. "doublekey": float64(123.456),
  76. },
  77. },
  78. },
  79. Status: trace.Status{
  80. Code: 3,
  81. Message: "error",
  82. },
  83. },
  84. want: model.SpanModel{
  85. SpanContext: model.SpanContext{
  86. TraceID: model.TraceID{
  87. High: 0x0102030405060708,
  88. Low: 0x090a0b0c0d0e0f10,
  89. },
  90. ID: 0x1112131415161718,
  91. Sampled: &sampledTrue,
  92. },
  93. Name: "name",
  94. Kind: model.Client,
  95. Timestamp: now,
  96. Duration: 24 * time.Hour,
  97. Shared: false,
  98. Annotations: []model.Annotation{
  99. {
  100. Timestamp: now,
  101. Value: "Annotation",
  102. },
  103. {
  104. Timestamp: now,
  105. Value: "SENT",
  106. },
  107. },
  108. Tags: map[string]string{
  109. "stringkey": "value",
  110. "intkey": "42",
  111. "boolkey1": "true",
  112. "boolkey2": "false",
  113. "doublekey": "123.456",
  114. "error": "INVALID_ARGUMENT",
  115. "opencensus.status_description": "error",
  116. },
  117. },
  118. },
  119. {
  120. span: &trace.SpanData{
  121. SpanContext: trace.SpanContext{
  122. TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
  123. SpanID: trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
  124. TraceOptions: 1,
  125. },
  126. Name: "name",
  127. StartTime: now,
  128. EndTime: now.Add(24 * time.Hour),
  129. },
  130. want: model.SpanModel{
  131. SpanContext: model.SpanContext{
  132. TraceID: model.TraceID{
  133. High: 0x0102030405060708,
  134. Low: 0x090a0b0c0d0e0f10,
  135. },
  136. ID: 0x1112131415161718,
  137. Sampled: &sampledTrue,
  138. },
  139. Name: "name",
  140. Timestamp: now,
  141. Duration: 24 * time.Hour,
  142. Shared: false,
  143. },
  144. },
  145. {
  146. span: &trace.SpanData{
  147. SpanContext: trace.SpanContext{
  148. TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
  149. SpanID: trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
  150. TraceOptions: 1,
  151. },
  152. Name: "name",
  153. StartTime: now,
  154. EndTime: now.Add(24 * time.Hour),
  155. Status: trace.Status{
  156. Code: 0,
  157. Message: "there is no cause for alarm",
  158. },
  159. },
  160. want: model.SpanModel{
  161. SpanContext: model.SpanContext{
  162. TraceID: model.TraceID{
  163. High: 0x0102030405060708,
  164. Low: 0x090a0b0c0d0e0f10,
  165. },
  166. ID: 0x1112131415161718,
  167. Sampled: &sampledTrue,
  168. },
  169. Name: "name",
  170. Timestamp: now,
  171. Duration: 24 * time.Hour,
  172. Shared: false,
  173. Tags: map[string]string{
  174. "opencensus.status_description": "there is no cause for alarm",
  175. },
  176. },
  177. },
  178. {
  179. span: &trace.SpanData{
  180. SpanContext: trace.SpanContext{
  181. TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
  182. SpanID: trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
  183. TraceOptions: 1,
  184. },
  185. Name: "name",
  186. StartTime: now,
  187. EndTime: now.Add(24 * time.Hour),
  188. Status: trace.Status{
  189. Code: 1234,
  190. },
  191. },
  192. want: model.SpanModel{
  193. SpanContext: model.SpanContext{
  194. TraceID: model.TraceID{
  195. High: 0x0102030405060708,
  196. Low: 0x090a0b0c0d0e0f10,
  197. },
  198. ID: 0x1112131415161718,
  199. Sampled: &sampledTrue,
  200. },
  201. Name: "name",
  202. Timestamp: now,
  203. Duration: 24 * time.Hour,
  204. Shared: false,
  205. Tags: map[string]string{
  206. "error": "error code 1234",
  207. },
  208. },
  209. },
  210. }
  211. for _, tt := range tests {
  212. got := zipkinSpan(tt.span, nil)
  213. if len(got.Annotations) != len(tt.want.Annotations) {
  214. t.Fatalf("zipkinSpan: got %d annotations in span, want %d", len(got.Annotations), len(tt.want.Annotations))
  215. }
  216. if !reflect.DeepEqual(got, tt.want) {
  217. t.Errorf("zipkinSpan:\n\tgot %#v\n\twant %#v", got, tt.want)
  218. }
  219. }
  220. for _, tt := range tests {
  221. ch := make(chan []byte)
  222. client := http.Client{
  223. Transport: roundTripper(func(req *http.Request) (*http.Response, error) {
  224. body, _ := ioutil.ReadAll(req.Body)
  225. ch <- body
  226. return &http.Response{StatusCode: 200, Body: ioutil.NopCloser(strings.NewReader(""))}, nil
  227. }),
  228. }
  229. reporter := httpreporter.NewReporter("foo", httpreporter.Client(&client), httpreporter.BatchInterval(time.Millisecond))
  230. exporter := NewExporter(reporter, nil)
  231. exporter.ExportSpan(tt.span)
  232. var data []byte
  233. select {
  234. case data = <-ch:
  235. case <-time.After(2 * time.Second):
  236. t.Fatalf("span was not exported")
  237. }
  238. var spans []model.SpanModel
  239. json.Unmarshal(data, &spans)
  240. if len(spans) != 1 {
  241. t.Fatalf("Export: got %d spans, want 1", len(spans))
  242. }
  243. got := spans[0]
  244. got.SpanContext.Sampled = &sampledTrue // Sampled is not set when the span is reported.
  245. if len(got.Annotations) != len(tt.want.Annotations) {
  246. t.Fatalf("Export: got %d annotations in span, want %d", len(got.Annotations), len(tt.want.Annotations))
  247. }
  248. if !reflect.DeepEqual(got, tt.want) {
  249. t.Errorf("Export:\n\tgot %#v\n\twant %#v", got, tt.want)
  250. }
  251. }
  252. }