All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.telemetry.TelemetryNodeService Maven / Gradle / Ivy

package org.graylog2.telemetry;

import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import com.github.joschi.jadconfig.util.Duration;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.graylog2.inputs.InputService;
import org.graylog2.plugin.PluginMetaData;
import org.graylog2.plugin.ServerStatus;
import org.graylog2.plugin.Tools;
import org.graylog2.plugin.Version;
import org.graylog2.shared.system.stats.StatsService;
import org.graylog2.telemetry.dto.NodeDataSet;
import org.graylog2.telemetry.dto.NodeInfo;
import org.graylog2.telemetry.dto.NodeRole;
import org.graylog2.telemetry.dto.NodeStats;
import org.graylog2.telemetry.dto.PluginInfo;
import org.graylog2.telemetry.server.TelemetryServerMetaData;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Set;

@Singleton
public class TelemetryNodeService {
    private static final Set METRICS_BLACKLIST = ImmutableSet.builder()
            .add("org.graylog2.rest.resources")
            .build();

    public static final MetricFilter METRICS_FILTER = new MetricFilter() {
        @Override
        public boolean matches(String name, Metric metric) {
            for (final String prefix : METRICS_BLACKLIST) {
                if (name.startsWith(prefix)) {
                    return false;
                }
            }
            return true;
        }
    };

    private final ServerStatus serverStatus;
    private final MetricRegistry metricRegistry;
    private final StatsService statsService;
    private final Set plugins;

    private final String nodeId;
    private final NodeInfo nodeInfo;
    private final Supplier cachedDataSet;
    private final long reportIntervalMs;

    // This is such a hack, but Radio simply doesn't have an
    // InputService and this is easier than creating a custom
    // TelemetryNodeService for Radio.
    @com.google.inject.Inject(optional = true)
    private InputService inputService = null;


    @Inject
    public TelemetryNodeService(ServerStatus serverStatus,
                                MetricRegistry metricRegistry,
                                StatsService statsService,
                                Set plugins,
                                @Named("telemetry_cache_timeout") Duration cacheTimeout,
                                @Named("telemetry_report_interval") Duration reportInterval) {
        this.serverStatus = serverStatus;
        this.metricRegistry = metricRegistry;
        this.statsService = statsService;
        this.plugins = plugins;

        this.nodeId = serverStatus.getNodeId().toString();
        this.nodeInfo = buildNodeInfo();
        this.cachedDataSet = Suppliers.memoizeWithExpiration(cachingSupplier(), cacheTimeout.getQuantity(), cacheTimeout.getUnit());
        this.reportIntervalMs = reportInterval.toMilliseconds();
    }

    private NodeInfo buildNodeInfo() {
        return NodeInfo.create(
                nodeId,
                serverStatus.getNodeId().anonymize(),
                nodeRole(),
                Tools.getLocalHostname(),
                Version.CURRENT_CLASSPATH.toString(),
                serverStatus.getStartedAt(),
                serverStatus.getTimezone(),
                buildPluginInfo()
        );
    }

    private Set buildPluginInfo() {
        final Set pluginInfos = Sets.newHashSetWithExpectedSize(plugins.size());
        for (PluginMetaData pluginMetaData : plugins) {
            pluginInfos.add(PluginInfo.create(
                            pluginMetaData.getUniqueId(),
                            pluginMetaData.getName(),
                            pluginMetaData.getVersion().toString()
                    )
            );
        }

        return pluginInfos;
    }

    private NodeRole nodeRole() {
        if (serverStatus.hasCapabilities(ServerStatus.Capability.MASTER)) {
            return NodeRole.MASTER;
        } else if (serverStatus.hasCapabilities(ServerStatus.Capability.SERVER)) {
            return NodeRole.SERVER;
        } else if (serverStatus.hasCapabilities(ServerStatus.Capability.RADIO)) {
            return NodeRole.RADIO;
        }

        return null;
    }

    public NodeDataSet buildNodeDataSet() {
        return cachedDataSet.get();
    }

    private Supplier cachingSupplier() {
        return new Supplier() {
            @Override
            public NodeDataSet get() {
                final NodeStats nodeStats = NodeStats.create(
                        serverStatus.getLifecycle(),
                        serverStatus.isProcessing(),
                        serverStatus.getLifecycle().getLoadbalancerStatus(),
                        inputService == null ? -1 : inputService.totalCountForNode(nodeId)
                );

                return NodeDataSet.create(
                        String.valueOf(TelemetryServerMetaData.VERSION),
                        System.currentTimeMillis(),
                        reportIntervalMs,
                        nodeInfo,
                        nodeStats,
                        metricRegistry,
                        statsService.systemStats()
                );
            }
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy