package org.apereo.cas.monitor; import net.spy.memcached.MemcachedClientIF; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Monitors the memcached hosts known to an instance of {@link net.spy.memcached.MemcachedClientIF}. * * @author Marvin S. Addison * @since 3.5.1 */ public class MemcachedMonitor extends AbstractCacheMonitor { private final MemcachedClientIF memcachedClient; /** * Creates a new monitor that observes the given memcached client. * * @param client Memcached client. */ public MemcachedMonitor(final MemcachedClientIF client) { super(MemcachedMonitor.class.getSimpleName()); this.memcachedClient = client; } /** * Supersede the default cache status algorithm by considering unavailable memcached nodes above cache statistics. * If all nodes are unavailable, raise an error; if one or more nodes are unavailable, raise a warning; otherwise * delegate to examination of cache statistics. * * @return Cache status descriptor. */ @Override public CacheStatus observe() { if (this.memcachedClient.getAvailableServers().isEmpty()) { return new CacheStatus(StatusCode.ERROR, "No memcached servers available."); } final Collection<SocketAddress> unavailableList = this.memcachedClient.getUnavailableServers(); final CacheStatus status; if (!unavailableList.isEmpty()) { final String description = "One or more memcached servers is unavailable: " + unavailableList; status = new CacheStatus(StatusCode.WARN, description, getStatistics()); } else { status = super.observe(); } return status; } /** * Get cache statistics for all memcached hosts known to {@link MemcachedClientIF}. * * @return Statistics for all available hosts. */ @Override protected CacheStatistics[] getStatistics() { final List<CacheStatistics> statsList = new ArrayList<>(); if (this.memcachedClient != null) { this.memcachedClient.getStats().forEach((key, statsMap) -> { if (!statsMap.isEmpty()) { final long size = Long.parseLong(statsMap.get("bytes")); final long capacity = Long.parseLong(statsMap.get("limit_maxbytes")); final long evictions = Long.parseLong(statsMap.get("evictions")); final String name; if (key instanceof InetSocketAddress) { name = ((InetSocketAddress) key).getHostName(); } else { name = key.toString(); } statsList.add(new SimpleCacheStatistics(size, capacity, evictions, name)); } }); } return statsList.toArray(new CacheStatistics[statsList.size()]); } }