client/web: add metric logging logic to the web client (#10434)

Add metric logging logic for the web client frontend. This is an initial
pass of adding the base logic, plus a single point where it is used for
validation that the logging is working correctly. More metric logging
calls will follow in subsquent PRs.

Updates https://github.com/tailscale/tailscale/issues/10261

Signed-off-by: Mario Minardi <mario@tailscale.com>
This commit is contained in:
Mario Minardi
2023-12-05 08:28:19 -07:00
committed by GitHub
parent 9c4b73d77d
commit 6b083a8ddf
3 changed files with 40 additions and 17 deletions

View File

@@ -77,3 +77,30 @@ export function setSynoToken(token?: string) {
export function setUnraidCsrfToken(token?: string) {
unraidCsrfToken = token
}
// incrementMetric hits the client metrics local API endpoint to
// increment the given counter metric by one.
export function incrementMetric(metricName: MetricName) {
const postData : MetricsPOSTData[] = [{
Name: metricName,
Type: "counter",
Value: 1
}]
apiFetch("/local/v0/upload-client-metrics", "POST", postData)
.catch((error) => {
console.error(error)
})
}
type MetricsPOSTData = {
Name: MetricName
Type: MetricType
Value: number
}
type MetricType = "counter" | "gauge"
export type MetricName =
| "web_client_advertise_exitnode_enable"
| "web_client_advertise_exitnode_disable"

View File

@@ -6,6 +6,7 @@ import { apiFetch, setUnraidCsrfToken } from "src/api"
import { ExitNode, noExitNode, runAsExitNode } from "src/hooks/exit-nodes"
import { VersionInfo } from "src/hooks/self-update"
import { assertNever } from "src/util"
import { incrementMetric, MetricName } from "src/api"
export type NodeData = {
Profile: UserProfile
@@ -173,16 +174,25 @@ export default function useNodeData() {
setIsPosting(false)
refreshData() // refresh data after POST finishes
}
const updateMetrics = () => {
// only update metrics if values have changed
if (data?.AdvertisingExitNode !== d.AdvertiseExitNode) {
incrementMetric(d.AdvertiseExitNode ? "web_client_advertise_exitnode_enable" : "web_client_advertise_exitnode_disable")
}
}
return apiFetch("/routes", "POST", d)
.then(onComplete)
.then(() => {
updateMetrics()
onComplete()
})
.catch((err) => {
onComplete()
alert("Failed to update routes")
throw err
})
},
[setIsPosting, refreshData]
[setIsPosting, refreshData, data?.AdvertisingExitNode]
)
useEffect(