@@ -8,12 +8,12 @@ import (
88 "io"
99 "net"
1010 "net/http"
11+ "os"
12+ "path/filepath"
1113 "strings"
1214 "sync"
1315 "time"
1416
15- "path/filepath"
16-
1717 "github.com/fnproject/fn/api/agent/drivers"
1818 dockerdriver "github.com/fnproject/fn/api/agent/drivers/docker"
1919 "github.com/fnproject/fn/api/common"
@@ -23,9 +23,10 @@ import (
2323 "github.com/fsnotify/fsnotify"
2424 docker "github.com/fsouza/go-dockerclient"
2525 "github.com/sirupsen/logrus"
26+ "go.opencensus.io/plugin/ochttp"
2627 "go.opencensus.io/stats"
2728 "go.opencensus.io/trace"
28- "os "
29+ "go.opencensus.io/trace/propagation "
2930)
3031
3132const (
@@ -630,7 +631,17 @@ func (s *hotSlot) dispatch(ctx context.Context, call *call) error {
630631 swapBack := s .container .swap (call .stderr , & call .Stats )
631632 defer swapBack ()
632633
633- resp , err := s .container .udsClient .Do (createUDSRequest (ctx , call ))
634+ req := createUDSRequest (ctx , call )
635+
636+ var resp * http.Response
637+ var err error
638+ { // don't leak ctx scope
639+ ctx , span := trace .StartSpan (ctx , "agent_dispatch_uds_do" )
640+ req = req .WithContext (ctx )
641+ resp , err = s .container .udsClient .Do (req )
642+ span .End ()
643+ }
644+
634645 if err != nil {
635646 // IMPORTANT: Container contract: If http-uds errors/timeout, container cannot continue
636647 s .trySetError (err )
@@ -1170,6 +1181,17 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf
11701181 bufs = append (bufs , buf1 )
11711182 }
11721183
1184+ baseTransport := & http.Transport {
1185+ MaxIdleConns : 1 ,
1186+ MaxIdleConnsPerHost : 1 ,
1187+ MaxResponseHeaderBytes : int64 (cfg .MaxHdrResponseSize ),
1188+ IdleConnTimeout : 120 * time .Second , // TODO(reed): since we only allow one, and we close them, this is gratuitous?
1189+ DialContext : func (ctx context.Context , _ , _ string ) (net.Conn , error ) {
1190+ var d net.Dialer
1191+ return d .DialContext (ctx , "unix" , filepath .Join (iofs .AgentPath (), udsFilename ))
1192+ },
1193+ }
1194+
11731195 return & container {
11741196 id : id , // XXX we could just let docker generate ids...
11751197 image : call .Image ,
@@ -1191,16 +1213,12 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf
11911213 },
11921214 stderr : stderr ,
11931215 udsClient : http.Client {
1194- Transport : & http.Transport {
1195- MaxIdleConns : 1 ,
1196- MaxIdleConnsPerHost : 1 ,
1197- MaxResponseHeaderBytes : int64 (cfg .MaxHdrResponseSize ),
1198- // XXX(reed): other settings ?
1199- IdleConnTimeout : 1 * time .Second ,
1200- DialContext : func (ctx context.Context , _ , _ string ) (net.Conn , error ) {
1201- var d net.Dialer
1202- return d .DialContext (ctx , "unix" , filepath .Join (iofs .AgentPath (), udsFilename ))
1203- },
1216+ // use this transport so we can trace the requests to container, handy for debugging...
1217+ Transport : & ochttp.Transport {
1218+ NewClientTrace : ochttp .NewSpanAnnotatingClientTrace ,
1219+ Propagation : noopOCHTTPFormat {}, // we do NOT want to send our tracers to user function, they default to b3
1220+ Base : baseTransport ,
1221+ // NOTE: the global trace sampler will be used, this is what we want for now at least
12041222 },
12051223 },
12061224 evictor : evictor ,
@@ -1212,10 +1230,23 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf
12121230 if err := iofs .Close (); err != nil {
12131231 logger .WithError (err ).Error ("Error closing IOFS" )
12141232 }
1233+ baseTransport .CloseIdleConnections ()
12151234 },
12161235 }
12171236}
12181237
1238+ var _ propagation.HTTPFormat = noopOCHTTPFormat {}
1239+
1240+ // we do not want to pass these to the user functions, since they're our internal traces...
1241+ // it is useful for debugging, admittedly, we could make it more friendly for OSS debugging...
1242+ type noopOCHTTPFormat struct {}
1243+
1244+ func (noopOCHTTPFormat ) SpanContextFromRequest (req * http.Request ) (sc trace.SpanContext , ok bool ) {
1245+ // our transport isn't receiving requests anyway
1246+ return trace.SpanContext {}, false
1247+ }
1248+ func (noopOCHTTPFormat ) SpanContextToRequest (sc trace.SpanContext , req * http.Request ) {}
1249+
12191250func (c * container ) swap (stderr io.Writer , cs * drivers.Stats ) func () {
12201251 // if they aren't using a ghost writer, the logs are disabled, we can skip swapping
12211252 gw , ok := c .stderr .(common.GhostWriter )
0 commit comments