-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #262 from GetFeedback/feature/introduce-kafka-stre…
…ams-health-checks Feature/introduce kafka streams health checks
- Loading branch information
Showing
6 changed files
with
195 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
...utoconfigure/src/main/java/dev/vox/platform/kahpp/actuator/KafkaStreamsProducerState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package dev.vox.platform.kahpp.actuator; | ||
|
||
import io.micrometer.core.instrument.FunctionCounter; | ||
import io.micrometer.core.instrument.MeterRegistry; | ||
import io.micrometer.core.instrument.search.Search; | ||
import java.util.Optional; | ||
import org.springframework.boot.actuate.health.AbstractHealthIndicator; | ||
import org.springframework.boot.actuate.health.Health; | ||
import org.springframework.boot.actuate.health.Status; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class KafkaStreamsProducerState extends AbstractHealthIndicator { | ||
|
||
private final MeterRegistry meterRegistry; | ||
|
||
public static final String KAFKA_PRODUCER_CONNECTION_METRIC_LABEL = | ||
"kafka.producer.connection.count"; | ||
|
||
public KafkaStreamsProducerState(MeterRegistry meterRegistry) { | ||
this.meterRegistry = meterRegistry; | ||
} | ||
|
||
@Override | ||
protected void doHealthCheck(Health.Builder builder) { | ||
Search connectionsSearch = meterRegistry.find(KAFKA_PRODUCER_CONNECTION_METRIC_LABEL); | ||
Double kafkaConnections = | ||
Optional.ofNullable(connectionsSearch.functionCounter()) | ||
.map(FunctionCounter::count) | ||
.orElse(0d); | ||
if (kafkaConnections > 0) { | ||
builder.status(Status.UP); | ||
return; | ||
} | ||
builder.status(Status.DOWN); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...spring-autoconfigure/src/main/java/dev/vox/platform/kahpp/actuator/KafkaStreamsState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package dev.vox.platform.kahpp.actuator; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import org.apache.kafka.streams.KafkaStreams; | ||
import org.springframework.boot.actuate.health.AbstractHealthIndicator; | ||
import org.springframework.boot.actuate.health.Health; | ||
import org.springframework.boot.actuate.health.Status; | ||
import org.springframework.kafka.config.StreamsBuilderFactoryBean; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class KafkaStreamsState extends AbstractHealthIndicator { | ||
|
||
private final List<StreamsBuilderFactoryBean> streamsBuilders; | ||
|
||
public KafkaStreamsState(List<StreamsBuilderFactoryBean> streamsBuilders) { | ||
this.streamsBuilders = List.copyOf(streamsBuilders); | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("PMD.CloseResource") | ||
protected void doHealthCheck(Health.Builder builder) { | ||
List<KafkaStreams> streamsList = | ||
streamsBuilders.stream() | ||
.map(StreamsBuilderFactoryBean::getKafkaStreams) | ||
.filter(Objects::nonNull) | ||
.toList(); | ||
|
||
if (streamsList.isEmpty()) { | ||
builder.status(Status.UNKNOWN); | ||
return; | ||
} | ||
|
||
for (KafkaStreams streams : streamsList) { | ||
if (streams.state().hasNotStarted()) { | ||
builder.status(Status.UNKNOWN); | ||
return; | ||
} else if (!streams.state().isRunningOrRebalancing()) { | ||
builder.status(Status.DOWN); | ||
return; | ||
} | ||
} | ||
|
||
builder.status(Status.UP); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
...onfigure/src/test/java/dev/vox/platform/kahpp/actuator/KafkaStreamsProducerStateTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package dev.vox.platform.kahpp.actuator; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import io.micrometer.core.instrument.*; | ||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.boot.actuate.health.Health; | ||
import org.springframework.boot.actuate.health.Status; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class KafkaStreamsProducerStateTest { | ||
|
||
private MeterRegistry meterRegistry; | ||
|
||
@BeforeEach | ||
public void setUp() { | ||
meterRegistry = new SimpleMeterRegistry(); | ||
} | ||
|
||
@Test | ||
void statusDownWhenProducerIsNotActive() { | ||
meterRegistry | ||
.more() | ||
.counter(KafkaStreamsProducerState.KAFKA_PRODUCER_CONNECTION_METRIC_LABEL, Tags.empty(), 0); | ||
Health.Builder builder = new Health.Builder(); | ||
new KafkaStreamsProducerState(meterRegistry).doHealthCheck(builder); | ||
assertThat(builder.build().getStatus()).isEqualTo(Status.DOWN); | ||
} | ||
|
||
@Test | ||
void statusUpWhenProducerIsActive() { | ||
meterRegistry | ||
.more() | ||
.counter(KafkaStreamsProducerState.KAFKA_PRODUCER_CONNECTION_METRIC_LABEL, Tags.empty(), 1); | ||
Health.Builder builder = new Health.Builder(); | ||
new KafkaStreamsProducerState(meterRegistry).doHealthCheck(builder); | ||
assertThat(builder.build().getStatus()).isEqualTo(Status.UP); | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
...ng-autoconfigure/src/test/java/dev/vox/platform/kahpp/actuator/KafkaStreamsStateTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package dev.vox.platform.kahpp.actuator; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.mockito.Mockito.lenient; | ||
import static org.mockito.Mockito.when; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
import org.apache.kafka.streams.KafkaStreams; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.boot.actuate.health.Health; | ||
import org.springframework.boot.actuate.health.Status; | ||
import org.springframework.kafka.config.StreamsBuilderFactoryBean; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class KafkaStreamsStateTest { | ||
|
||
@Mock private StreamsBuilderFactoryBean streamsBuilderFactoryBean; | ||
|
||
@Mock private KafkaStreams kafkaStreams; | ||
|
||
Map<KafkaStreams.State, Status> kafkaStateMapping = | ||
Map.of( | ||
KafkaStreams.State.CREATED, Status.UNKNOWN, | ||
KafkaStreams.State.RUNNING, Status.UP, | ||
KafkaStreams.State.REBALANCING, Status.UP, | ||
KafkaStreams.State.ERROR, Status.DOWN, | ||
KafkaStreams.State.PENDING_ERROR, Status.DOWN, | ||
KafkaStreams.State.PENDING_SHUTDOWN, Status.DOWN, | ||
KafkaStreams.State.NOT_RUNNING, Status.DOWN); | ||
|
||
@BeforeEach | ||
public void setUp() { | ||
lenient().when(streamsBuilderFactoryBean.getKafkaStreams()).thenReturn(kafkaStreams); | ||
} | ||
|
||
@Test | ||
void checkIfStatusIsUnknownWhenStreamsIsNull() { | ||
Health.Builder builder = new Health.Builder(); | ||
new KafkaStreamsState(List.of()).doHealthCheck(builder); | ||
assertThat(builder.build().getStatus()).isEqualTo(Status.UNKNOWN); | ||
} | ||
|
||
@Test | ||
@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") | ||
void checkAllKafkaStreamsStatuses() { | ||
KafkaStreamsState kafkaStreamsState = new KafkaStreamsState(List.of(streamsBuilderFactoryBean)); | ||
Health.Builder builder = new Health.Builder(); | ||
|
||
new KafkaStreamsState(List.of(streamsBuilderFactoryBean)); | ||
Arrays.stream(KafkaStreams.State.values()) | ||
.forEach( | ||
state -> { | ||
when(kafkaStreams.state()).thenReturn(state); | ||
kafkaStreamsState.doHealthCheck(builder); | ||
assertThat(builder.build().getStatus()) | ||
.as("Testing %s Kafka Stream State", state) | ||
.isEqualTo(kafkaStateMapping.get(state)); | ||
}); | ||
} | ||
} |