2525import static org .mockito .ArgumentMatchers .anyString ;
2626import static org .mockito .ArgumentMatchers .argThat ;
2727import static org .mockito .ArgumentMatchers .eq ;
28+ import static org .mockito .Mockito .never ;
2829import static org .mockito .Mockito .verify ;
2930import static org .mockito .Mockito .when ;
3031
3940import org .apache .beam .runners .core .metrics .SimpleMonitoringInfoBuilder ;
4041import org .apache .beam .runners .flink .metrics .FlinkMetricContainerBase .FlinkDistributionGauge ;
4142import org .apache .beam .sdk .metrics .Counter ;
43+ import org .apache .beam .sdk .metrics .DelegatingCounter ;
44+ import org .apache .beam .sdk .metrics .DelegatingDistribution ;
45+ import org .apache .beam .sdk .metrics .DelegatingGauge ;
4246import org .apache .beam .sdk .metrics .Distribution ;
4347import org .apache .beam .sdk .metrics .DistributionResult ;
4448import org .apache .beam .sdk .metrics .Gauge ;
4549import org .apache .beam .sdk .metrics .GaugeResult ;
4650import org .apache .beam .sdk .metrics .MetricKey ;
4751import org .apache .beam .sdk .metrics .MetricName ;
52+ import org .apache .beam .sdk .metrics .Metrics ;
4853import org .apache .beam .sdk .metrics .MetricsContainer ;
54+ import org .apache .beam .sdk .metrics .MetricsEnvironment ;
4955import org .apache .beam .vendor .guava .v32_1_2_jre .com .google .common .collect .ImmutableList ;
5056import org .apache .flink .api .common .functions .RuntimeContext ;
5157import org .apache .flink .metrics .SimpleCounter ;
5258import org .apache .flink .metrics .groups .OperatorMetricGroup ;
59+ import org .junit .After ;
5360import org .junit .Before ;
5461import org .junit .Test ;
62+ import org .mockito .ArgumentCaptor ;
5563import org .mockito .ArgumentMatcher ;
5664import org .mockito .Mock ;
5765import org .mockito .MockitoAnnotations ;
@@ -74,6 +82,11 @@ public void beforeTest() {
7482 container = new FlinkMetricContainer (runtimeContext );
7583 }
7684
85+ @ After
86+ public void afterTest () {
87+ MetricsEnvironment .setProcessWideContainer (null );
88+ }
89+
7790 @ Test
7891 public void testMetricNameGeneration () {
7992 MetricKey key = MetricKey .create ("step" , MetricName .named ("namespace" , "name" ));
@@ -97,6 +110,91 @@ public void testCounter() {
97110 assertThat (flinkCounter .getCount (), is (2L ));
98111 }
99112
113+ @ Test
114+ public void testProcessWideMetrics () {
115+ SimpleCounter flinkCounter = new SimpleCounter ();
116+ when (metricGroup .counter ("global.counter" )).thenReturn (flinkCounter );
117+ when (metricGroup .gauge (eq ("global.gauge" ), any ()))
118+ .thenAnswer (invocation -> invocation .getArgument (1 ));
119+ when (metricGroup .gauge (eq ("global.distribution" ), any ()))
120+ .thenAnswer (invocation -> invocation .getArgument (1 ));
121+
122+ Counter counter = new DelegatingCounter (MetricName .named ("global" , "counter" ), true );
123+ Gauge gauge = new DelegatingGauge (MetricName .named ("global" , "gauge" ), true );
124+ Distribution distribution =
125+ new DelegatingDistribution (MetricName .named ("global" , "distribution" ), true );
126+ counter .inc (5 );
127+ gauge .set (3 );
128+ distribution .update (11 );
129+ distribution .update (13 );
130+ MetricsContainerImpl processWideContainer =
131+ (MetricsContainerImpl ) MetricsEnvironment .getProcessWideContainer ();
132+ assertThat (
133+ processWideContainer
134+ .getGauge (MetricName .named ("global" , "gauge" ))
135+ .getCumulative ()
136+ .extractResult ()
137+ .getValue (),
138+ is (3L ));
139+
140+ container .updateMetrics ("step" );
141+ assertThat (flinkCounter .getCount (), is (5L ));
142+ ArgumentCaptor <FlinkMetricContainerBase .FlinkGauge > gaugeCaptor =
143+ ArgumentCaptor .forClass (FlinkMetricContainerBase .FlinkGauge .class );
144+ ArgumentCaptor <FlinkDistributionGauge > distributionCaptor =
145+ ArgumentCaptor .forClass (FlinkDistributionGauge .class );
146+ verify (metricGroup ).gauge (eq ("global.gauge" ), gaugeCaptor .capture ());
147+ verify (metricGroup ).gauge (eq ("global.distribution" ), distributionCaptor .capture ());
148+ FlinkMetricContainerBase .FlinkGauge flinkGauge = gaugeCaptor .getValue ();
149+ FlinkDistributionGauge flinkDistributionGauge = distributionCaptor .getValue ();
150+ assertThat (flinkGauge .getValue (), is (3L ));
151+ assertThat (flinkDistributionGauge .getValue (), is (DistributionResult .create (24 , 2 , 11 , 13 )));
152+
153+ container .updateMetrics ("step" );
154+ assertThat (flinkCounter .getCount (), is (5L ));
155+ assertThat (flinkGauge .getValue (), is (3L ));
156+ assertThat (flinkDistributionGauge .getValue (), is (DistributionResult .create (24 , 2 , 11 , 13 )));
157+
158+ counter .inc (2 );
159+ gauge .set (4 );
160+ distribution .update (17 );
161+ container .updateMetrics ("step" );
162+ assertThat (flinkCounter .getCount (), is (7L ));
163+ assertThat (flinkGauge .getValue (), is (4L ));
164+ assertThat (flinkDistributionGauge .getValue (), is (DistributionResult .create (41 , 3 , 11 , 17 )));
165+ }
166+
167+ @ Test
168+ public void testProcessWideMetricsArePublishedOnlyByOwningContainer () {
169+ RuntimeContext otherRuntimeContext = org .mockito .Mockito .mock (RuntimeContext .class );
170+ OperatorMetricGroup otherMetricGroup = org .mockito .Mockito .mock (OperatorMetricGroup .class );
171+ when (otherRuntimeContext .<MetricsContainerStepMap , MetricsContainerStepMap >getAccumulator (
172+ anyString ()))
173+ .thenReturn (new MetricsAccumulator ());
174+ when (otherRuntimeContext .getMetricGroup ()).thenReturn (otherMetricGroup );
175+ FlinkMetricContainer otherContainer = new FlinkMetricContainer (otherRuntimeContext );
176+
177+ Counter counter = new DelegatingCounter (MetricName .named ("global" , "counter" ), true );
178+ counter .inc (5 );
179+
180+ otherContainer .updateMetrics ("otherStep" );
181+ verify (otherMetricGroup , never ()).counter ("global.counter" );
182+
183+ SimpleCounter flinkCounter = new SimpleCounter ();
184+ when (metricGroup .counter ("global.counter" )).thenReturn (flinkCounter );
185+ container .updateMetrics ("step" );
186+ assertThat (flinkCounter .getCount (), is (5L ));
187+ }
188+
189+ @ Test
190+ public void testUnscopedThreadMetricsAreNotPublishedAsProcessWideMetrics () {
191+ Metrics .counter ("global" , "unscoped" ).inc (5 );
192+
193+ container .updateMetrics ("step" );
194+
195+ verify (metricGroup , never ()).counter ("global.unscoped" );
196+ }
197+
100198 @ Test
101199 public void testGauge () {
102200 FlinkMetricContainerBase .FlinkGauge flinkGauge =
0 commit comments