2020-10-12 08:15:53 +00:00
|
|
|
/*
|
2020-08-18 11:49:48 +00:00
|
|
|
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
|
|
|
|
*
|
|
|
|
* Licensed 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.
|
|
|
|
*/
|
2020-10-09 08:20:50 +00:00
|
|
|
package biz.nellemann.hmci;
|
|
|
|
|
2020-10-11 10:25:55 +00:00
|
|
|
import biz.nellemann.hmci.Configuration.InfluxObject;
|
2020-10-09 08:20:50 +00:00
|
|
|
import org.influxdb.BatchOptions;
|
|
|
|
import org.influxdb.InfluxDB;
|
|
|
|
import org.influxdb.InfluxDBFactory;
|
|
|
|
import org.influxdb.dto.BatchPoints;
|
|
|
|
import org.influxdb.dto.Point;
|
|
|
|
import org.influxdb.dto.Query;
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2020-08-11 14:26:16 +00:00
|
|
|
|
2020-10-11 10:25:55 +00:00
|
|
|
import java.time.Instant;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2020-10-09 08:20:50 +00:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2020-08-11 14:26:16 +00:00
|
|
|
|
2020-12-23 12:02:48 +00:00
|
|
|
import static java.lang.Thread.sleep;
|
|
|
|
|
2020-08-10 13:44:14 +00:00
|
|
|
class InfluxClient {
|
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
private final static Logger log = LoggerFactory.getLogger(InfluxClient.class);
|
|
|
|
|
2021-01-14 13:22:42 +00:00
|
|
|
private static final int BATCH_ACTIONS_LIMIT = 5000;
|
|
|
|
private static final int BATCH_INTERVAL_DURATION = 1000;
|
|
|
|
|
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
final private String url;
|
|
|
|
final private String username;
|
|
|
|
final private String password;
|
|
|
|
final private String database;
|
2020-08-11 14:26:16 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
private InfluxDB influxDB;
|
|
|
|
private BatchPoints batchPoints;
|
2020-08-11 14:26:16 +00:00
|
|
|
|
2020-09-02 07:27:38 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
InfluxClient(InfluxObject config) {
|
|
|
|
this.url = config.url;
|
|
|
|
this.username = config.username;
|
|
|
|
this.password = config.password;
|
|
|
|
this.database = config.database;
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-09-02 07:27:38 +00:00
|
|
|
|
2021-01-14 12:51:18 +00:00
|
|
|
synchronized void login() throws RuntimeException, InterruptedException {
|
2020-10-09 08:20:50 +00:00
|
|
|
|
|
|
|
if(influxDB != null) {
|
2020-10-11 10:25:55 +00:00
|
|
|
return;
|
2020-10-09 08:20:50 +00:00
|
|
|
}
|
|
|
|
|
2020-12-23 12:02:48 +00:00
|
|
|
boolean connected = false;
|
|
|
|
int errors = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
try {
|
|
|
|
log.debug("Connecting to InfluxDB - " + url);
|
|
|
|
influxDB = InfluxDBFactory.connect(url, username, password);
|
|
|
|
createDatabase();
|
|
|
|
batchPoints = BatchPoints.database(database).precision(TimeUnit.SECONDS).build();
|
|
|
|
connected = true;
|
|
|
|
} catch(Exception e) {
|
2021-01-14 12:51:18 +00:00
|
|
|
sleep(15 * 1000);
|
2020-12-23 12:02:48 +00:00
|
|
|
if(errors++ > 3) {
|
|
|
|
log.error("login() error, giving up - " + e.getMessage());
|
2021-01-14 12:51:18 +00:00
|
|
|
throw new RuntimeException(e);
|
2020-12-23 12:02:48 +00:00
|
|
|
} else {
|
|
|
|
log.warn("login() error, retrying - " + e.getMessage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while(!connected);
|
2020-08-14 07:34:44 +00:00
|
|
|
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-09-02 07:27:38 +00:00
|
|
|
|
2020-10-14 08:41:31 +00:00
|
|
|
synchronized void logoff() {
|
2020-10-09 08:20:50 +00:00
|
|
|
if(influxDB != null) {
|
|
|
|
influxDB.close();
|
|
|
|
}
|
|
|
|
influxDB = null;
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 15:50:26 +00:00
|
|
|
void createDatabase() {
|
2020-09-02 07:27:38 +00:00
|
|
|
// Create our database... with a default retention of 156w == 3 years
|
|
|
|
influxDB.query(new Query("CREATE DATABASE " + database + " WITH DURATION 156w"));
|
2020-08-13 15:50:26 +00:00
|
|
|
influxDB.setDatabase(database);
|
2020-08-14 07:34:44 +00:00
|
|
|
}
|
2020-08-11 14:26:16 +00:00
|
|
|
|
|
|
|
|
2020-10-14 08:41:31 +00:00
|
|
|
synchronized void writeBatchPoints() throws Exception {
|
2020-10-09 08:20:50 +00:00
|
|
|
log.debug("writeBatchPoints()");
|
2020-08-16 14:42:05 +00:00
|
|
|
try {
|
2021-01-14 13:22:42 +00:00
|
|
|
influxDB.writeWithRetry(batchPoints);
|
2020-08-16 14:42:05 +00:00
|
|
|
} catch(Exception e) {
|
2020-10-09 08:20:50 +00:00
|
|
|
log.error("writeBatchPoints() error - " + e.getMessage());
|
|
|
|
logoff();
|
|
|
|
login();
|
2020-08-16 14:42:05 +00:00
|
|
|
}
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 09:48:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Managed System
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2020-08-11 14:26:16 +00:00
|
|
|
void writeManagedSystem(ManagedSystem system) {
|
|
|
|
|
|
|
|
if(system.metrics == null) {
|
2021-01-13 07:31:07 +00:00
|
|
|
log.debug("writeManagedSystem() - null metrics, skipping");
|
2020-10-09 08:20:50 +00:00
|
|
|
return;
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
Instant timestamp = system.getTimestamp();
|
|
|
|
if(timestamp == null) {
|
|
|
|
log.warn("writeManagedSystem() - no timestamp, skipping");
|
|
|
|
return;
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-10-15 13:23:16 +00:00
|
|
|
getSystemMemory(system, timestamp).forEach( it -> batchPoints.point(it) );
|
|
|
|
getSystemProcessor(system, timestamp).forEach( it -> batchPoints.point(it) );
|
|
|
|
getSystemSharedProcessorPools(system, timestamp).forEach( it -> batchPoints.point(it) );
|
|
|
|
getSystemSharedAdapters(system, timestamp).forEach( it -> batchPoints.point(it) );
|
|
|
|
getSystemFiberChannelAdapters(system, timestamp).forEach( it -> batchPoints.point(it) );
|
2020-12-11 07:39:19 +00:00
|
|
|
getSystemVirtualEthernetAdapters(system, timestamp).forEach( it -> batchPoints.point(it) );
|
2020-12-16 11:36:08 +00:00
|
|
|
getSystemViosMemory(system, timestamp).forEach( it -> batchPoints.point(it) );
|
|
|
|
getSystemViosProcessor(system, timestamp).forEach( it -> batchPoints.point(it) );
|
2020-09-03 14:12:07 +00:00
|
|
|
|
2020-08-11 14:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 14:12:07 +00:00
|
|
|
|
2020-08-13 09:48:00 +00:00
|
|
|
private static List<Point> getSystemMemory(ManagedSystem system, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = system.getMemoryMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemMemory");
|
2020-08-13 09:48:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getSystemProcessor(ManagedSystem system, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = system.getProcessorMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemProcessor");
|
2020-08-13 09:48:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getSystemSharedProcessorPools(ManagedSystem system, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = system.getSharedProcessorPools();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemSharedProcessorPool");
|
2020-08-13 09:48:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getSystemSharedAdapters(ManagedSystem system, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = system.getSystemSharedAdapters();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemSharedAdapters");
|
2020-08-13 09:48:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getSystemFiberChannelAdapters(ManagedSystem system, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = system.getSystemFiberChannelAdapters();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemFiberChannelAdapters");
|
2020-08-13 09:48:00 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 11:36:08 +00:00
|
|
|
private static List<Point> getSystemVirtualEthernetAdapters(ManagedSystem system, Instant timestamp) {
|
|
|
|
List<Measurement> metrics = system.getSystemVirtualEthernetAdapters();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemVirtualEthernetAdapters");
|
2020-09-03 14:12:07 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 11:36:08 +00:00
|
|
|
private static List<Point> getSystemViosMemory(ManagedSystem system, Instant timestamp) {
|
|
|
|
List<Measurement> metrics = system.getViosMemoryMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemViosMemory");
|
2020-09-03 14:12:07 +00:00
|
|
|
}
|
2020-12-11 07:39:19 +00:00
|
|
|
|
2020-12-16 11:36:08 +00:00
|
|
|
private static List<Point> getSystemViosProcessor(ManagedSystem system, Instant timestamp) {
|
|
|
|
List<Measurement> metrics = system.getViosProcessorMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemViosProcessor");
|
2020-12-11 07:39:19 +00:00
|
|
|
}
|
2020-09-03 14:12:07 +00:00
|
|
|
|
2020-08-13 09:48:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Logical Partitions
|
|
|
|
*/
|
2020-08-11 14:26:16 +00:00
|
|
|
|
2020-08-12 15:00:31 +00:00
|
|
|
void writeLogicalPartition(LogicalPartition partition) {
|
|
|
|
|
|
|
|
if(partition.metrics == null) {
|
2020-10-09 08:20:50 +00:00
|
|
|
log.warn("writeLogicalPartition() - null metrics, skipping");
|
|
|
|
return;
|
2020-08-12 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
Instant timestamp = partition.getTimestamp();
|
|
|
|
if(timestamp == null) {
|
|
|
|
log.warn("writeLogicalPartition() - no timestamp, skipping");
|
|
|
|
return;
|
2020-08-12 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2020-10-15 13:23:16 +00:00
|
|
|
getPartitionAffinityScore(partition, timestamp).forEach( it -> batchPoints.point(it));
|
|
|
|
getPartitionMemory(partition, timestamp).forEach( it -> batchPoints.point(it));
|
|
|
|
getPartitionProcessor(partition, timestamp).forEach( it -> batchPoints.point(it));
|
|
|
|
getPartitionVirtualEthernetAdapter(partition, timestamp).forEach( it -> batchPoints.point(it));
|
|
|
|
getPartitionVirtualFiberChannelAdapter(partition, timestamp).forEach( it -> batchPoints.point(it));
|
2020-08-11 14:26:16 +00:00
|
|
|
|
|
|
|
}
|
2020-12-11 07:39:19 +00:00
|
|
|
|
2020-09-03 14:12:07 +00:00
|
|
|
private static List<Point> getPartitionAffinityScore(LogicalPartition partition, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = partition.getAffinityScore();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "PartitionAffinityScore");
|
2020-09-03 14:12:07 +00:00
|
|
|
}
|
|
|
|
|
2020-08-12 15:00:31 +00:00
|
|
|
private static List<Point> getPartitionMemory(LogicalPartition partition, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = partition.getMemoryMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "PartitionMemory");
|
2020-08-12 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getPartitionProcessor(LogicalPartition partition, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = partition.getProcessorMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "PartitionProcessor");
|
2020-08-12 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getPartitionVirtualEthernetAdapter(LogicalPartition partition, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = partition.getVirtualEthernetAdapterMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "PartitionVirtualEthernetAdapters");
|
2020-08-12 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2020-08-13 09:48:00 +00:00
|
|
|
private static List<Point> getPartitionVirtualFiberChannelAdapter(LogicalPartition partition, Instant timestamp) {
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Measurement> metrics = partition.getVirtualFiberChannelAdaptersMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "PartitionVirtualFiberChannelAdapters");
|
2020-08-13 09:48:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-12 15:00:31 +00:00
|
|
|
|
2020-12-11 07:39:19 +00:00
|
|
|
/*
|
|
|
|
System Energy
|
2021-01-13 07:31:07 +00:00
|
|
|
Not supported on older HMC (pre v8) or older Power server (pre Power 8)
|
2020-12-11 07:39:19 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void writeSystemEnergy(SystemEnergy system) {
|
|
|
|
|
|
|
|
if(system.metrics == null) {
|
2021-01-13 07:31:07 +00:00
|
|
|
log.debug("writeSystemEnergy() - null metrics, skipping");
|
2020-12-11 07:39:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Instant timestamp = system.getTimestamp();
|
|
|
|
if(timestamp == null) {
|
|
|
|
log.warn("writeSystemEnergy() - no timestamp, skipping");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
getSystemEnergyPower(system, timestamp).forEach(it -> batchPoints.point(it) );
|
|
|
|
getSystemEnergyTemperature(system, timestamp).forEach(it -> batchPoints.point(it) );
|
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getSystemEnergyPower(SystemEnergy system, Instant timestamp) {
|
|
|
|
List<Measurement> metrics = system.getPowerMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemEnergyPower");
|
|
|
|
}
|
|
|
|
|
|
|
|
private static List<Point> getSystemEnergyTemperature(SystemEnergy system, Instant timestamp) {
|
|
|
|
List<Measurement> metrics = system.getThermalMetrics();
|
|
|
|
return processMeasurementMap(metrics, timestamp, "SystemEnergyThermal");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 09:48:00 +00:00
|
|
|
/*
|
|
|
|
Shared
|
|
|
|
*/
|
2020-08-12 15:00:31 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
private static List<Point> processMeasurementMap(List<Measurement> measurements, Instant timestamp, String measurement) {
|
2020-08-12 15:00:31 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
List<Point> listOfPoints = new ArrayList<>();
|
|
|
|
measurements.forEach( m -> {
|
2020-08-12 15:00:31 +00:00
|
|
|
|
|
|
|
// Iterate fields
|
2020-10-09 08:20:50 +00:00
|
|
|
m.fields.forEach((fieldName, fieldValue) -> {
|
2020-10-11 10:25:55 +00:00
|
|
|
log.debug("processMeasurementMap() " + measurement + " - fieldName: " + fieldName + ", fieldValue: " + fieldValue);
|
2020-08-12 15:00:31 +00:00
|
|
|
|
|
|
|
Point.Builder builder = Point.measurement(measurement)
|
|
|
|
.time(timestamp.toEpochMilli(), TimeUnit.MILLISECONDS)
|
|
|
|
.tag("name", fieldName)
|
2020-10-09 08:20:50 +00:00
|
|
|
.addField("value", fieldValue);
|
2020-08-12 15:00:31 +00:00
|
|
|
|
|
|
|
// For each field, we add all tags
|
2020-10-09 08:20:50 +00:00
|
|
|
m.tags.forEach((tagName, tagValue) -> {
|
|
|
|
builder.tag(tagName, tagValue);
|
|
|
|
log.debug("processMeasurementMap() " + measurement + " - tagName: " + tagName + ", tagValue: " + tagValue);
|
|
|
|
});
|
2020-08-12 15:00:31 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
listOfPoints.add(builder.build());
|
|
|
|
});
|
2020-08-12 15:00:31 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
});
|
2020-08-12 15:00:31 +00:00
|
|
|
|
2020-10-09 08:20:50 +00:00
|
|
|
return listOfPoints;
|
2020-08-12 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-10 13:44:14 +00:00
|
|
|
}
|