client/web: add endpoint for logging device detail click metric (#10505)
Add an endpoint for logging the device detail click metric to allow for this metric to be logged without having a valid session which is the case when in readonly mode. Updates https://github.com/tailscale/tailscale/issues/10261 Signed-off-by: Mario Minardi <mario@tailscale.com>
This commit is contained in:
parent
d8493d4bd5
commit
109929d110
|
@ -369,4 +369,3 @@ export type MetricName =
|
|||
| "web_client_node_connect"
|
||||
| "web_client_node_disconnect"
|
||||
| "web_client_advertise_routes_change"
|
||||
| "web_client_device_details_click"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import cx from "classnames"
|
||||
import React, { useMemo } from "react"
|
||||
import { incrementMetric } from "src/api"
|
||||
import { apiFetch } from "src/api"
|
||||
import { ReactComponent as ArrowRight } from "src/assets/icons/arrow-right.svg"
|
||||
import { ReactComponent as Machine } from "src/assets/icons/machine.svg"
|
||||
import AddressCard from "src/components/address-copy-card"
|
||||
|
@ -68,7 +68,7 @@ export default function HomeView({
|
|||
<Link
|
||||
className="link font-medium"
|
||||
to="/details"
|
||||
onClick={() => incrementMetric("web_client_device_details_click")}
|
||||
onClick={() => apiFetch("/device-details-click", "POST")}
|
||||
>
|
||||
View device details →
|
||||
</Link>
|
||||
|
|
|
@ -336,6 +336,9 @@ func (s *Server) authorizeRequest(w http.ResponseWriter, r *http.Request) (ok bo
|
|||
case r.URL.Path == "/api/data" && r.Method == httpm.GET:
|
||||
// Readonly endpoint allowed without valid browser session.
|
||||
return true
|
||||
case r.URL.Path == "/api/device-details-click" && r.Method == httpm.POST:
|
||||
// Special case metric endpoint that is allowed without a browser session.
|
||||
return true
|
||||
case strings.HasPrefix(r.URL.Path, "/api/"):
|
||||
// All other /api/ endpoints require a valid browser session.
|
||||
if err != nil || !session.isAuthorized(s.timeNow()) {
|
||||
|
@ -371,6 +374,8 @@ func (s *Server) serveLoginAPI(w http.ResponseWriter, r *http.Request) {
|
|||
s.serveGetNodeData(w, r)
|
||||
case r.URL.Path == "/api/up" && r.Method == httpm.POST:
|
||||
s.serveTailscaleUp(w, r)
|
||||
case r.URL.Path == "/api/device-details-click" && r.Method == httpm.POST:
|
||||
s.serveDeviceDetailsClick(w, r)
|
||||
default:
|
||||
http.Error(w, "invalid endpoint or method", http.StatusNotFound)
|
||||
}
|
||||
|
@ -549,6 +554,9 @@ func (s *Server) serveAPI(w http.ResponseWriter, r *http.Request) {
|
|||
case path == "/routes" && r.Method == httpm.POST:
|
||||
s.servePostRoutes(w, r)
|
||||
return
|
||||
case path == "/device-details-click" && r.Method == httpm.POST:
|
||||
s.serveDeviceDetailsClick(w, r)
|
||||
return
|
||||
case strings.HasPrefix(path, "/local/"):
|
||||
s.proxyRequestToLocalAPI(w, r)
|
||||
return
|
||||
|
@ -970,6 +978,21 @@ func (s *Server) serveTailscaleUp(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// serveDeviceDetailsClick increments the web_client_device_details_click metric
|
||||
// by one.
|
||||
//
|
||||
// Metric logging from the frontend typically is proxied to the localapi. This event
|
||||
// has been special cased as access to the localapi is gated upon having a valid
|
||||
// session which is not always the case when we want to be logging this metric (e.g.,
|
||||
// when in readonly mode).
|
||||
//
|
||||
// Other metrics should not be logged in this way without a good reason.
|
||||
func (s *Server) serveDeviceDetailsClick(w http.ResponseWriter, r *http.Request) {
|
||||
s.lc.IncrementCounter(r.Context(), "web_client_device_details_click", 1)
|
||||
|
||||
io.WriteString(w, "{}")
|
||||
}
|
||||
|
||||
// proxyRequestToLocalAPI proxies the web API request to the localapi.
|
||||
//
|
||||
// The web API request path is expected to exactly match a localapi path,
|
||||
|
|
Loading…
Reference in New Issue