mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 00:01:40 +01:00 
			
		
		
		
	The callback itself is not removed as it is used in other repos, making it simpler for those to slowly transition to the eventbus. Updates #15160 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
		
			
				
	
	
		
			61 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			61 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) Tailscale Inc & AUTHORS
 | |
| // SPDX-License-Identifier: BSD-3-Clause
 | |
| 
 | |
| package netmon
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"sync"
 | |
| 
 | |
| 	"tailscale.com/types/logger"
 | |
| 	"tailscale.com/util/eventbus"
 | |
| )
 | |
| 
 | |
| // LinkChangeLogLimiter returns a new [logger.Logf] that logs each unique
 | |
| // format string to the underlying logger only once per major LinkChange event.
 | |
| //
 | |
| // The logger stops tracking seen format strings when the provided context is
 | |
| // done.
 | |
| func LinkChangeLogLimiter(ctx context.Context, logf logger.Logf, nm *Monitor) logger.Logf {
 | |
| 	var formatSeen sync.Map // map[string]bool
 | |
| 	nm.b.Monitor(nm.changeDeltaWatcher(nm.b, ctx, func(cd ChangeDelta) {
 | |
| 		// If we're in a major change or a time jump, clear the seen map.
 | |
| 		if cd.Major || cd.TimeJumped {
 | |
| 			formatSeen.Clear()
 | |
| 		}
 | |
| 	}))
 | |
| 
 | |
| 	return func(format string, args ...any) {
 | |
| 		// We only store 'true' in the map, so if it's present then it
 | |
| 		// means we've already logged this format string.
 | |
| 		_, loaded := formatSeen.LoadOrStore(format, true)
 | |
| 		if loaded {
 | |
| 			// TODO(andrew-d): we may still want to log this
 | |
| 			// message every N minutes (1x/hour?) even if it's been
 | |
| 			// seen, so that debugging doesn't require searching
 | |
| 			// back in the logs for an unbounded amount of time.
 | |
| 			//
 | |
| 			// See: https://github.com/tailscale/tailscale/issues/13145
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		logf(format, args...)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (nm *Monitor) changeDeltaWatcher(ec *eventbus.Client, ctx context.Context, fn func(ChangeDelta)) func(*eventbus.Client) {
 | |
| 	sub := eventbus.Subscribe[ChangeDelta](ec)
 | |
| 	return func(ec *eventbus.Client) {
 | |
| 		for {
 | |
| 			select {
 | |
| 			case <-ctx.Done():
 | |
| 				return
 | |
| 			case <-sub.Done():
 | |
| 				return
 | |
| 			case change := <-sub.Events():
 | |
| 				fn(change)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 |