fix: eliminate race condition on Monitor.globalTags (#23471)

close #23470

(cherry picked from commit dd356e0bcc)
pull/23490/head
Geoffrey Wossum 2022-06-16 20:11:52 -05:00 committed by GitHub
parent 75ed51b9c3
commit ee881ec558
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 41 additions and 8 deletions

View File

@ -32,6 +32,39 @@ const (
MonitorRetentionPolicyReplicaN = 1 MonitorRetentionPolicyReplicaN = 1
) )
// tags provides thread-safe tag handling
type tags struct {
mu sync.RWMutex
tags map[string]string
}
// NewTags creates a new tags struct to use
func newTags() *tags {
return &tags{
tags: make(map[string]string),
}
}
// Add adds a new tag to the tag collection
func (t *tags) Add(key string, value interface{}) {
t.mu.Lock()
defer t.mu.Unlock()
t.tags[key] = fmt.Sprintf("%v", value)
}
// Tags safely returns a copy of the current tag mapping
func (t *tags) Tags() map[string]string {
t.mu.RLock()
defer t.mu.RUnlock()
r := make(map[string]string)
for k, v := range t.tags {
r[k] = v
}
return r
}
// Monitor represents an instance of the monitor system. // Monitor represents an instance of the monitor system.
type Monitor struct { type Monitor struct {
// Build information for diagnostics. // Build information for diagnostics.
@ -42,8 +75,9 @@ type Monitor struct {
wg sync.WaitGroup wg sync.WaitGroup
globalTags *tags
mu sync.RWMutex mu sync.RWMutex
globalTags map[string]string
diagRegistrations map[string]diagnostics.Client diagRegistrations map[string]diagnostics.Client
reporter Reporter reporter Reporter
done chan struct{} done chan struct{}
@ -73,7 +107,7 @@ type PointsWriter interface {
// New returns a new instance of the monitor system. // New returns a new instance of the monitor system.
func New(r Reporter, c Config) *Monitor { func New(r Reporter, c Config) *Monitor {
return &Monitor{ return &Monitor{
globalTags: make(map[string]string), globalTags: newTags(),
diagRegistrations: make(map[string]diagnostics.Client), diagRegistrations: make(map[string]diagnostics.Client),
reporter: r, reporter: r,
storeEnabled: c.StoreEnabled, storeEnabled: c.StoreEnabled,
@ -138,9 +172,10 @@ func (m *Monitor) WritePoints(p models.Points) error {
return nil return nil
} }
if len(m.globalTags) > 0 { gt := m.globalTags.Tags()
if len(gt) > 0 {
for _, pp := range p { for _, pp := range p {
pp.SetTags(pp.Tags().Merge(m.globalTags)) pp.SetTags(pp.Tags().Merge(gt))
} }
} }
@ -185,9 +220,7 @@ func (m *Monitor) Close() error {
// SetGlobalTag can be used to set tags that will appear on all points // SetGlobalTag can be used to set tags that will appear on all points
// written by the Monitor. // written by the Monitor.
func (m *Monitor) SetGlobalTag(key string, value interface{}) { func (m *Monitor) SetGlobalTag(key string, value interface{}) {
m.mu.Lock() m.globalTags.Add(key, value)
m.globalTags[key] = fmt.Sprintf("%v", value)
m.mu.Unlock()
} }
// RemoteWriterConfig represents the configuration of a remote writer. // RemoteWriterConfig represents the configuration of a remote writer.
@ -440,7 +473,7 @@ func (m *Monitor) storeStatistics() {
m.createInternalStorage() m.createInternalStorage()
}() }()
stats, err := m.Statistics(m.globalTags) stats, err := m.Statistics(m.globalTags.Tags())
if err != nil { if err != nil {
m.Logger.Info("Failed to retrieve registered statistics", zap.Error(err)) m.Logger.Info("Failed to retrieve registered statistics", zap.Error(err))
return return