1
1
use anyhow:: Result ;
2
- use http:: HeaderMap ;
2
+ use http:: { HeaderMap , Uri } ;
3
3
use reqwest:: Client ;
4
4
use spin_core:: async_trait;
5
5
use spin_outbound_networking:: { AllowedHostsConfig , OutboundUrl } ;
6
6
use spin_world:: v1:: {
7
7
http as outbound_http,
8
8
http_types:: { Headers , HttpError , Method , Request , Response } ,
9
9
} ;
10
+ use tracing:: { field:: Empty , instrument, Level } ;
10
11
11
12
/// A very simple implementation for outbound HTTP requests.
12
13
#[ derive( Default , Clone ) ]
@@ -38,8 +39,28 @@ impl OutboundHttp {
38
39
39
40
#[ async_trait]
40
41
impl outbound_http:: Host for OutboundHttp {
42
+ #[ instrument( name = "spin_outbound_http.send_request" , skip_all, err( level = Level :: INFO ) ,
43
+ fields( otel. kind = "client" , url. full = Empty , http. request. method = Empty ,
44
+ http. response. status_code = Empty , otel. name = Empty , server. address = Empty , server. port = Empty ) ) ]
41
45
async fn send_request ( & mut self , req : Request ) -> Result < Result < Response , HttpError > > {
42
46
Ok ( async {
47
+ let current_span = tracing:: Span :: current ( ) ;
48
+ let method = format ! ( "{:?}" , req. method)
49
+ . strip_prefix ( "Method::" )
50
+ . unwrap_or ( "_OTHER" )
51
+ . to_uppercase ( ) ;
52
+ current_span. record ( "otel.name" , method. clone ( ) ) ;
53
+ current_span. record ( "url.full" , req. uri . clone ( ) ) ;
54
+ current_span. record ( "http.request.method" , method) ;
55
+ if let Ok ( uri) = req. uri . parse :: < Uri > ( ) {
56
+ if let Some ( authority) = uri. authority ( ) {
57
+ current_span. record ( "server.address" , authority. host ( ) ) ;
58
+ if let Some ( port) = authority. port ( ) {
59
+ current_span. record ( "server.port" , port. as_u16 ( ) ) ;
60
+ }
61
+ }
62
+ }
63
+
43
64
tracing:: log:: trace!( "Attempting to send outbound HTTP request to {}" , req. uri) ;
44
65
if !self
45
66
. is_allowed ( & req. uri )
@@ -63,7 +84,8 @@ impl outbound_http::Host for OutboundHttp {
63
84
64
85
let req_url = reqwest:: Url :: parse ( & abs_url) . map_err ( |_| HttpError :: InvalidUrl ) ?;
65
86
66
- let headers = request_headers ( req. headers ) . map_err ( |_| HttpError :: RuntimeError ) ?;
87
+ let mut headers = request_headers ( req. headers ) . map_err ( |_| HttpError :: RuntimeError ) ?;
88
+ spin_telemetry:: inject_trace_context ( & mut headers) ;
67
89
let body = req. body . unwrap_or_default ( ) . to_vec ( ) ;
68
90
69
91
if !req. params . is_empty ( ) {
@@ -82,6 +104,7 @@ impl outbound_http::Host for OutboundHttp {
82
104
. await
83
105
. map_err ( log_reqwest_error) ?;
84
106
tracing:: log:: trace!( "Returning response from outbound request to {}" , req. uri) ;
107
+ current_span. record ( "http.response.status_code" , resp. status ( ) . as_u16 ( ) ) ;
85
108
response_from_reqwest ( resp) . await
86
109
}
87
110
. await )
0 commit comments