diff --git a/rdb/build.gradle b/rdb/build.gradle index 0a46d40..8fcbc5f 100644 --- a/rdb/build.gradle +++ b/rdb/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation("mysql:mysql-connector-java:5.1.46") implementation(files("libs/DmJdbcDriver18.jar")) + implementation(files("libs/ngdbc-2.4.64.jar")) } application { diff --git a/rdb/config/config-hana.yaml b/rdb/config/config-hana.yaml new file mode 100644 index 0000000..1e48842 --- /dev/null +++ b/rdb/config/config-hana.yaml @@ -0,0 +1,17 @@ +#Database properties: +db.system: hana +db.driver: com.sap.db.jdbc.Driver +instances: + - db.address: 9.42.129.183 + db.port: 30015 + db.username: D4MON + db.password: UGVyZjBybS4= + db.connection.url: jdbc:sap://9.42.129.183:30015 + db.name: ML4 + #Data collector properties: + poll.interval: 30 + callback.interval: 20 + otel.backend.url: http://127.0.0.1:4317 + #otel.backend.using.http: true + #OTel properties: + otel.service.name: SAPHana diff --git a/rdb/libs/ngdbc-2.4.64.jar b/rdb/libs/ngdbc-2.4.64.jar new file mode 100644 index 0000000..291cca1 Binary files /dev/null and b/rdb/libs/ngdbc-2.4.64.jar differ diff --git a/rdb/src/main/java/com/instana/dc/rdb/impl/DbDcRegistry.java b/rdb/src/main/java/com/instana/dc/rdb/impl/DbDcRegistry.java index 1663dc7..281bc06 100644 --- a/rdb/src/main/java/com/instana/dc/rdb/impl/DbDcRegistry.java +++ b/rdb/src/main/java/com/instana/dc/rdb/impl/DbDcRegistry.java @@ -16,6 +16,7 @@ public class DbDcRegistry { private final Map> map = new HashMap>() {{ put("DAMENG", DamengDc.class); put("OCEANBASE4", Oceanbase4Dc.class); + put("HANA", HanaDc.class); }}; public Class findDatabaseDc(String dbSystem) throws DcException { diff --git a/rdb/src/main/java/com/instana/dc/rdb/impl/HanaDc.java b/rdb/src/main/java/com/instana/dc/rdb/impl/HanaDc.java new file mode 100644 index 0000000..3afbbc1 --- /dev/null +++ b/rdb/src/main/java/com/instana/dc/rdb/impl/HanaDc.java @@ -0,0 +1,87 @@ +/* + * (c) Copyright IBM Corp. 2023 + * (c) Copyright Instana Inc. + */ +package com.instana.dc.rdb.impl; + +import com.instana.dc.CalculationMode; +import com.instana.dc.DcUtil; +import com.instana.dc.rdb.AbstractDbDc; +import com.instana.dc.rdb.DbDcUtil; +import io.opentelemetry.api.OpenTelemetry; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.instana.agent.sensorsdk.semconv.SemanticAttributes.*; +import static com.instana.dc.rdb.DbDcUtil.*; + +import static com.instana.dc.rdb.impl.HanaUtil.*; + + +public class HanaDc extends AbstractDbDc { + + private static final Logger logger = Logger.getLogger(HanaDc.class.getName()); + + public HanaDc(Map properties, String dbSystem, String dbDriver) throws SQLException { + super(properties, dbSystem, dbDriver); + setDbPassword(DcUtil.base64Decode(getDbPassword())); + findDbNameAndVersion(); + if (getServiceInstanceId() == null) { + setServiceInstanceId(getDbAddress() + ":" + getDbPort() + "@" + getDbName()); + } + } + + @Override + public void registerMetrics() { + super.registerMetrics(); + getRawMetric(DB_TRANSACTION_RATE_NAME).setCalculationMode(CalculationMode.RATE); + getRawMetric(DB_SQL_RATE_NAME).setCalculationMode(CalculationMode.RATE); + getRawMetric(DB_IO_READ_RATE_NAME).setCalculationMode(CalculationMode.RATE); + getRawMetric(DB_IO_WRITE_RATE_NAME).setCalculationMode(CalculationMode.RATE); + } + + private void findDbNameAndVersion() throws SQLException { + try (Connection connection = getConnection()) { + ResultSet rs = DbDcUtil.executeQuery(connection, DB_NAME_VERSION_SQL); + rs.next(); + if (getDbName() == null) + setDbName(rs.getString(1)); + setDbVersion(rs.getString(2)); + } + } + + @Override + public void collectData() { + logger.info("Start to collect metrics"); + try (Connection conn = getConnection()) { + + getRawMetric(DB_STATUS_NAME).setValue(1); + getRawMetric(DB_INSTANCE_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, INSTANCE_COUNT_SQL)); + getRawMetric(DB_INSTANCE_ACTIVE_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, INSTANCE_ACTIVE_COUNT_SQL)); + + getRawMetric(DB_SESSION_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, SESSION_COUNT_SQL)); + getRawMetric(DB_SESSION_ACTIVE_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, SESSION_ACTIVE_COUNT_SQL)); + getRawMetric(DB_TRANSACTION_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, TRANSACTION_COUNT_SQL)); + getRawMetric(DB_TRANSACTION_RATE_NAME).setValue(getSimpleMetricWithSql(conn, TRANSACTION_RATE_SQL)); + getRawMetric(DB_TRANSACTION_LATENCY_NAME).setValue(getSimpleMetricWithSql(conn, TRANSACTION_LATENCY_SQL)); + getRawMetric(DB_SQL_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, SQL_COUNT_SQL)); + getRawMetric(DB_SQL_RATE_NAME).setValue(getSimpleMetricWithSql(conn, SQL_RATE_SQL)); + getRawMetric(DB_IO_READ_RATE_NAME).setValue(getSimpleMetricWithSql(conn, IO_READ_COUNT_SQL)); + getRawMetric(DB_IO_WRITE_RATE_NAME).setValue(getSimpleMetricWithSql(conn, IO_WRITE_COUNT_SQL)); + getRawMetric(DB_TASK_WAIT_COUNT_NAME).setValue(getSimpleMetricWithSql(conn, TASK_WAIT_COUNT_SQL)); + getRawMetric(DB_TASK_AVG_WAIT_TIME_NAME).setValue(getSimpleMetricWithSql(conn, TASK_AVG_WAIT_TIME_SQL)); + getRawMetric(DB_CPU_UTILIZATION_NAME).setValue(getSimpleMetricWithSql(conn, CPU_UTILIZATION_SQL)); + getRawMetric(DB_MEM_UTILIZATION_NAME).setValue(getSimpleMetricWithSql(conn, MEMORY_UTILIZATION)); + }catch (Exception e) { + logger.log(Level.SEVERE, "Failed to update metric with exception", e); + getRawMetric(DB_STATUS_NAME).setValue(0); + } + + } +} diff --git a/rdb/src/main/java/com/instana/dc/rdb/impl/HanaUtil.java b/rdb/src/main/java/com/instana/dc/rdb/impl/HanaUtil.java new file mode 100644 index 0000000..5778b36 --- /dev/null +++ b/rdb/src/main/java/com/instana/dc/rdb/impl/HanaUtil.java @@ -0,0 +1,27 @@ +package com.instana.dc.rdb.impl; + +public class HanaUtil { + + public static final String DB_NAME_VERSION_SQL = "select DATABASE_NAME, VERSION from SYS.M_DATABASE"; + public static final String TRANSACTION_COUNT_SQL = "SELECT COUNT(*) AS transaction_count from M_TRANSACTIONS"; + + public static final String TRANSACTION_RATE_SQL = "SELECT CURRENT_TRANSACTION_RATE FROM SYS.M_WORKLOAD"; + public static final String TRANSACTION_LATENCY_SQL = "SELECT SUM(floor( mod( (seconds_between(START_TIME,END_TIME)) , 3600) / 60 ) ) AS TOTAL_TRANSACTION_LATENCY_SECONDS FROM M_TRANSACTIONS"; + + public static final String SQL_COUNT_SQL = "SELECT COUNT(*) AS sql_statement_count FROM M_SQL_PLAN_CACHE"; + public static final String SQL_RATE_SQL = "SELECT SUM(AVG_EXECUTION_FETCH_TIME) As latency FROM M_SQL_PLAN_CACHE"; + + public static final String IO_READ_COUNT_SQL = "SELECT EXECUTION_COUNT FROM SYS.M_WORKLOAD"; + public static final String IO_WRITE_COUNT_SQL = "SELECT EXECUTION_COUNT FROM SYS.M_WORKLOAD"; + public static final String TASK_WAIT_COUNT_SQL = "SELECT EXECUTION_COUNT FROM SYS.M_WORKLOAD"; + public static final String TASK_AVG_WAIT_TIME_SQL = "SELECT TOTAL_LOCK_WAIT_TIME FROM M_LOCK_WAITS_STATISTICS"; + + public static final String SESSION_COUNT_SQL = "SELECT COUNT(*) as TOTAL_SESSIONS FROM M_SESSION_CONTEXT"; + + public static final String SESSION_ACTIVE_COUNT_SQL = "SELECT COUNT(*) as TOTAL_SESSIONS FROM M_SESSION_CONTEXT"; + public static final String INSTANCE_COUNT_SQL = "SELECT COUNT(*) FROM SYS.M_SYSTEM_OVERVIEW where Name = 'All Started'"; + public static final String INSTANCE_ACTIVE_COUNT_SQL = "SELECT COUNT(*) FROM SYS.M_SYSTEM_OVERVIEW where Name = 'All Started'"; + public static final String CPU_UTILIZATION_SQL = "SELECT TOTAL_CPU_SYSTEM_TIME FROM SYS.M_HOST_RESOURCE_UTILIZATION"; + public static final String MEMORY_UTILIZATION = "SELECT USED_PHYSICAL_MEMORY FROM SYS.M_HOST_RESOURCE_UTILIZATION"; + +}