/*
* Licensed to Crate under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Crate licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial
* agreement.
*/
package io.crate.monitor;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.SingleObjectCache;
import org.elasticsearch.env.NodeEnvironment;
import org.hyperic.sigar.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class SigarExtendedNodeInfo implements ExtendedNodeInfo {
private final SigarService sigarService;
private final NodeEnvironment nodeEnvironment;
private final Map<File, FileSystem> fileSystems = new HashMap<>();
private final ExtendedOsStatsCache osStatsCache;
private final ExtendedFsStatsCache fsStatsCache;
private final ExtendedNetworkStatsCache networkStatsCache;
private final ExtendedProcessCpuStatsCache processCpuStatsCache;
static final TimeValue PROBE_CACHE_TIME = TimeValue.timeValueMillis(500L);
@Inject
public SigarExtendedNodeInfo(SigarService sigarService, NodeEnvironment nodeEnvironment) {
this.sigarService = sigarService;
this.nodeEnvironment = nodeEnvironment;
this.osStatsCache = new ExtendedOsStatsCache(PROBE_CACHE_TIME, osStatsProbe());
this.fsStatsCache = new ExtendedFsStatsCache(PROBE_CACHE_TIME, fsStatsProbe());
this.networkStatsCache = new ExtendedNetworkStatsCache(PROBE_CACHE_TIME, networkStatsProbe());
this.processCpuStatsCache = new ExtendedProcessCpuStatsCache(PROBE_CACHE_TIME, processCpuStatsProbe());
}
@Override
public ExtendedNetworkStats networkStats() {
return networkStatsCache.getOrRefresh();
}
private ExtendedNetworkStats networkStatsProbe() {
Sigar sigar = sigarService.sigar();
ExtendedNetworkStats.Tcp tcp;
try {
Tcp sigarTcp = sigar.getTcp();
tcp = new ExtendedNetworkStats.Tcp(
sigarTcp.getActiveOpens(),
sigarTcp.getPassiveOpens(),
sigarTcp.getAttemptFails(),
sigarTcp.getEstabResets(),
sigarTcp.getCurrEstab(),
sigarTcp.getInSegs(),
sigarTcp.getOutSegs(),
sigarTcp.getRetransSegs(),
sigarTcp.getInErrs(),
sigarTcp.getOutRsts()
);
} catch (SigarException e) {
// ignore
tcp = new ExtendedNetworkStats.Tcp();
}
ExtendedNetworkStats stats = new ExtendedNetworkStats(tcp);
stats.timestamp(System.currentTimeMillis());
return stats;
}
@Override
public ExtendedNetworkInfo networkInfo() {
Sigar sigar = sigarService.sigar();
ExtendedNetworkInfo.Interface iface;
try {
NetInterfaceConfig netInterfaceConfig = sigar.getNetInterfaceConfig(null);
iface = new ExtendedNetworkInfo.Interface(netInterfaceConfig.getName(), netInterfaceConfig.getHwaddr());
} catch (SigarException e) {
// ignore
iface = ExtendedNetworkInfo.NA_INTERFACE;
}
return new ExtendedNetworkInfo(iface);
}
@Override
public ExtendedFsStats fsStats() {
return fsStatsCache.getOrRefresh();
}
private ExtendedFsStats fsStatsProbe() {
if (!nodeEnvironment.hasNodeFile()) {
return new ExtendedFsStats(new ExtendedFsStats.Info[0]);
}
NodeEnvironment.NodePath[] nodePaths = nodeEnvironment.nodePaths();
ExtendedFsStats.Info[] infos = new ExtendedFsStats.Info[nodePaths.length];
Sigar sigar = sigarService.sigar();
for (int i = 0; i < nodePaths.length; i++) {
NodeEnvironment.NodePath nodePath = nodePaths[i];
File dataLocation = nodePath.path.toFile();
ExtendedFsStats.Info info = new ExtendedFsStats.Info();
info.path(dataLocation.getAbsolutePath());
try {
FileSystem fileSystem = fileSystems.get(dataLocation);
if (fileSystem == null) {
FileSystemMap fileSystemMap = sigar.getFileSystemMap();
if (fileSystemMap != null) {
fileSystem = fileSystemMap.getMountPoint(dataLocation.getPath());
fileSystems.put(dataLocation, fileSystem);
}
}
if (fileSystem != null) {
info.dev(fileSystem.getDevName());
FileSystemUsage fileSystemUsage = sigar.getFileSystemUsage(fileSystem.getDirName());
if (fileSystemUsage != null) {
// total/free/available seem to be reported in kilobytes
// so convert it into bytes
info.total(fileSystemUsage.getTotal() * 1024);
info.free(fileSystemUsage.getFree() * 1024);
info.used(fileSystemUsage.getUsed() * 1024);
info.available(fileSystemUsage.getAvail() * 1024);
info.diskReads(fileSystemUsage.getDiskReads());
info.diskWrites(fileSystemUsage.getDiskWrites());
info.diskReadSizeInBytes(fileSystemUsage.getDiskReadBytes());
info.diskWriteSizeInBytes(fileSystemUsage.getDiskWriteBytes());
}
}
} catch (SigarException e) {
// failed...
}
infos[i] = info;
}
return new ExtendedFsStats(infos);
}
@Override
public ExtendedOsStats osStats() {
return osStatsCache.getOrRefresh();
}
private ExtendedOsStats osStatsProbe() {
Sigar sigar = sigarService.sigar();
ExtendedOsStats.Cpu cpu;
try {
CpuPerc cpuPerc = sigar.getCpuPerc();
cpu = new ExtendedOsStats.Cpu(
(short) Math.round(cpuPerc.getSys() * 100),
(short) Math.round(cpuPerc.getUser() * 100),
(short) Math.round(cpuPerc.getIdle() * 100),
(short) Math.round(cpuPerc.getStolen() * 100)
);
} catch (SigarException e) {
// ignore
cpu = new ExtendedOsStats.Cpu();
}
ExtendedOsStats stats = new ExtendedOsStats(cpu);
stats.timestamp(System.currentTimeMillis());
try {
stats.loadAverage(sigar.getLoadAverage());
} catch (SigarException e) {
// ignore
}
try {
stats.uptime((long) sigar.getUptime().getUptime());
} catch (SigarException e) {
// ignore
}
return stats;
}
@SuppressWarnings("unchecked")
@Override
public ExtendedOsInfo osInfo() {
return new ExtendedOsInfo(OperatingSystem.getInstance().toMap());
}
@Override
public ExtendedProcessCpuStats processCpuStats() {
return processCpuStatsCache.getOrRefresh();
}
private ExtendedProcessCpuStats processCpuStatsProbe() {
Sigar sigar = sigarService.sigar();
try {
ProcCpu cpu = sigar.getProcCpu(sigar.getPid());
return new ExtendedProcessCpuStats(
(short) Math.round(cpu.getPercent() * 100),
cpu.getSys(),
cpu.getUser(),
cpu.getTotal()
);
} catch (SigarException e) {
// ignore
return new ExtendedProcessCpuStats();
}
}
/**
* Cache for networkStats()
*/
private class ExtendedNetworkStatsCache extends SingleObjectCache<ExtendedNetworkStats> {
ExtendedNetworkStatsCache(TimeValue refreshInterval, ExtendedNetworkStats initialValue) {
super(refreshInterval, initialValue);
}
@Override
protected ExtendedNetworkStats refresh() {
return networkStatsProbe();
}
}
/**
* Cache for processCpuStats()
*/
private class ExtendedProcessCpuStatsCache extends SingleObjectCache<ExtendedProcessCpuStats> {
ExtendedProcessCpuStatsCache(TimeValue refreshInterval, ExtendedProcessCpuStats initialValue) {
super(refreshInterval, initialValue);
}
@Override
protected ExtendedProcessCpuStats refresh() {
return processCpuStatsProbe();
}
}
/**
* Cache for fsStats()
*/
private class ExtendedFsStatsCache extends SingleObjectCache<ExtendedFsStats> {
ExtendedFsStatsCache(TimeValue refreshInterval, ExtendedFsStats initialValue) {
super(refreshInterval, initialValue);
}
@Override
protected ExtendedFsStats refresh() {
return fsStatsProbe();
}
}
/**
* Cache for osStats()
*/
private class ExtendedOsStatsCache extends SingleObjectCache<ExtendedOsStats> {
ExtendedOsStatsCache(TimeValue interval, ExtendedOsStats initValue) {
super(interval, initValue);
}
@Override
protected ExtendedOsStats refresh() {
return osStatsProbe();
}
}
}