1
+ /**
2
+ * Copyright 2020 Pinterest, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ package com .pinterest .singer .writer ;
17
+
18
+ import java .util .Arrays ;
19
+ import java .util .HashSet ;
20
+ import java .util .Map ;
21
+ import java .util .Map .Entry ;
22
+ import java .util .Set ;
23
+
24
+ import org .apache .kafka .clients .producer .KafkaProducer ;
25
+ import org .apache .kafka .common .Metric ;
26
+ import org .apache .kafka .common .MetricName ;
27
+ import org .slf4j .Logger ;
28
+ import org .slf4j .LoggerFactory ;
29
+
30
+ import com .pinterest .singer .metrics .OpenTsdbMetricConverter ;
31
+ import com .pinterest .singer .thrift .configuration .KafkaProducerConfig ;
32
+ import com .pinterest .singer .utils .LogConfigUtils ;
33
+
34
+ /**
35
+ * Responsible for pulling metrics from {@link KafkaProducer} and copying them
36
+ * to Ostrich so they can be accessed and forwarded. This helps provide
37
+ * additional instrumentation on Singer and how it's performing.
38
+ */
39
+ public class KafkaProducerMetricsMonitor implements Runnable {
40
+
41
+ private static final Logger LOG = LoggerFactory .getLogger (KafkaProducerMetricsMonitor .class );
42
+ public static final Set <String > PRODUCER_METRICS_WHITELIST = new HashSet <>(
43
+ Arrays .asList ("buffer-total-bytes" , "buffer-available-bytes" ));
44
+ // sample every 60seconds
45
+ private static final int SAMPLING_INTERVAL = 60_000 ;
46
+
47
+ @ Override
48
+ public void run () {
49
+ while (true ) {
50
+ try {
51
+ publishKafkaProducerMetricsToOstrich ();
52
+ } catch (Exception e ) {
53
+ LOG .warn ("Error publishing KafkaProducer metrics" , e );
54
+ }
55
+ try {
56
+ Thread .sleep (SAMPLING_INTERVAL );
57
+ } catch (InterruptedException e ) {
58
+ LOG .warn ("KafkaProducerMetricsMonitor thread interrupted, exiting" );
59
+ break ;
60
+ }
61
+ }
62
+ }
63
+
64
+ @ SuppressWarnings ({ "deprecation" })
65
+ protected void publishKafkaProducerMetricsToOstrich () {
66
+ Map <KafkaProducerConfig , KafkaProducer <byte [], byte []>> producers = KafkaProducerManager
67
+ .getInstance ().getProducers ();
68
+ for (Entry <KafkaProducerConfig , KafkaProducer <byte [], byte []>> kafkaProducerEntry : producers
69
+ .entrySet ()) {
70
+ KafkaProducerConfig key = kafkaProducerEntry .getKey ();
71
+ String signature = convertSignatureToTag (key );
72
+ Map <MetricName , ? extends Metric > metrics = kafkaProducerEntry .getValue ().metrics ();
73
+ for (Entry <MetricName , ? extends Metric > entry : metrics .entrySet ()) {
74
+ if (PRODUCER_METRICS_WHITELIST .contains (entry .getKey ().name ())) {
75
+ OpenTsdbMetricConverter .gauge ("kafkaproducer." + entry .getKey ().name (),
76
+ entry .getValue ().value (), "cluster=" + signature );
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ public static String convertSignatureToTag (KafkaProducerConfig key ) {
83
+ return key .getKafkaClusterSignature ()
84
+ .replaceAll ("(" + LogConfigUtils .DEFAULT_SERVERSET_DIR + "|discovery|/|prod|\\ .)" , "" );
85
+ }
86
+
87
+ }
0 commit comments