You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

170 lines
5.0 KiB

  1. // Copyright 2018, 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 ochttp
  15. import (
  16. "crypto/tls"
  17. "net/http"
  18. "net/http/httptrace"
  19. "strings"
  20. "go.opencensus.io/trace"
  21. )
  22. type spanAnnotator struct {
  23. sp *trace.Span
  24. }
  25. // TODO: Remove NewSpanAnnotator at the next release.
  26. // NewSpanAnnotator returns a httptrace.ClientTrace which annotates
  27. // all emitted httptrace events on the provided Span.
  28. // Deprecated: Use NewSpanAnnotatingClientTrace instead
  29. func NewSpanAnnotator(r *http.Request, s *trace.Span) *httptrace.ClientTrace {
  30. return NewSpanAnnotatingClientTrace(r, s)
  31. }
  32. // NewSpanAnnotatingClientTrace returns a httptrace.ClientTrace which annotates
  33. // all emitted httptrace events on the provided Span.
  34. func NewSpanAnnotatingClientTrace(_ *http.Request, s *trace.Span) *httptrace.ClientTrace {
  35. sa := spanAnnotator{sp: s}
  36. return &httptrace.ClientTrace{
  37. GetConn: sa.getConn,
  38. GotConn: sa.gotConn,
  39. PutIdleConn: sa.putIdleConn,
  40. GotFirstResponseByte: sa.gotFirstResponseByte,
  41. Got100Continue: sa.got100Continue,
  42. DNSStart: sa.dnsStart,
  43. DNSDone: sa.dnsDone,
  44. ConnectStart: sa.connectStart,
  45. ConnectDone: sa.connectDone,
  46. TLSHandshakeStart: sa.tlsHandshakeStart,
  47. TLSHandshakeDone: sa.tlsHandshakeDone,
  48. WroteHeaders: sa.wroteHeaders,
  49. Wait100Continue: sa.wait100Continue,
  50. WroteRequest: sa.wroteRequest,
  51. }
  52. }
  53. func (s spanAnnotator) getConn(hostPort string) {
  54. attrs := []trace.Attribute{
  55. trace.StringAttribute("httptrace.get_connection.host_port", hostPort),
  56. }
  57. s.sp.Annotate(attrs, "GetConn")
  58. }
  59. func (s spanAnnotator) gotConn(info httptrace.GotConnInfo) {
  60. attrs := []trace.Attribute{
  61. trace.BoolAttribute("httptrace.got_connection.reused", info.Reused),
  62. trace.BoolAttribute("httptrace.got_connection.was_idle", info.WasIdle),
  63. }
  64. if info.WasIdle {
  65. attrs = append(attrs,
  66. trace.StringAttribute("httptrace.got_connection.idle_time", info.IdleTime.String()))
  67. }
  68. s.sp.Annotate(attrs, "GotConn")
  69. }
  70. // PutIdleConn implements a httptrace.ClientTrace hook
  71. func (s spanAnnotator) putIdleConn(err error) {
  72. var attrs []trace.Attribute
  73. if err != nil {
  74. attrs = append(attrs,
  75. trace.StringAttribute("httptrace.put_idle_connection.error", err.Error()))
  76. }
  77. s.sp.Annotate(attrs, "PutIdleConn")
  78. }
  79. func (s spanAnnotator) gotFirstResponseByte() {
  80. s.sp.Annotate(nil, "GotFirstResponseByte")
  81. }
  82. func (s spanAnnotator) got100Continue() {
  83. s.sp.Annotate(nil, "Got100Continue")
  84. }
  85. func (s spanAnnotator) dnsStart(info httptrace.DNSStartInfo) {
  86. attrs := []trace.Attribute{
  87. trace.StringAttribute("httptrace.dns_start.host", info.Host),
  88. }
  89. s.sp.Annotate(attrs, "DNSStart")
  90. }
  91. func (s spanAnnotator) dnsDone(info httptrace.DNSDoneInfo) {
  92. var addrs []string
  93. for _, addr := range info.Addrs {
  94. addrs = append(addrs, addr.String())
  95. }
  96. attrs := []trace.Attribute{
  97. trace.StringAttribute("httptrace.dns_done.addrs", strings.Join(addrs, " , ")),
  98. }
  99. if info.Err != nil {
  100. attrs = append(attrs,
  101. trace.StringAttribute("httptrace.dns_done.error", info.Err.Error()))
  102. }
  103. s.sp.Annotate(attrs, "DNSDone")
  104. }
  105. func (s spanAnnotator) connectStart(network, addr string) {
  106. attrs := []trace.Attribute{
  107. trace.StringAttribute("httptrace.connect_start.network", network),
  108. trace.StringAttribute("httptrace.connect_start.addr", addr),
  109. }
  110. s.sp.Annotate(attrs, "ConnectStart")
  111. }
  112. func (s spanAnnotator) connectDone(network, addr string, err error) {
  113. attrs := []trace.Attribute{
  114. trace.StringAttribute("httptrace.connect_done.network", network),
  115. trace.StringAttribute("httptrace.connect_done.addr", addr),
  116. }
  117. if err != nil {
  118. attrs = append(attrs,
  119. trace.StringAttribute("httptrace.connect_done.error", err.Error()))
  120. }
  121. s.sp.Annotate(attrs, "ConnectDone")
  122. }
  123. func (s spanAnnotator) tlsHandshakeStart() {
  124. s.sp.Annotate(nil, "TLSHandshakeStart")
  125. }
  126. func (s spanAnnotator) tlsHandshakeDone(_ tls.ConnectionState, err error) {
  127. var attrs []trace.Attribute
  128. if err != nil {
  129. attrs = append(attrs,
  130. trace.StringAttribute("httptrace.tls_handshake_done.error", err.Error()))
  131. }
  132. s.sp.Annotate(attrs, "TLSHandshakeDone")
  133. }
  134. func (s spanAnnotator) wroteHeaders() {
  135. s.sp.Annotate(nil, "WroteHeaders")
  136. }
  137. func (s spanAnnotator) wait100Continue() {
  138. s.sp.Annotate(nil, "Wait100Continue")
  139. }
  140. func (s spanAnnotator) wroteRequest(info httptrace.WroteRequestInfo) {
  141. var attrs []trace.Attribute
  142. if info.Err != nil {
  143. attrs = append(attrs,
  144. trace.StringAttribute("httptrace.wrote_request.error", info.Err.Error()))
  145. }
  146. s.sp.Annotate(attrs, "WroteRequest")
  147. }