2424import java .sql .Connection ;
2525import java .sql .PreparedStatement ;
2626import java .sql .ResultSet ;
27- import java .time .Instant ;
2827import java .util .HashMap ;
2928import java .util .Map ;
3029
3332import org .slf4j .Logger ;
3433import org .slf4j .LoggerFactory ;
3534import org .springframework .beans .factory .annotation .Autowired ;
36- import org .springframework .beans .factory .annotation .Value ;
3735import org .springframework .data .redis .core .RedisCallback ;
3836import org .springframework .data .redis .core .RedisTemplate ;
3937import org .springframework .stereotype .Service ;
@@ -47,142 +45,75 @@ public class HealthService {
4745 @ Autowired
4846 private DataSource dataSource ;
4947
50- @ Value ("${app.version:unknown}" )
51- private String appVersion ;
52-
5348 @ Autowired (required = false )
5449 private RedisTemplate <String , Object > redisTemplate ;
5550
5651 public Map <String , Object > checkHealth () {
5752 Map <String , Object > healthStatus = new HashMap <>();
58- Map <String , Object > services = new HashMap <>();
5953 boolean overallHealth = true ;
6054
61- // Check database connectivity
62- Map <String , Object > dbStatus = checkDatabaseHealth ();
63- services .put ("database" , dbStatus );
64- if (!"UP" .equals (dbStatus .get ("status" ))) {
55+ // Check database connectivity (details logged internally, not exposed)
56+ boolean dbHealthy = checkDatabaseHealthInternal ();
57+ if (!dbHealthy ) {
6558 overallHealth = false ;
6659 }
6760
68- // Check Redis connectivity if configured
61+ // Check Redis connectivity if configured (details logged internally)
6962 if (redisTemplate != null ) {
70- Map <String , Object > redisStatus = checkRedisHealth ();
71- services .put ("redis" , redisStatus );
72- if (!"UP" .equals (redisStatus .get ("status" ))) {
63+ boolean redisHealthy = checkRedisHealthInternal ();
64+ if (!redisHealthy ) {
7365 overallHealth = false ;
7466 }
75- } else {
76- Map <String , Object > redisStatus = new HashMap <>();
77- redisStatus .put ("status" , "NOT_CONFIGURED" );
78- redisStatus .put ("message" , "Redis not configured for this environment" );
79- services .put ("redis" , redisStatus );
8067 }
8168
8269 healthStatus .put ("status" , overallHealth ? "UP" : "DOWN" );
83- healthStatus .put ("services" , services );
84- healthStatus .put ("timestamp" , Instant .now ().toString ());
85- healthStatus .put ("application" , "admin-api" );
86- healthStatus .put ("version" , appVersion );
8770
8871 logger .info ("Health check completed - Overall status: {}" , overallHealth ? "UP" : "DOWN" );
8972 return healthStatus ;
9073 }
9174
92- private Map <String , Object > checkDatabaseHealth () {
93- Map <String , Object > dbStatus = new HashMap <>();
75+ private boolean checkDatabaseHealthInternal () {
9476 long startTime = System .currentTimeMillis ();
9577
9678 try (Connection connection = dataSource .getConnection ()) {
97- // Test connection validity
98- boolean isConnectionValid = connection .isValid (5 ); // 5 second timeout
79+ boolean isConnectionValid = connection .isValid (2 ); // 2 second timeout per best practices
9980
10081 if (isConnectionValid ) {
101- // Execute a simple query to ensure database is responsive
102- try (PreparedStatement stmt = connection .prepareStatement (DB_HEALTH_CHECK_QUERY );
103- ResultSet rs = stmt .executeQuery ()) {
104-
105- if (rs .next () && rs .getInt (1 ) == 1 ) {
106- long responseTime = System .currentTimeMillis () - startTime ;
107-
108- dbStatus .put ("status" , "UP" );
109- dbStatus .put ("responseTime" , responseTime + "ms" );
110- dbStatus .put ("message" , "Database connection successful" );
111-
112- logger .debug ("Database health check: UP ({}ms)" , responseTime );
113- } else {
114- dbStatus .put ("status" , "DOWN" );
115- dbStatus .put ("message" , "Database query returned unexpected result" );
116- logger .warn ("Database health check: Query returned unexpected result" );
82+ try (PreparedStatement stmt = connection .prepareStatement (DB_HEALTH_CHECK_QUERY )) {
83+ stmt .setQueryTimeout (3 ); // 3 second query timeout
84+ try (ResultSet rs = stmt .executeQuery ()) {
85+ if (rs .next () && rs .getInt (1 ) == 1 ) {
86+ long responseTime = System .currentTimeMillis () - startTime ;
87+ logger .debug ("Database health check: UP ({}ms)" , responseTime );
88+ return true ;
89+ }
11790 }
11891 }
119- } else {
120- dbStatus .put ("status" , "DOWN" );
121- dbStatus .put ("message" , "Database connection is not valid" );
122- logger .warn ("Database health check: Connection is not valid" );
12392 }
124-
93+ logger .warn ("Database health check: Connection not valid" );
94+ return false ;
12595 } catch (Exception e ) {
126- long responseTime = System .currentTimeMillis () - startTime ;
127- dbStatus .put ("status" , "DOWN" );
128- dbStatus .put ("responseTime" , responseTime + "ms" );
129- dbStatus .put ("error" , e .getClass ().getSimpleName ());
130-
131- logger .error ("Database health check failed: {}" , e .getMessage (), e );
96+ logger .error ("Database health check failed: {}" , e .getMessage ());
97+ return false ;
13298 }
133-
134- return dbStatus ;
13599 }
136100
137- private Map <String , Object > checkRedisHealth () {
138- Map <String , Object > redisStatus = new HashMap <>();
101+ private boolean checkRedisHealthInternal () {
139102 long startTime = System .currentTimeMillis ();
140103
141104 try {
142- // Test Redis connection with ping using explicit RedisCallback
143- String pong = redisTemplate .execute ((RedisCallback <String >) connection -> {
144- return connection .ping ();
145- });
105+ String pong = redisTemplate .execute ((RedisCallback <String >) connection -> connection .ping ());
146106
147107 if ("PONG" .equals (pong )) {
148108 long responseTime = System .currentTimeMillis () - startTime ;
149-
150- // Additional test: set and get a test key
151- String testKey = "health:check:" + System .currentTimeMillis ();
152- String testValue = "test-value" ;
153-
154- redisTemplate .opsForValue ().set (testKey , testValue );
155- Object retrievedValue = redisTemplate .opsForValue ().get (testKey );
156- redisTemplate .delete (testKey ); // Clean up test key
157-
158- if (testValue .equals (retrievedValue )) {
159- redisStatus .put ("status" , "UP" );
160- redisStatus .put ("responseTime" , responseTime + "ms" );
161- redisStatus .put ("message" , "Redis connection and operations successful" );
162- redisStatus .put ("ping" , "PONG" );
163-
164- logger .debug ("Redis health check: UP ({}ms)" , responseTime );
165- } else {
166- redisStatus .put ("status" , "DOWN" );
167- redisStatus .put ("message" , "Redis set/get operation failed" );
168- logger .warn ("Redis health check: Set/Get operation failed" );
169- }
170- } else {
171- redisStatus .put ("status" , "DOWN" );
172- redisStatus .put ("message" , "Redis ping returned: " + pong );
173- logger .warn ("Redis health check: Ping returned unexpected response: {}" , pong );
109+ logger .debug ("Redis health check: UP ({}ms)" , responseTime );
110+ return true ;
174111 }
175-
112+ logger .warn ("Redis health check: Ping returned unexpected response" );
113+ return false ;
176114 } catch (Exception e ) {
177- long responseTime = System .currentTimeMillis () - startTime ;
178- redisStatus .put ("status" , "DOWN" );
179- redisStatus .put ("message" , "Redis connection failed" );
180- redisStatus .put ("responseTime" , responseTime + "ms" );
181- redisStatus .put ("error" , e .getClass ().getSimpleName ());
182-
183- logger .error ("Redis health check failed" , e );
115+ logger .error ("Redis health check failed: {}" , e .getMessage ());
116+ return false ;
184117 }
185-
186- return redisStatus ;
187118 }
188119}
0 commit comments