package stats import ( "sync" "time" ) // OnlineMap is an implementation of stats.OnlineMap. type OnlineMap struct { value int ipList map[string]time.Time access sync.RWMutex lastCleanup time.Time cleanupPeriod time.Duration } // NewOnlineMap creates a new instance of OnlineMap. func NewOnlineMap() *OnlineMap { return &OnlineMap{ ipList: make(map[string]time.Time), lastCleanup: time.Now(), cleanupPeriod: 10 * time.Second, } } // Count implements stats.OnlineMap. func (c *OnlineMap) Count() int { return c.value } // List implements stats.OnlineMap. func (c *OnlineMap) List() []string { return c.GetKeys() } // AddIP implements stats.OnlineMap. func (c *OnlineMap) AddIP(ip string) { list := c.ipList if ip == "127.0.0.1" { return } if _, ok := list[ip]; !ok { c.access.Lock() list[ip] = time.Now() c.access.Unlock() } if time.Since(c.lastCleanup) > c.cleanupPeriod { list = c.RemoveExpiredIPs(list) c.lastCleanup = time.Now() } c.value = len(list) c.ipList = list } func (c *OnlineMap) GetKeys() []string { c.access.RLock() defer c.access.RUnlock() keys := []string{} for k := range c.ipList { keys = append(keys, k) } return keys } func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.Time { c.access.Lock() defer c.access.Unlock() now := time.Now() for k, t := range list { diff := now.Sub(t) if diff.Seconds() > 20 { delete(list, k) } } return list }