lib/discovery: Export information on advertisements and scans.
- The discovery implementation exports all the AdInfos being advertised
- The BLE plugin exports the set of devices it has scanned
(Temporarily, I'm going to try to move this up to the discovery
implementation instead)
Change-Id: I8e9f5ffdf80f4191d3e9c24a893e71f5e6267b11
diff --git a/lib/discovery/advertise.go b/lib/discovery/advertise.go
index 342c614..8b20b50 100644
--- a/lib/discovery/advertise.go
+++ b/lib/discovery/advertise.go
@@ -5,12 +5,15 @@
package discovery
import (
+ "fmt"
"sync"
"time"
"v.io/v23/context"
"v.io/v23/discovery"
+ "v.io/v23/naming"
"v.io/v23/security"
+ "v.io/x/ref/lib/stats"
)
const (
@@ -114,6 +117,8 @@
}
func (d *idiscovery) startAdvertising(ctx *context.T, adinfo *AdInfo) (func(), error) {
+ statName := naming.Join(d.statsPrefix, "ad", adinfo.Ad.Id.String())
+ stats.NewStringFunc(statName, func() string { return fmt.Sprint(*adinfo) })
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
for _, plugin := range d.plugins {
@@ -124,6 +129,7 @@
}
stop := func() {
+ stats.Delete(statName)
cancel()
wg.Wait()
}
diff --git a/lib/discovery/discovery.go b/lib/discovery/discovery.go
index 1c024f4..81a2192 100644
--- a/lib/discovery/discovery.go
+++ b/lib/discovery/discovery.go
@@ -5,10 +5,12 @@
package discovery
import (
+ "fmt"
"sync"
"v.io/v23/context"
"v.io/v23/discovery"
+ "v.io/v23/naming"
)
type idiscovery struct {
@@ -26,8 +28,15 @@
adStopTrigger *Trigger
dirServer *dirServer
+
+ statsPrefix string
}
+var (
+ statsMu sync.Mutex
+ statsIdx int
+)
+
type sessionId uint64
type adSubtask struct {
@@ -91,12 +100,17 @@
if len(plugins) == 0 {
return nil, NewErrNoDiscoveryPlugin(ctx)
}
+ statsMu.Lock()
+ statsPrefix := naming.Join("discovery", fmt.Sprint(statsIdx))
+ statsIdx++
+ statsMu.Unlock()
d := &idiscovery{
plugins: make([]Plugin, len(plugins)),
tasks: make(map[*context.T]func()),
adSessions: make(map[discovery.AdId]sessionId),
adSubtasks: make(map[discovery.AdId]*adSubtask),
adStopTrigger: NewTrigger(),
+ statsPrefix: statsPrefix,
}
copy(d.plugins, plugins)
diff --git a/lib/discovery/plugins/ble/ble.go b/lib/discovery/plugins/ble/ble.go
index dad1926..e08ecb7 100644
--- a/lib/discovery/plugins/ble/ble.go
+++ b/lib/discovery/plugins/ble/ble.go
@@ -5,6 +5,7 @@
package ble
import (
+ "bytes"
"fmt"
"runtime"
"sync"
@@ -12,6 +13,7 @@
"v.io/v23/context"
"v.io/v23/discovery"
+ "v.io/v23/naming"
idiscovery "v.io/x/ref/lib/discovery"
"v.io/x/ref/lib/stats"
)
@@ -30,8 +32,8 @@
type plugin struct {
advertiser *advertiser
scanner *scanner
-
- adStopper *idiscovery.Trigger
+ adStopper *idiscovery.Trigger
+ statPrefix string
}
func (p *plugin) Advertise(ctx *context.T, adinfo *idiscovery.AdInfo, done func()) (err error) {
@@ -55,17 +57,38 @@
defer p.scanner.removeListener(interfaceName, listener)
seen := make(map[discovery.AdId]*idiscovery.AdInfo)
+
+ // TODO(ashankar,jhahn): To prevent plugins from stepping over
+ // each other (e.g., a Lost even from one undoing a Found event
+ // from another), the discovery implementation that uses
+ // plugins should be made aware of the plugin that sent the event.
+ // In that case, perhaps these stats should also be exported there,
+ // rather than in each plugin implementation?
+ stat := naming.Join(p.statPrefix, "seen")
+ var seenMu sync.Mutex // Safety between this goroutine and stats
+ stats.NewStringFunc(stat, func() string {
+ seenMu.Lock()
+ defer seenMu.Unlock()
+ buf := new(bytes.Buffer)
+ for k, v := range seen {
+ fmt.Fprintf(buf, "%s: %v\n\n", k, *v)
+ }
+ return buf.String()
+ })
+ defer stats.Delete(stat)
for {
select {
case adinfo := <-listener:
if adinfo.Lost {
+ seenMu.Lock()
delete(seen, adinfo.Ad.Id)
+ seenMu.Unlock()
+ } else if prev := seen[adinfo.Ad.Id]; prev != nil && (prev.Hash == adinfo.Hash || prev.TimestampNs >= adinfo.TimestampNs) {
+ continue
} else {
- prev := seen[adinfo.Ad.Id]
- if prev != nil && (prev.Hash == adinfo.Hash || prev.TimestampNs >= adinfo.TimestampNs) {
- continue
- }
+ seenMu.Lock()
seen[adinfo.Ad.Id] = adinfo
+ seenMu.Unlock()
}
copied := *adinfo
select {
@@ -98,9 +121,9 @@
return nil, err
}
statMu.Lock()
- statName := fmt.Sprintf("discovery/ble/driver/%d", statIdx)
+ statPrefix := naming.Join("discovery", "ble", fmt.Sprint(statIdx))
statIdx++
- stats.NewStringFunc(statName, func() string {
+ stats.NewStringFunc(naming.Join(statPrefix, "driver"), func() string {
return driver.DebugString()
})
statMu.Unlock()
@@ -108,7 +131,8 @@
advertiser: newAdvertiser(ctx, driver),
scanner: newScanner(ctx, driver, ttl),
adStopper: idiscovery.NewTrigger(),
+ statPrefix: statPrefix,
}
- runtime.SetFinalizer(p, func(p *plugin) { stats.Delete(statName) })
+ runtime.SetFinalizer(p, func(p *plugin) { stats.Delete(statPrefix) })
return p, nil
}