-
Notifications
You must be signed in to change notification settings - Fork 547
Add documentation for metrics endpoint #816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
_build/ | ||
_deployed | ||
_deployed.old | ||
_syncthing |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
// Copyright (C) 2023 The Syncthing Authors. | ||
// | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
// You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
// Usage: go run script/find-metrics.go > metrics.md | ||
// | ||
// This script finds all of the metrics in the Syncthing codebase and prints | ||
// them in Markdown format. It's used to generate the metrics documentation | ||
// for the Syncthing docs. | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"go/ast" | ||
"go/token" | ||
"log" | ||
"os" | ||
"strconv" | ||
"strings" | ||
|
||
"golang.org/x/exp/slices" | ||
"golang.org/x/tools/go/packages" | ||
) | ||
|
||
type metric struct { | ||
subsystem string | ||
name string | ||
help string | ||
kind string | ||
} | ||
|
||
func main() { | ||
flag.Parse() | ||
if flag.NArg() != 1 { | ||
fmt.Println("Usage: find-metrics <path>") | ||
os.Exit(1) | ||
} | ||
|
||
opts := &packages.Config{ | ||
Dir: flag.Arg(0), | ||
Mode: packages.NeedSyntax | packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedDeps, | ||
} | ||
|
||
pkgs, err := packages.Load(opts, "github.com/syncthing/syncthing/...") | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
var coll metricCollector | ||
for _, pkg := range pkgs { | ||
for _, file := range pkg.Syntax { | ||
ast.Inspect(file, coll.Visit) | ||
} | ||
} | ||
coll.print() | ||
} | ||
|
||
type metricCollector struct { | ||
metrics []metric | ||
} | ||
|
||
func (c *metricCollector) Visit(n ast.Node) bool { | ||
if gen, ok := n.(*ast.GenDecl); ok { | ||
// We're only interested in var declarations (var metricWhatever = | ||
// promauto.NewCounter(...) etc). | ||
if gen.Tok != token.VAR { | ||
return false | ||
} | ||
|
||
for _, spec := range gen.Specs { | ||
// We want to look at the value given to a var (the NewCounter() | ||
// etc call). | ||
if vsp, ok := spec.(*ast.ValueSpec); ok { | ||
// There should be only one value. | ||
if len(vsp.Values) != 1 { | ||
continue | ||
} | ||
|
||
// The value should be a function call. | ||
call, ok := vsp.Values[0].(*ast.CallExpr) | ||
if !ok { | ||
continue | ||
} | ||
|
||
// The call should be a selector expression | ||
// (package.Identifer). | ||
sel, ok := call.Fun.(*ast.SelectorExpr) | ||
if !ok { | ||
continue | ||
} | ||
|
||
// The package selector should be `promauto`. | ||
selID, ok := sel.X.(*ast.Ident) | ||
if !ok || selID.Name != "promauto" { | ||
continue | ||
} | ||
|
||
// The function should be one of the New* functions. | ||
var kind string | ||
switch sel.Sel.Name { | ||
case "NewCounter": | ||
kind = "counter" | ||
case "NewGauge": | ||
kind = "gauge" | ||
case "NewCounterVec": | ||
kind = "counter vector" | ||
case "NewGaugeVec": | ||
kind = "gauge vector" | ||
default: | ||
continue | ||
} | ||
|
||
// The arguments to the function should be a single | ||
// composite (struct literal). Grab all of the fields in the | ||
// declaration into a map so we can easily access them. | ||
args := make(map[string]string) | ||
for _, el := range call.Args[0].(*ast.CompositeLit).Elts { | ||
kv := el.(*ast.KeyValueExpr) | ||
key := kv.Key.(*ast.Ident).Name // e.g., "Name" | ||
val := kv.Value.(*ast.BasicLit).Value // e.g., `"foo"` | ||
args[key], _ = strconv.Unquote(val) | ||
} | ||
|
||
// Build the full name of the metric from the namespace + | ||
// subsystem + name, like Prometheus does. | ||
var parts []string | ||
if v := args["Namespace"]; v != "" { | ||
parts = append(parts, v) | ||
} | ||
if v := args["Subsystem"]; v != "" { | ||
parts = append(parts, v) | ||
} | ||
if v := args["Name"]; v != "" { | ||
parts = append(parts, v) | ||
} | ||
fullName := strings.Join(parts, "_") | ||
|
||
// Add the metric to the list. | ||
c.metrics = append(c.metrics, metric{ | ||
subsystem: args["Subsystem"], | ||
name: fullName, | ||
help: args["Help"], | ||
kind: kind, | ||
}) | ||
} | ||
} | ||
} | ||
return true | ||
} | ||
|
||
func (c *metricCollector) print() { | ||
slices.SortFunc(c.metrics, func(a, b metric) int { | ||
if a.subsystem != b.subsystem { | ||
return strings.Compare(a.subsystem, b.subsystem) | ||
} | ||
return strings.Compare(a.name, b.name) | ||
}) | ||
|
||
var prevSubsystem string | ||
for _, m := range c.metrics { | ||
if m.subsystem != prevSubsystem { | ||
fmt.Println(header(fmt.Sprintf("Package *%s*", m.subsystem), "~")) | ||
prevSubsystem = m.subsystem | ||
} | ||
fmt.Println(header(fmt.Sprintf("Metric *%v* (%s)", m.name, m.kind), "^")) | ||
fmt.Println(wordwrap(sentenceize(m.help), 72)) | ||
fmt.Println() | ||
} | ||
} | ||
|
||
func header(header, underline string) string { | ||
under := strings.Repeat(underline, len(header)) | ||
return fmt.Sprintf("%s\n%s\n", header, under) | ||
} | ||
|
||
func sentenceize(s string) string { | ||
if s == "" { | ||
return "" | ||
} | ||
if !strings.HasSuffix(s, ".") { | ||
return s + "." | ||
} | ||
return s | ||
} | ||
|
||
func wordwrap(s string, width int) string { | ||
var lines []string | ||
for _, line := range strings.Split(s, "\n") { | ||
for len(line) > width { | ||
i := strings.LastIndex(line[:width], " ") | ||
if i == -1 { | ||
i = width | ||
} | ||
lines = append(lines, line[:i]) | ||
line = line[i+1:] | ||
} | ||
lines = append(lines, line) | ||
} | ||
return strings.Join(lines, "\n") | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
.. _rest: | ||
|
||
REST API | ||
======== | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
Package *events* | ||
~~~~~~~~~~~~~~~~ | ||
|
||
Metric *syncthing_events_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of created/forwarded/dropped events. | ||
|
||
Package *fs* | ||
~~~~~~~~~~~~ | ||
|
||
Metric *syncthing_fs_operation_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of filesystem bytes transferred, per filesystem root and | ||
operation. | ||
|
||
Metric *syncthing_fs_operation_seconds_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total time spent in filesystem operations, per filesystem root and | ||
operation. | ||
|
||
Metric *syncthing_fs_operations_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of filesystem operations, per filesystem root and | ||
operation. | ||
|
||
Package *model* | ||
~~~~~~~~~~~~~~~ | ||
|
||
Metric *syncthing_model_folder_processed_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total amount of data processed during folder syncing, per folder ID and | ||
data source (network/local_origin/local_other/local_shifted/skipped). | ||
|
||
Metric *syncthing_model_folder_pull_seconds_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total time spent in folder pull iterations, per folder ID. | ||
|
||
Metric *syncthing_model_folder_pulls_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of folder pull iterations, per folder ID. | ||
|
||
Metric *syncthing_model_folder_scan_seconds_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total time spent in folder scan iterations, per folder ID. | ||
|
||
Metric *syncthing_model_folder_scans_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of folder scan iterations, per folder ID. | ||
|
||
Metric *syncthing_model_folder_state* (gauge vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Current folder state. | ||
|
||
Metric *syncthing_model_folder_summary* (gauge vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Current folder summary data (counts for global/local/need | ||
files/directories/symlinks/deleted/bytes). | ||
|
||
Package *protocol* | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
Metric *syncthing_protocol_recv_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total amount of data received, per device. | ||
|
||
Metric *syncthing_protocol_recv_decompressed_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total amount of data received, after decompression, per device. | ||
|
||
Metric *syncthing_protocol_recv_messages_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of messages received, per device. | ||
|
||
Metric *syncthing_protocol_sent_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total amount of data sent, per device. | ||
|
||
Metric *syncthing_protocol_sent_messages_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of messages sent, per device. | ||
|
||
Metric *syncthing_protocol_sent_uncompressed_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total amount of data sent, before compression, per device. | ||
|
||
Package *scanner* | ||
~~~~~~~~~~~~~~~~~ | ||
|
||
Metric *syncthing_scanner_hashed_bytes_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total amount of data hashed, per folder. | ||
|
||
Metric *syncthing_scanner_scanned_items_total* (counter vector) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Total number of items (files/directories) inspected, per folder. | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/bin/sh | ||
set -euo pipefail | ||
|
||
rm -rf _syncthing | ||
git clone --depth 1 https://github.com/syncthing/syncthing.git _syncthing | ||
pushd _script | ||
go run ./find-metrics ../_syncthing > ../includes/metrics-list.rst | ||
popd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ Usage | |
guilisten | ||
ldap | ||
tuning | ||
metrics | ||
|
||
syncing | ||
untrusted | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.