Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e84d067
feat: add Micrometer KafkaClientMetrics to KafkaMessageReader
jamespfaulkner Jun 8, 2026
42797a7
chore: ignore dependency-reduced-pom.xml maven shade artifact
jamespfaulkner Jun 8, 2026
7de7eaa
feat: add tagged outcome counters to ApiaryGlueSync event handlers
jamespfaulkner Jun 8, 2026
71f8cb8
refactor: redesign gluesync tagged metrics to single counter with Tag…
jamespfaulkner Jun 8, 2026
5f34706
refactor: replace Tag.of chains with MetricService.recordEvent
jamespfaulkner Jun 8, 2026
99a6c64
fix: fill observability gaps in ApiaryGlueSync
jamespfaulkner Jun 10, 2026
fa7201f
fix: align KafkaMessageReader metrics with GlueSync JMX/Spring Boot p…
jamespfaulkner Jun 17, 2026
e2eb03e
fix: log when JmxMeterRegistry is auto-registered in KafkaMessageReader
jamespfaulkner Jun 17, 2026
208de29
fix: bound metric tag cardinality in ApiaryGlueSync failure paths
jamespfaulkner Jun 18, 2026
1a50fac
fix: prevent duplicate JmxMeterRegistry registration under concurrent…
jamespfaulkner Jun 18, 2026
99d2bd1
fix: ensure consumer.close() is called if kafkaClientMetrics.close() …
jamespfaulkner Jun 18, 2026
65a278e
fix: cache recordEvent counters to avoid per-call Tags allocation in …
jamespfaulkner Jun 18, 2026
e4946bc
refactor: extract GlueOutcome enum and private helpers for create/upd…
jamespfaulkner Jun 18, 2026
ebc4daa
refactor: apply GlueOutcome enum pattern to onAddPartition
jamespfaulkner Jun 18, 2026
854f548
test: add coverage for recovery paths in ApiaryGlueSync and fix outco…
jamespfaulkner Jun 18, 2026
f15b9de
test: add onDropTable tests and a single ignored-event test covering …
jamespfaulkner Jun 19, 2026
20bdb8f
test: add onDropPartition happy path, generic failure, and throwExcep…
jamespfaulkner Jun 19, 2026
6b8a1a0
test: add onAddPartition happy path, Iceberg rename, and rename failu…
jamespfaulkner Jun 19, 2026
9aa1c90
chore: reorder static imports in MetricService and tighten KafkaMessa…
jamespfaulkner Jun 19, 2026
a3d6b18
chore: align .sdkmanrc with project Java 8 source/target
jamespfaulkner Jun 19, 2026
9b698f9
fix: replace GlueOutcome enum with lowercase string constants and doc…
jamespfaulkner Jun 19, 2026
6f3b10e
chore: update changelog for 8.1.19
jamespfaulkner Jun 19, 2026
84e8fdb
fix: replace List.of() with Arrays.asList() for Java 8 compatibility
jamespfaulkner Jun 19, 2026
39f0315
fix: use simple name string matching in toOutcome to survive Maven sh…
jamespfaulkner Jun 19, 2026
fe9f09d
feat: expose Micrometer tags as JMX ObjectName key properties via Tag…
jamespfaulkner Jun 19, 2026
5ce4c5d
docs: clarify configuredRegistry divergence between MetricService and…
jamespfaulkner Jun 19, 2026
bd07cc6
chore: reorder imports in MetricService and MetricServiceTest
jamespfaulkner Jun 23, 2026
3cbe132
chore: log existing registry when skipping JmxMeterRegistry in KafkaM…
jamespfaulkner Jun 23, 2026
4c9b9e9
chore: bump version to 8.2.0-SNAPSHOT
jamespfaulkner Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ dependency-reduced-pom.xml

# Jenv file
.java-version

