in hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/snmp/SnmpCollectImpl.java [104:259]
public void collect(CollectRep.MetricsData.Builder builder, Metrics metrics) {
long startTime = System.currentTimeMillis();
SnmpProtocol snmpProtocol = metrics.getSnmp();
int timeout = CollectUtil.getTimeout(snmpProtocol.getTimeout());
int snmpVersion = getSnmpVersion(snmpProtocol.getVersion());
Snmp snmpService = null;
try {
SnmpBuilder snmpBuilder = new SnmpBuilder();
snmpService = getSnmpService(snmpVersion, snmpBuilder);
snmpService.listen();
Target<?> target;
Address targetAddress = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + snmpProtocol.getHost()
+ "/" + snmpProtocol.getPort());
TargetBuilder<?> targetBuilder = snmpBuilder.target(targetAddress);
if (snmpVersion == SnmpConstants.version3) {
TargetBuilder.PrivProtocol privatePasswordEncryption = getPrivPasswordEncryption(snmpProtocol.getPrivPasswordEncryption());
TargetBuilder.AuthProtocol authPasswordEncryption = getAuthPasswordEncryption(snmpProtocol.getAuthPasswordEncryption());
target = targetBuilder
.user(snmpProtocol.getUsername())
.auth(authPasswordEncryption).authPassphrase(snmpProtocol.getAuthPassphrase())
.priv(privatePasswordEncryption).privPassphrase(snmpProtocol.getPrivPassphrase())
.done()
.timeout(timeout).retries(1)
.build();
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
snmpService.getUSM().addUser(
new OctetString(snmpProtocol.getUsername()),
new UsmUser(new OctetString(snmpProtocol.getUsername()),
AuthMD5.ID,
new OctetString(snmpProtocol.getAuthPassphrase()),
PrivDES.ID,
new OctetString(snmpProtocol.getPrivPassphrase()))
);
} else if (snmpVersion == SnmpConstants.version1) {
target = targetBuilder
.v1()
.community(new OctetString(snmpProtocol.getCommunity()))
.timeout(timeout).retries(1)
.build();
target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv1);
} else {
target = targetBuilder
.v2c()
.community(new OctetString(snmpProtocol.getCommunity()))
.timeout(timeout).retries(1)
.build();
target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);
}
String operation = snmpProtocol.getOperation();
operation = StringUtils.hasText(operation) ? operation : OPERATION_GET;
if (OPERATION_GET.equalsIgnoreCase(operation)) {
String contextName = getContextName(snmpProtocol.getContextName());
PDU pdu = targetBuilder.pdu().type(PDU.GET).oids(snmpProtocol.getOids().values().toArray(new String[0])).contextName(contextName).build();
SnmpCompletableFuture snmpRequestFuture = SnmpCompletableFuture.send(snmpService, target, pdu);
List<VariableBinding> vbs = snmpRequestFuture.get().getAll();
long responseTime = System.currentTimeMillis() - startTime;
Map<String, String> oidsMap = snmpProtocol.getOids();
Map<String, String> oidsValueMap = new HashMap<>(oidsMap.size());
for (VariableBinding binding : vbs) {
if (binding == null) {
continue;
}
Variable variable = binding.getVariable();
if (variable instanceof TimeTicks timeTicks) {
String value = timeTicks.toString(FORMAT_PATTERN);
oidsValueMap.put(binding.getOid().toDottedString(), value);
} else {
oidsValueMap.put(binding.getOid().toDottedString(), binding.toValueString());
}
}
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : metrics.getAliasFields()) {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumn(Long.toString(responseTime));
} else {
String oid = oidsMap.get(alias);
String value = oidsValueMap.get(oid);
valueRowBuilder.addColumn(Objects.requireNonNullElse(value, CommonConstants.NULL_VALUE));
}
}
builder.addValueRow(valueRowBuilder.build());
} else if (OPERATION_WALK.equalsIgnoreCase(operation)) {
Map<String, String> oidMap = snmpProtocol.getOids();
Assert.notEmpty(oidMap, "snmp oids is required when operation is walk.");
TableUtils tableUtils = new TableUtils(snmpService, new DefaultPDUFactory(PDU.GETBULK));
OID[] oids = oidMap.values().stream().map(OID::new).toArray(OID[]::new);
List<TableEvent> tableEvents = tableUtils.getTable(target, oids, null, null);
Assert.notNull(tableEvents, "snmp walk response empty content.");
long responseTime = System.currentTimeMillis() - startTime;
for (TableEvent tableEvent : tableEvents) {
if (tableEvent == null || tableEvent.isError()) {
continue;
}
VariableBinding[] varBindings = tableEvent.getColumns();
Map<String, String> oidsValueMap = new HashMap<>(varBindings.length);
for (VariableBinding binding : varBindings) {
if (binding == null) {
continue;
}
Variable variable = binding.getVariable();
if (variable instanceof TimeTicks timeTicks) {
String value = timeTicks.toString(FORMAT_PATTERN);
oidsValueMap.put(binding.getOid().trim().toDottedString(), value);
} else {
oidsValueMap.put(binding.getOid().trim().toDottedString(), bingdingHexValueToString(binding));
}
}
// when too many empty value field, ignore
if (oidsValueMap.size() < metrics.getAliasFields().size() / 2) {
continue;
}
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : metrics.getAliasFields()) {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumn(Long.toString(responseTime));
} else {
String oid = oidMap.get(alias);
String value = oidsValueMap.get(oid);
if (value == null) {
// get leaf
for (String key : oidsValueMap.keySet()) {
if (key.startsWith(oid)) {
value = oidsValueMap.get(key);
break;
}
}
}
valueRowBuilder.addColumn(Objects.requireNonNullElse(value, CommonConstants.NULL_VALUE));
}
}
builder.addValueRow(valueRowBuilder.build());
}
}
} catch (ExecutionException | InterruptedException ex) {
String errorMsg = CommonUtil.getMessageFromThrowable(ex);
log.warn("[snmp collect] error: {}", errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg(errorMsg);
} catch (Exception e) {
String errorMsg = CommonUtil.getMessageFromThrowable(e);
log.warn("[snmp collect] error: {}", errorMsg, e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} finally {
if (snmpService != null) {
if (snmpVersion == SnmpConstants.version3) {
try {
snmpClose(snmpService, SnmpConstants.version3);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}