client/web: allow providing logger implementation

Also report metrics in separate go routine with a 5 second timeout.

Updates tailscale/corp#14335

Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
pull/9987/head
Sonia Appasamy 1 year ago committed by Sonia Appasamy
parent 95715c4a12
commit 93aa8a8cff

@ -32,12 +32,14 @@ import (
"tailscale.com/licenses" "tailscale.com/licenses"
"tailscale.com/net/netutil" "tailscale.com/net/netutil"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/logger"
"tailscale.com/util/httpm" "tailscale.com/util/httpm"
"tailscale.com/version/distro" "tailscale.com/version/distro"
) )
// Server is the backend server for a Tailscale web client. // Server is the backend server for a Tailscale web client.
type Server struct { type Server struct {
logf logger.Logf
lc *tailscale.LocalClient lc *tailscale.LocalClient
timeNow func() time.Time timeNow func() time.Time
@ -136,6 +138,8 @@ type ServerOpts struct {
// TimeNow optionally provides a time function. // TimeNow optionally provides a time function.
// time.Now is used as default. // time.Now is used as default.
TimeNow func() time.Time TimeNow func() time.Time
Logf logger.Logf
} }
// NewServer constructs a new Tailscale web client server. // NewServer constructs a new Tailscale web client server.
@ -144,6 +148,7 @@ func NewServer(opts ServerOpts) (s *Server, cleanup func()) {
opts.LocalClient = &tailscale.LocalClient{} opts.LocalClient = &tailscale.LocalClient{}
} }
s = &Server{ s = &Server{
logf: opts.Logf,
devMode: opts.DevMode, devMode: opts.DevMode,
lc: opts.LocalClient, lc: opts.LocalClient,
cgiMode: opts.CGIMode, cgiMode: opts.CGIMode,
@ -153,9 +158,14 @@ func NewServer(opts ServerOpts) (s *Server, cleanup func()) {
if s.timeNow == nil { if s.timeNow == nil {
s.timeNow = time.Now s.timeNow = time.Now
} }
if s.logf == nil {
s.logf = log.Printf
}
s.tsDebugMode = s.debugMode() s.tsDebugMode = s.debugMode()
s.assetsHandler, cleanup = assetsHandler(opts.DevMode) s.assetsHandler, cleanup = assetsHandler(opts.DevMode)
var metric string // clientmetric to report on startup
// Create handler for "/api" requests with CSRF protection. // Create handler for "/api" requests with CSRF protection.
// We don't require secure cookies, since the web client is regularly used // We don't require secure cookies, since the web client is regularly used
// on network appliances that are served on local non-https URLs. // on network appliances that are served on local non-https URLs.
@ -166,12 +176,19 @@ func NewServer(opts ServerOpts) (s *Server, cleanup func()) {
// For the login client, we don't serve the full web client API, // For the login client, we don't serve the full web client API,
// only the login endpoints. // only the login endpoints.
s.apiHandler = csrfProtect(http.HandlerFunc(s.serveLoginAPI)) s.apiHandler = csrfProtect(http.HandlerFunc(s.serveLoginAPI))
s.lc.IncrementCounter(context.Background(), "web_login_client_initialization", 1) metric = "web_login_client_initialization"
} else { } else {
s.apiHandler = csrfProtect(http.HandlerFunc(s.serveAPI)) s.apiHandler = csrfProtect(http.HandlerFunc(s.serveAPI))
s.lc.IncrementCounter(context.Background(), "web_client_initialization", 1) metric = "web_client_initialization"
} }
// Report metric in separate go routine with 5 second timeout.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
go func() {
defer cancel()
s.lc.IncrementCounter(ctx, metric, 1)
}()
return s, cleanup return s, cleanup
} }
@ -645,7 +662,7 @@ func (s *Server) servePostNodeUpdate(w http.ResponseWriter, r *http.Request) {
} }
mp.Prefs.WantRunning = true mp.Prefs.WantRunning = true
mp.Prefs.AdvertiseRoutes = routes mp.Prefs.AdvertiseRoutes = routes
log.Printf("Doing edit: %v", mp.Pretty()) s.logf("Doing edit: %v", mp.Pretty())
if _, err := s.lc.EditPrefs(r.Context(), mp); err != nil { if _, err := s.lc.EditPrefs(r.Context(), mp); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
@ -661,9 +678,9 @@ func (s *Server) servePostNodeUpdate(w http.ResponseWriter, r *http.Request) {
if postData.ForceLogout { if postData.ForceLogout {
logout = true logout = true
} }
log.Printf("tailscaleUp(reauth=%v, logout=%v) ...", reauth, logout) s.logf("tailscaleUp(reauth=%v, logout=%v) ...", reauth, logout)
url, err := s.tailscaleUp(r.Context(), st, postData) url, err := s.tailscaleUp(r.Context(), st, postData)
log.Printf("tailscaleUp = (URL %v, %v)", url != "", err) s.logf("tailscaleUp = (URL %v, %v)", url != "", err)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(mi{"error": err.Error()}) json.NewEncoder(w).Encode(mi{"error": err.Error()})

Loading…
Cancel
Save