# Maven shade plugin artifact
dependency-reduced-pom.xml
1 change: 1 addition & 0 deletions .sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
java=8.0.472-amzn
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 8.2.0 - TBD
### Added
- `apiary-gluesync-listener`: per-event observability via a new `glue_listener_event` Micrometer counter, tagged with `operation` (e.g. `create_table`), `result` (`success`, `failure`, `ignored`), and `outcome` (e.g. `created`, `updated`, `deleted`, `not_found`, `renamed`, exception class name). Covers all 8 HMS event handlers. A `glue_listener_table_rename_duration` timer is also recorded on every table rename.
- `kafka-metastore-receiver`: Kafka consumer metrics via Micrometer `KafkaClientMetrics`. Bind a registry at build time with `KafkaMessageReaderBuilder.withMeterRegistry(registry)`.
### Fixed
- `apiary-gluesync-listener`: fallback Glue operations (update-after-`AlreadyExistsException`, create-after-`EntityNotFoundException`) that previously escaped their catch blocks unhandled are now consistently caught, logged, and metered by the outer exception handler.
### Changed
- Bump Micrometer from `1.9.9` to `1.14.14`.

## 8.1.18 - 2026-06-09
### Fixed
- `apiary-gluesync-listener`: glue sync metrics were silently dropped in HMS deployments; counters are now exported via JMX. In framework deployments (e.g. Dronefly/Spring Boot), metrics continue to flow to the existing registry (e.g. Prometheus) unchanged.
Expand Down
2 changes: 1 addition & 1 deletion apiary-metastore-events/apiary-hive-events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-hive-events</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kafka-metastore-events-parent</artifactId>
<groupId>com.expediagroup.apiary</groupId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>kafka-metastore-integration-tests</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>kafka-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>kafka-metastore-listener</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kafka-metastore-events-parent</artifactId>
<groupId>com.expediagroup.apiary</groupId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>kafka-metastore-receiver</artifactId>
Expand All @@ -22,6 +22,14 @@
<artifactId>kafka-clients</artifactId>
<version>${kafka.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-jmx</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2018-2020 Expedia, Inc.
* Copyright (C) 2018-2026 Expedia, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,6 +28,15 @@

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.binder.kafka.KafkaClientMetrics;
import io.micrometer.jmx.JmxConfig;
import io.micrometer.jmx.JmxMeterRegistry;

import com.google.common.annotations.VisibleForTesting;

Expand All @@ -37,21 +46,27 @@

public class KafkaMessageReader implements Iterator<ApiaryListenerEvent>, Closeable {

private static final Logger log = LoggerFactory.getLogger(KafkaMessageReader.class);
private static final Duration POLL_TIMEOUT = Duration.ofMinutes(5);

private KafkaConsumer<Long, byte[]> consumer;
private MetaStoreEventSerDe eventSerDe;
private Iterator<ConsumerRecord<Long, byte[]>> records;
private KafkaClientMetrics kafkaClientMetrics;

private KafkaMessageReader(String topicName, MetaStoreEventSerDe eventSerDe, Properties consumerProperties) {
this(topicName, eventSerDe, new KafkaConsumer(consumerProperties));
private KafkaMessageReader(String topicName, MetaStoreEventSerDe eventSerDe, Properties consumerProperties, MeterRegistry meterRegistry) {
this(topicName, eventSerDe, new KafkaConsumer(consumerProperties), meterRegistry);
}

@VisibleForTesting
KafkaMessageReader(String topicName, MetaStoreEventSerDe eventSerDe, KafkaConsumer<Long, byte[]> consumer) {
KafkaMessageReader(String topicName, MetaStoreEventSerDe eventSerDe, KafkaConsumer<Long, byte[]> consumer, MeterRegistry meterRegistry) {
this.eventSerDe = eventSerDe;
this.consumer = consumer;
this.consumer.subscribe(Collections.singletonList(topicName));
if (meterRegistry != null) {
this.kafkaClientMetrics = new KafkaClientMetrics(consumer);
this.kafkaClientMetrics.bindTo(meterRegistry);
}
}

@Override
Expand All @@ -73,7 +88,13 @@ public void remove() {

@Override
public void close() {
consumer.close();
try {
if (kafkaClientMetrics != null) {
kafkaClientMetrics.close();
}
} finally {
consumer.close();
}
}

private void readRecordsIfNeeded() {
Expand All @@ -89,6 +110,7 @@ public static final class KafkaMessageReaderBuilder {
private String groupId = "apiary-kafka-metastore-receiver-";
private MetaStoreEventSerDe metaStoreEventSerDe = new JsonMetaStoreEventSerDe();
private Properties consumerProperties = new Properties();
private MeterRegistry meterRegistry;

private KafkaMessageReaderBuilder(String bootstrapServers, String topicName, String applicationName) {
this.bootstrapServers = bootstrapServers;
Expand All @@ -114,14 +136,36 @@ public KafkaMessageReaderBuilder withConsumerProperties(Properties consumerPrope
return this;
}

public KafkaMessageReaderBuilder withMeterRegistry(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
return this;
}

public KafkaMessageReader build() {
Properties props = new Properties();
props.put(BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(GROUP_ID_CONFIG, groupId);
props.put("key.deserializer", "org.apache.kafka.common.serialization.LongDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.ByteArrayDeserializer");
consumerProperties.forEach((key, value) -> props.merge(key, value, (v1, v2) -> v1));
return new KafkaMessageReader(topicName, metaStoreEventSerDe, props);
MeterRegistry registry = meterRegistry != null ? meterRegistry : configuredRegistry();
return new KafkaMessageReader(topicName, metaStoreEventSerDe, props, registry);
}

// DO NOT extract to a shared utility. MetricService in apiary-gluesync-listener has a
// similar method, but the two implementations intentionally differ: that module shades and
// relocates micrometer-jmx for HMS classpath isolation, and uses a Dropwizard-backed
// JmxMeterRegistry with TaggedObjectNameFactory for tagged JMX ObjectName properties. This
// module runs outside HMS and uses a plain JmxMeterRegistry without tag promotion.
// Each module must own its own copy.
private static synchronized MeterRegistry configuredRegistry() {
if (Metrics.globalRegistry.getRegistries().isEmpty()) {
log.info("No MeterRegistry found; registering JmxMeterRegistry for Kafka consumer metrics");
Metrics.addRegistry(new JmxMeterRegistry(JmxConfig.DEFAULT, Clock.SYSTEM));
} else {
log.info("Using existing MeterRegistry for Kafka consumer metrics: {}", Metrics.globalRegistry);
}
return Metrics.globalRegistry;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2018-2020 Expedia, Inc.
* Copyright (C) 2018-2026 Expedia, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -37,6 +37,8 @@
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import io.micrometer.core.instrument.simple.SimpleMeterRegistry;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

Expand All @@ -60,17 +62,19 @@ public class KafkaMessageReaderTest {

private ConsumerRecords<Long, byte[]> messages;
private KafkaMessageReader reader;
private SimpleMeterRegistry meterRegistry;

@Before
public void init() {
meterRegistry = new SimpleMeterRegistry();
List<ConsumerRecord<Long, byte[]>> messageList = ImmutableList.of(message);
Map<TopicPartition, List<ConsumerRecord<Long, byte[]>>> messageMap = ImmutableMap
.of(new TopicPartition(TOPIC_NAME, PARTITION), messageList);
messages = new ConsumerRecords<>(messageMap);
when(consumer.poll(any(Duration.class))).thenReturn(messages);
when(message.value()).thenReturn(MESSAGE_CONTENT);
when(serDe.unmarshal(MESSAGE_CONTENT)).thenReturn(event);
reader = new KafkaMessageReader(TOPIC_NAME, serDe, consumer);
reader = new KafkaMessageReader(TOPIC_NAME, serDe, consumer, meterRegistry);
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion apiary-metastore-events/kafka-metastore-events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>kafka-metastore-events-parent</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion apiary-metastore-events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-extensions-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-metastore-events-parent</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-metastore-consumers-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>metastore-consumer-common</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>sns-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-metastore-consumers-parent</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-metastore-consumers-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-privileges-grantor-parent</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-privileges-grantor-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-privileges-grantor-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-privileges-grantor-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-privileges-grantor-lambda</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>sns-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-metastore-listener</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-receivers-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-receiver-common</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-receivers-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-receiver-sqs</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>sns-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-receivers-parent</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion apiary-metastore-events/sns-metastore-events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-metastore-events-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>sns-metastore-events-parent</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion apiary-metastore-metrics/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>apiary-extensions-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>

<artifactId>apiary-metastore-metrics</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion hive-event-listeners/apiary-gluesync-listener/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.expediagroup.apiary</groupId>
<artifactId>hive-event-listeners-parent</artifactId>
<version>8.1.19-SNAPSHOT</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
<artifactId>apiary-gluesync-listener</artifactId>
<name>Apiary GlueSync Listener</name>
Expand Down
Loading
Loading