From 565ee02f587f35b3849f8604e575e3bc26ac87a5 Mon Sep 17 00:00:00 2001 From: muskan124947 Date: Fri, 20 Dec 2024 13:03:12 +0530 Subject: [PATCH] Capture Client Guest OS and architecture in JDBC (#2561) * Capture Client Guest OS and architecture in JDBC * Added app name with format Microsoft JDBC - {os}, {platform} - {arch} * Adding log info and getAppNameWithProperties() * Updated the application name to be set dynamically * Added log level as FINE * Added test case to verify application name * Updated the SQLServerDriverPropertyInfo with default name * Added static block for initialization * Added test case for code coverage * Updated app Name --- .../sqlserver/jdbc/SQLServerConnection.java | 2 +- .../sqlserver/jdbc/SQLServerDriver.java | 31 ++++++++++++++- .../sqlserver/jdbc/SQLServerDriverTest.java | 38 +++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 6874deab4..42ae6647d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -2446,7 +2446,7 @@ Connection connectInternal(Properties propsIn, if (null != sPropValue) validateMaxSQLLoginName(sPropKey, sPropValue); else - activeConnectionProperties.setProperty(sPropKey, SQLServerDriver.DEFAULT_APP_NAME); + activeConnectionProperties.setProperty(sPropKey, SQLServerDriver.constructedAppName); sPropKey = SQLServerDriverBooleanProperty.LAST_UPDATE_COUNT.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index e4b1d59ee..833368169 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -731,7 +731,32 @@ public final class SQLServerDriver implements java.sql.Driver { static final String AUTH_DLL_NAME = "mssql-jdbc_auth-" + SQLJdbcVersion.MAJOR + "." + SQLJdbcVersion.MINOR + "." + SQLJdbcVersion.PATCH + "." + Util.getJVMArchOnWindows() + SQLJdbcVersion.RELEASE_EXT; static final String DEFAULT_APP_NAME = "Microsoft JDBC Driver for SQL Server"; + static final String APP_NAME_TEMPLATE = "Microsoft JDBC - %s, %s - %s"; + static final String constructedAppName; + static { + constructedAppName = getAppName(); + } + /** + * Constructs the application name using system properties for OS, platform, and architecture. + * If any of the properties cannot be fetched, it falls back to the default application name. + * Format -> Microsoft JDBC - {OS}, {Platform} - {architecture} + * + * @return the constructed application name or the default application name if properties are not available + */ + static String getAppName() { + String osName = System.getProperty("os.name", ""); + String osArch = System.getProperty("os.arch", ""); + String javaVmName = System.getProperty("java.vm.name", ""); + String javaVmVersion = System.getProperty("java.vm.version", ""); + String platform = javaVmName.isEmpty() || javaVmVersion.isEmpty() ? "" : javaVmName + " " + javaVmVersion; + + if (osName.isEmpty() && platform.isEmpty() && osArch.isEmpty()) { + return DEFAULT_APP_NAME; + } + return String.format(APP_NAME_TEMPLATE, osName, platform, osArch); + } + private static final String[] TRUE_FALSE = {"true", "false"}; private static final SQLServerDriverPropertyInfo[] DRIVER_PROPERTIES = { @@ -741,7 +766,7 @@ public final class SQLServerDriver implements java.sql.Driver { SQLServerDriverStringProperty.APPLICATION_INTENT.getDefaultValue(), false, new String[] {ApplicationIntent.READ_ONLY.toString(), ApplicationIntent.READ_WRITE.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.APPLICATION_NAME.toString(), - SQLServerDriverStringProperty.APPLICATION_NAME.getDefaultValue(), false, null), + SQLServerDriverStringProperty.APPLICATION_NAME.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.COLUMN_ENCRYPTION.toString(), SQLServerDriverStringProperty.COLUMN_ENCRYPTION.getDefaultValue(), false, new String[] {ColumnEncryptionSetting.DISABLED.toString(), @@ -1028,6 +1053,9 @@ String getClassNameLogging() { drLogger.finer("Error registering driver: " + e); } } + if (loggerExternal.isLoggable(Level.FINE)) { + loggerExternal.log(Level.FINE, "Application Name: " + SQLServerDriver.constructedAppName); + } } // Check for jdk.net.ExtendedSocketOptions to set TCP keep-alive options for idle connection resiliency @@ -1266,6 +1294,7 @@ public java.sql.Connection connect(String url, Properties suppliedProperties) th Properties connectProperties = parseAndMergeProperties(url, suppliedProperties); if (connectProperties != null) { result = DriverJDBCVersion.getSQLServerConnection(toString()); + connectProperties.setProperty(SQLServerDriverStringProperty.APPLICATION_NAME.toString(), SQLServerDriver.constructedAppName); result.connect(connectProperties, null); } loggerExternal.exiting(getClassNameLogging(), "connect", result); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerDriverTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerDriverTest.java index 5309780ca..2d2fee89d 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerDriverTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerDriverTest.java @@ -2,6 +2,8 @@ import static org.junit.Assert.fail; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; @@ -190,4 +192,40 @@ public void testConnectionDriver() throws SQLException { } } } + + /** + * test application name + * + * @throws SQLException + */ + @Test + public void testApplicationName() throws SQLException { + try (Connection conn = DriverManager.getConnection(connectionString); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT program_name FROM sys.dm_exec_sessions WHERE session_id = @@SPID")) { + if (rs.next()) { + assertEquals(SQLServerDriver.constructedAppName, rs.getString("program_name")); + } + } catch (SQLException e) { + fail(e.getMessage()); + } + } + + /** + * test application name when system properties are empty + * + */ + @Test + public void testGetAppName() { + String appName = SQLServerDriver.getAppName(); + assertNotNull(appName, "Application name should not be null"); + assertFalse(appName.isEmpty(), "Application name should not be empty"); + + System.setProperty("os.name", ""); + System.setProperty("os.arch", ""); + System.setProperty("java.vm.name", ""); + System.setProperty("java.vm.version", ""); + String defaultAppName = SQLServerDriver.getAppName(); + assertEquals(SQLServerDriver.DEFAULT_APP_NAME, defaultAppName, "Application name should be the default one"); + } }