Repository navigation
Flink: Do not ship optional flink-metrics-dropwizard dependency #16155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e3b7547
4abf18e
f519d2c
e638ad8
8f854aa
8c00e4a
bc07ad2
e8a911a
fd6cdea
2175b24
eafdbbe
b954ec1
91491f8
8e99f1b
63971c0
b43f620
d11e165
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,23 +18,33 @@ | |
| */ | ||
| package org.apache.iceberg.flink.sink; | ||
|
|
||
| import com.codahale.metrics.SlidingWindowReservoir; | ||
| import java.util.Arrays; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
| import org.apache.flink.annotation.Internal; | ||
| import org.apache.flink.dropwizard.metrics.DropwizardHistogramWrapper; | ||
| import org.apache.flink.annotation.VisibleForTesting; | ||
| import org.apache.flink.metrics.Counter; | ||
| import org.apache.flink.metrics.Histogram; | ||
| import org.apache.flink.metrics.MetricGroup; | ||
| import org.apache.iceberg.common.DynClasses; | ||
| import org.apache.iceberg.common.DynConstructors; | ||
| import org.apache.iceberg.io.WriteResult; | ||
| import org.apache.iceberg.util.ScanTaskUtil; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| @Internal | ||
| public class IcebergStreamWriterMetrics { | ||
|
|
||
| private static final Logger LOG = LoggerFactory.getLogger(IcebergStreamWriterMetrics.class); | ||
|
|
||
| // 1,024 reservoir size should cost about 8KB, which is quite small. | ||
| // It should also produce good accuracy for histogram distribution (like percentiles). | ||
| private static final int HISTOGRAM_RESERVOIR_SIZE = 1024; | ||
|
|
||
| // Histogram metrics loaded through Flink's optional flink-metrics-dropwizard dependency. | ||
| // Will be null if not available. | ||
| private static final DropwizardCtors DROPWIZARD = loadDropwizardCtors(); | ||
|
|
||
| private final Counter flushedDataFiles; | ||
| private final Counter flushedDeleteFiles; | ||
| private final Counter flushedReferencedDataFiles; | ||
|
|
@@ -51,18 +61,8 @@ public IcebergStreamWriterMetrics(MetricGroup metrics, String fullTableName) { | |
| this.lastFlushDurationMs = new AtomicLong(); | ||
| writerMetrics.gauge("lastFlushDurationMs", lastFlushDurationMs::get); | ||
|
|
||
| com.codahale.metrics.Histogram dropwizardDataFilesSizeHistogram = | ||
| new com.codahale.metrics.Histogram(new SlidingWindowReservoir(HISTOGRAM_RESERVOIR_SIZE)); | ||
| this.dataFilesSizeHistogram = | ||
| writerMetrics.histogram( | ||
| "dataFilesSizeHistogram", | ||
| new DropwizardHistogramWrapper(dropwizardDataFilesSizeHistogram)); | ||
| com.codahale.metrics.Histogram dropwizardDeleteFilesSizeHistogram = | ||
| new com.codahale.metrics.Histogram(new SlidingWindowReservoir(HISTOGRAM_RESERVOIR_SIZE)); | ||
| this.deleteFilesSizeHistogram = | ||
| writerMetrics.histogram( | ||
| "deleteFilesSizeHistogram", | ||
| new DropwizardHistogramWrapper(dropwizardDeleteFilesSizeHistogram)); | ||
| this.dataFilesSizeHistogram = registerHistogram(writerMetrics, "dataFilesSizeHistogram"); | ||
| this.deleteFilesSizeHistogram = registerHistogram(writerMetrics, "deleteFilesSizeHistogram"); | ||
| } | ||
|
|
||
| public void updateFlushResult(WriteResult result) { | ||
|
|
@@ -74,16 +74,21 @@ public void updateFlushResult(WriteResult result) { | |
| // This should works equally well and we avoided the overhead of tracking the list of file sizes | ||
| // in the {@link CommitSummary}, which currently stores simple stats for counters and gauges | ||
| // metrics. | ||
| Arrays.stream(result.dataFiles()) | ||
| .forEach( | ||
| dataFile -> { | ||
| dataFilesSizeHistogram.update(dataFile.fileSizeInBytes()); | ||
| }); | ||
| Arrays.stream(result.deleteFiles()) | ||
| .forEach( | ||
| deleteFile -> { | ||
| deleteFilesSizeHistogram.update(ScanTaskUtil.contentSizeInBytes(deleteFile)); | ||
| }); | ||
| if (dataFilesSizeHistogram != null) { | ||
| Arrays.stream(result.dataFiles()) | ||
| .forEach( | ||
| dataFile -> { | ||
| dataFilesSizeHistogram.update(dataFile.fileSizeInBytes()); | ||
| }); | ||
| } | ||
|
|
||
| if (deleteFilesSizeHistogram != null) { | ||
| Arrays.stream(result.deleteFiles()) | ||
| .forEach( | ||
| deleteFile -> { | ||
| deleteFilesSizeHistogram.update(ScanTaskUtil.contentSizeInBytes(deleteFile)); | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| public void flushDuration(long flushDurationMs) { | ||
|
|
@@ -97,4 +102,60 @@ public Counter getFlushedDataFiles() { | |
| public Counter getFlushedDeleteFiles() { | ||
| return flushedDeleteFiles; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| Histogram dataFilesSizeHistogram() { | ||
| return dataFilesSizeHistogram; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| Histogram deleteFilesSizeHistogram() { | ||
| return deleteFilesSizeHistogram; | ||
| } | ||
|
|
||
| private static Histogram registerHistogram(MetricGroup group, String name) { | ||
| Histogram histogram = newDropwizardHistogram(); | ||
| return histogram != null ? group.histogram(name, histogram) : null; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, |
||
| } | ||
|
|
||
| private static Histogram newDropwizardHistogram() { | ||
| if (DROPWIZARD == null) { | ||
| return null; | ||
| } | ||
|
|
||
| Object reservoir = DROPWIZARD.reservoirCtor.newInstance(HISTOGRAM_RESERVOIR_SIZE); | ||
| Object codahaleHistogram = DROPWIZARD.histogramCtor.newInstance(reservoir); | ||
| return DROPWIZARD.wrapperCtor.newInstance(codahaleHistogram); | ||
| } | ||
|
|
||
| private static DropwizardCtors loadDropwizardCtors() { | ||
| try { | ||
| Class<?> reservoirInterface = | ||
| DynClasses.builder().impl("com.codahale.metrics.Reservoir").buildChecked(); | ||
| Class<?> codahaleHistogramClass = | ||
| DynClasses.builder().impl("com.codahale.metrics.Histogram").buildChecked(); | ||
| return new DropwizardCtors( | ||
| DynConstructors.builder() | ||
| .impl("com.codahale.metrics.SlidingWindowReservoir", int.class) | ||
| .buildChecked(), | ||
| DynConstructors.builder() | ||
|
mxm marked this conversation as resolved.
|
||
| .impl("com.codahale.metrics.Histogram", reservoirInterface) | ||
| .buildChecked(), | ||
| DynConstructors.builder(Histogram.class) | ||
| .impl( | ||
| "org.apache.flink.dropwizard.metrics.DropwizardHistogramWrapper", | ||
| codahaleHistogramClass) | ||
| .buildChecked()); | ||
| } catch (ClassNotFoundException | NoSuchMethodException e) { | ||
| LOG.warn( | ||
| "Cannot load Dropwizard metrics; is org.apache.flink:flink-metrics-dropwizard on the classpath?", | ||
| e); | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| private record DropwizardCtors( | ||
| DynConstructors.Ctor<?> reservoirCtor, | ||
| DynConstructors.Ctor<?> histogramCtor, | ||
| DynConstructors.Ctor<Histogram> wrapperCtor) {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.iceberg.flink.sink; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.Assertions.assertThatNoException; | ||
|
|
||
| import org.apache.flink.metrics.groups.UnregisteredMetricsGroup; | ||
| import org.apache.iceberg.io.WriteResult; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| public class TestIcebergStreamWriterMetrics { | ||
|
|
||
| @Test | ||
| void histogramsCreatedWhenDropwizardAvailable() { | ||
| IcebergStreamWriterMetrics metrics = | ||
| new IcebergStreamWriterMetrics( | ||
| UnregisteredMetricsGroup.createSinkWriterMetricGroup(), "db.table"); | ||
|
|
||
| assertThat(metrics.dataFilesSizeHistogram()).isNotNull(); | ||
| assertThat(metrics.deleteFilesSizeHistogram()).isNotNull(); | ||
|
|
||
| assertThatNoException() | ||
| .isThrownBy(() -> metrics.updateFlushResult(WriteResult.builder().build())); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might miss something - just wonder why Flink's built-in
DescriptiveStatisticsHistogramdoes not work here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stevenzwu: Do you happen to remember why we chose
DropwizardHistogramWrapperoriginally?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the Flink docs, using Dropwizard metrics is still the official way to use Histogram metrics.
DescriptiveStatisticsHistogramwas added to flink-runtime for internal metrics around the same time of the initial implementation here. The semantics (e.g. bucketing) of the internal histogram are different. I would defer this to a follow-up, as the behavior of the implementation might change.