Skip to content

Commit bcdb746

Browse files
committed
Metrics: add detailed metrics for selected files
This adds a more detailed metrics category for files served by mirrorbits. These tracked files will detail their downloads per country, but due to the increased number of fields required for this, only files selected through the command line will be tracked. This also adds command line arguments to add, delete, and list the files to monitore closely.
1 parent a2eab78 commit bcdb746

8 files changed

Lines changed: 708 additions & 131 deletions

File tree

cli/commands.go

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,14 @@ func (c *cli) CmdHelp() error {
9999
help += fmt.Sprintf("CLI commands:\n")
100100
for _, command := range [][]string{
101101
{"add", "Add a new mirror"},
102+
{"addMetric", "Add a tracked file to the metrics route"},
102103
{"disable", "Disable a mirror"},
104+
{"delMetric", "Delete a tracked file from the metrics route"},
103105
{"edit", "Edit a mirror"},
104106
{"enable", "Enable a mirror"},
105107
{"export", "Export the mirror database"},
106108
{"list", "List all mirrors"},
109+
{"listMetrics", "List all tracked files from the metrics route"},
107110
{"logs", "Print logs of a mirror"},
108111
{"refresh", "Refresh the local repository"},
109112
{"reload", "Reload configuration"},
@@ -114,7 +117,7 @@ func (c *cli) CmdHelp() error {
114117
{"upgrade", "Seamless binary upgrade"},
115118
{"version", "Print version information"},
116119
} {
117-
help += fmt.Sprintf(" %-10.10s%s\n", command[0], command[1])
120+
help += fmt.Sprintf(" %-15.15s%s\n", command[0], command[1])
118121
}
119122
fmt.Fprintf(os.Stderr, "%s\n", help)
120123
return nil
@@ -349,6 +352,98 @@ func (c *cli) CmdAdd(args ...string) error {
349352
return nil
350353
}
351354

355+
func (c *cli) CmdAddmetric(args ...string) error {
356+
cmd := SubCmd("addMetric", "FILE_PATH", "Add a file to the metrics route")
357+
358+
if err := cmd.Parse(args); err != nil {
359+
return nil
360+
}
361+
if cmd.NArg() != 1 {
362+
cmd.Usage()
363+
return nil
364+
}
365+
file := cmd.Arg(0)
366+
367+
client := c.GetRPC()
368+
ctx, cancel := context.WithTimeout(context.Background(), defaultRPCTimeout)
369+
defer cancel()
370+
_, err := client.AddMetric(ctx, &rpc.Metric{
371+
Filename: string(file),
372+
})
373+
if err != nil {
374+
log.Fatal("Error while adding metric: ", err)
375+
}
376+
377+
log.Info("File ", file, " successfully added to metrics.")
378+
return nil
379+
}
380+
381+
func (c *cli) CmdDelmetric(args ...string) error {
382+
cmd := SubCmd("delMetric", "FILE_PATH", "Delete a file from the metrics route")
383+
384+
if err := cmd.Parse(args); err != nil {
385+
return nil
386+
}
387+
if cmd.NArg() != 1 {
388+
cmd.Usage()
389+
return nil
390+
}
391+
file := cmd.Arg(0)
392+
393+
client := c.GetRPC()
394+
ctx, cancel := context.WithTimeout(context.Background(), defaultRPCTimeout)
395+
defer cancel()
396+
_, err := client.DelMetric(ctx, &rpc.Metric{
397+
Filename: string(file),
398+
})
399+
if err != nil {
400+
log.Fatal("Error while deleting metric: ", err)
401+
}
402+
403+
log.Info("File ", file, " successfully deleted from metrics.")
404+
return nil
405+
}
406+
407+
func (c *cli) CmdListmetrics(args ...string) error {
408+
cmd := SubCmd("listMetrics", "[OPTIONNAL FILTER PATTERN]", "Optionnal pattern to filter results")
409+
410+
filterPattern := "*"
411+
if err := cmd.Parse(args); err != nil {
412+
return nil
413+
}
414+
nArg := cmd.NArg()
415+
if nArg > 1 {
416+
cmd.Usage()
417+
return nil
418+
} else if nArg == 1 {
419+
filterPattern = "*" + cmd.Arg(0) + "*"
420+
}
421+
422+
client := c.GetRPC()
423+
ctx, cancel := context.WithTimeout(context.Background(), defaultRPCTimeout)
424+
defer cancel()
425+
fileList, err := client.ListMetrics(ctx, &rpc.Metric{
426+
Filename: string(filterPattern),
427+
})
428+
if err != nil {
429+
log.Fatal("Error while listing metrics: ", err)
430+
}
431+
432+
if len(fileList.Filename) == 0 {
433+
if nArg == 1 {
434+
log.Info("There are no tracked files matching your request.")
435+
} else {
436+
log.Info("There are no tracked files.")
437+
}
438+
} else {
439+
for _, file := range fileList.Filename {
440+
log.Info(file)
441+
}
442+
}
443+
444+
return nil
445+
}
446+
352447
func (c *cli) CmdRemove(args ...string) error {
353448
cmd := SubCmd("remove", "IDENTIFIER", "Remove an existing mirror")
354449
force := cmd.Bool("f", false, "Never prompt for confirmation")

database/utils.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,43 @@ func (r *Redis) GetListOfFiles() ([]string, error) {
6565
return files, nil
6666
}
6767

68+
func (r *Redis) IsFileTracked(file string) (bool, error) {
69+
trackedFileList, err := r.GetListOfTrackedFiles()
70+
if err != nil {
71+
return false, nil
72+
}
73+
for _, v := range trackedFileList {
74+
if v == file {
75+
return true, nil
76+
}
77+
}
78+
return false, nil
79+
}
80+
81+
func (r *Redis) GetListOfTrackedFiles() ([]string, error) {
82+
conn, err := r.Connect()
83+
if err != nil {
84+
return nil, err
85+
}
86+
defer conn.Close()
87+
88+
values, err := redis.Values(conn.Do("SMEMBERS", "TRACKED_FILES"))
89+
if err != nil {
90+
return nil, err
91+
}
92+
93+
files := make([]string, len(values))
94+
for i, v := range values {
95+
value, okValue := v.([]byte)
96+
if !okValue {
97+
return nil, errors.New("invalid type for file")
98+
}
99+
files[i] = string(value)
100+
}
101+
102+
return files, nil
103+
}
104+
68105
func (r *Redis) GetListOfCountries() ([]string, error) {
69106
conn, err := r.Connect()
70107
if err != nil {
@@ -89,6 +126,30 @@ func (r *Redis) GetListOfCountries() ([]string, error) {
89126
return files, nil
90127
}
91128

129+
func (r *Redis) GetListOfTrackFilesFields(file string) ([]string, error) {
130+
conn, err := r.Connect()
131+
if err != nil {
132+
return nil, err
133+
}
134+
defer conn.Close()
135+
136+
values, err := redis.Values(conn.Do("HKEYS", "STATS_TRACKED_"+file))
137+
if err != nil {
138+
return nil, err
139+
}
140+
141+
files := make([]string, len(values))
142+
for i, v := range values {
143+
value, okValue := v.([]byte)
144+
if !okValue {
145+
return nil, errors.New("invalid type for file")
146+
}
147+
files[i] = string(value)
148+
}
149+
150+
return files, nil
151+
}
152+
92153
func (r *Redis) AddCountry(country string) error {
93154
conn, err := r.Connect()
94155
if err != nil {

http/http.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,15 @@ func (h *HTTP) mirrorHandler(w http.ResponseWriter, r *http.Request, ctx *Contex
331331
http.Error(w, err.Error(), status)
332332
}
333333

334+
isTracked, err := h.redis.IsFileTracked(fileInfo.Path)
335+
if err != nil {
336+
log.Error("There was a problem fetching the tracked file list: ", err)
337+
}
338+
334339
if !ctx.IsMirrorlist() {
335340
logs.LogDownload(resultRenderer.Type(), status, results, err)
336341
if len(mlist) > 0 {
337-
h.stats.CountDownload(mlist[0], fileInfo, clientInfo)
342+
h.stats.CountDownload(mlist[0], fileInfo, clientInfo, isTracked)
338343
}
339344
}
340345

0 commit comments

Comments
 (0)