diff --git a/deployer/pom.xml b/deployer/pom.xml index 75f05805..68224ca1 100644 --- a/deployer/pom.xml +++ b/deployer/pom.xml @@ -18,12 +18,12 @@ - - - - - - + + com.alibaba.otter + canal.prometheus + ${project.version} + runtime + diff --git a/deployer/src/main/bin/metrics_env.sh b/deployer/src/main/bin/metrics_env.sh deleted file mode 100644 index 1085eae2..00000000 --- a/deployer/src/main/bin/metrics_env.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# Additional line arg for current prometheus solution -case "`uname`" in -Linux) - bin_abs_path=$(readlink -f $(dirname $0)) - ;; -*) - bin_abs_path=`cd $(dirname $0); pwd` - ;; -esac -base=${bin_abs_path}/.. -if [ $(ls $base/lib/aspectjweaver*.jar | wc -l) -eq 1 ]; then - WEAVER=$(ls $base/lib/aspectjweaver*.jar) - METRICS_OPTS=" -javaagent:"${WEAVER}" " -fi diff --git a/deployer/src/main/bin/startup.sh b/deployer/src/main/bin/startup.sh index b87652c0..5655c713 100644 --- a/deployer/src/main/bin/startup.sh +++ b/deployer/src/main/bin/startup.sh @@ -94,12 +94,7 @@ then echo LOG CONFIGURATION : $logback_configurationFile echo canal conf : $canal_conf echo CLASSPATH :$CLASSPATH -# metrics support options -# if [ -x $base/bin/metrics_env.sh ]; then -# . $base/bin/metrics_env.sh -# echo METRICS_OPTS $METRICS_OPTS -# fi - $JAVA $JAVA_OPTS $METRICS_OPTS $JAVA_DEBUG_OPT $CANAL_OPTS -classpath .:$CLASSPATH com.alibaba.otter.canal.deployer.CanalLauncher 1>>$base/logs/canal/canal.log 2>&1 & + $JAVA $JAVA_OPTS $JAVA_DEBUG_OPT $CANAL_OPTS -classpath .:$CLASSPATH com.alibaba.otter.canal.deployer.CanalLauncher 1>>$base/logs/canal/canal.log 2>&1 & echo $! > $base/bin/canal.pid echo "cd to $current_path for continue" diff --git a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlConnection.java b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlConnection.java index 9d89a145..5d2dbb4d 100644 --- a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlConnection.java +++ b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlConnection.java @@ -50,7 +50,8 @@ public class MysqlConnection implements ErosaConnection { private AuthenticationInfo authInfo; protected int connTimeout = 5 * 1000; // 5秒 protected int soTimeout = 60 * 60 * 1000; // 1小时 - private AtomicLong receivedBinlogBytes; + // dump binlog bytes, 暂不包括meta与TSDB + private AtomicLong receivedBinlogBytes; public MysqlConnection(){ } diff --git a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlMultiStageCoprocessor.java b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlMultiStageCoprocessor.java index 92447d50..4fef7710 100644 --- a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlMultiStageCoprocessor.java +++ b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlMultiStageCoprocessor.java @@ -187,6 +187,11 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement //LockSupport.parkNanos(1L); applyWait(++fullTimes); interupted = Thread.interrupted(); + if (fullTimes % 1000 == 0) { + long nextStart = System.nanoTime(); + eventsPublishBlockingTime.addAndGet(nextStart - blockingStart); + blockingStart = nextStart; + } } } while (!interupted && isStart()); return isStart(); diff --git a/pom.xml b/pom.xml index 46d103e3..9a14868b 100644 --- a/pom.xml +++ b/pom.xml @@ -247,7 +247,7 @@ com.alibaba.fastsql fastsql - 2.0.0_preview_186 + 2.0.0_preview_520 com.alibaba diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/CanalInstanceExports.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/CanalInstanceExports.java index 487855fa..6f50214c 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/CanalInstanceExports.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/CanalInstanceExports.java @@ -77,7 +77,7 @@ public class CanalInstanceExports { private InstanceRegistry requiredInstanceRegistry(Collector collector) { if (!(collector instanceof InstanceRegistry)) { - throw new IllegalArgumentException("Canal collector need to implement InstanceRegistry."); + throw new IllegalArgumentException("Canal prometheus collector need to implement InstanceRegistry."); } return (InstanceRegistry) collector; } diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/PrometheusService.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/PrometheusService.java index 9e3ef18c..485f6728 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/PrometheusService.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/PrometheusService.java @@ -19,14 +19,15 @@ import static com.alibaba.otter.canal.server.netty.CanalServerWithNettyProfiler. */ public class PrometheusService implements CanalMetricsService { - private static final Logger logger = LoggerFactory.getLogger(PrometheusService.class); - private final CanalInstanceExports instanceExports; - private volatile boolean running = false; - private HTTPServer server; - private ClientInstanceProfiler clientProfiler = new PrometheusClientInstanceProfiler(); + private static final Logger logger = LoggerFactory.getLogger(PrometheusService.class); + private final CanalInstanceExports instanceExports; + private volatile boolean running = false; + private HTTPServer server; + private final ClientInstanceProfiler clientProfiler; private PrometheusService() { this.instanceExports = CanalInstanceExports.instance(); + this.clientProfiler = PrometheusClientInstanceProfiler.instance(); } private static class SingletonHolder { diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/EntryCollector.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/EntryCollector.java index dd282065..4aa6ff42 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/EntryCollector.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/EntryCollector.java @@ -29,7 +29,7 @@ public class EntryCollector extends Collector implements InstanceRegistry { private static final Logger logger = LoggerFactory.getLogger(SinkCollector.class); private static final String DELAY = "canal_instance_traffic_delay"; private static final String TRANSACTION = "canal_instance_transactions"; - private static final String DELAY_HELP = "Traffic delay of canal instance"; + private static final String DELAY_HELP = "Traffic delay of canal instance in milliseconds"; private static final String TRANSACTION_HELP = "Transactions counter of canal instance"; private final ConcurrentMap instances = new ConcurrentHashMap(); @@ -51,7 +51,11 @@ public class EntryCollector extends Collector implements InstanceRegistry { CounterMetricFamily transactions = new CounterMetricFamily(TRANSACTION, TRANSACTION_HELP, DEST_LABELS_LIST); for (EntryMetricsHolder emh : instances.values()) { - delay.addMetric(emh.destLabelValues, emh.latestExecTime.doubleValue()); + long now = System.currentTimeMillis(); + long latest = emh.latestExecTime.get(); + if (now > latest) { + delay.addMetric(emh.destLabelValues, (now - latest)); + } transactions.addMetric(emh.destLabelValues, emh.transactionCounter.doubleValue()); } mfs.add(delay); diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/MetaCollector.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/MetaCollector.java index aec9a424..e51e8e29 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/MetaCollector.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/MetaCollector.java @@ -11,22 +11,23 @@ import io.prometheus.client.GaugeMetricFamily; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABELS_LIST; + /** * @author Chuanyi Li */ public class MetaCollector extends Collector implements InstanceRegistry { - private static final List InfoLabel = Arrays.asList("destination", "mode"); + private static final List INFO_LABELS_LIST = Arrays.asList("destination", "mode"); private static final Logger logger = LoggerFactory.getLogger(MetaCollector.class); - private static final String SUBSCRIPTION = "canal_instance"; - private static final String SUBSCRIPTION_HELP = "Canal instance"; + private static final String INSTANCE = "canal_instance"; + private static final String INSTANCE_HELP = "Canal instance"; + private static final String SUBSCRIPTION = "canal_instance_subscriptions"; + private static final String SUBSCRIPTION_HELP = "Canal instance subscriptions"; private final ConcurrentMap instances = new ConcurrentHashMap(); private MetaCollector() {} @@ -42,18 +43,20 @@ public class MetaCollector extends Collector implements InstanceRegistry { @Override public List collect() { List mfs = new ArrayList(); - GaugeMetricFamily instanceInfo = new GaugeMetricFamily( - SUBSCRIPTION, - SUBSCRIPTION_HELP, - InfoLabel); + GaugeMetricFamily instanceInfo = new GaugeMetricFamily(INSTANCE, + INSTANCE_HELP, INFO_LABELS_LIST); + GaugeMetricFamily subsInfo = new GaugeMetricFamily(SUBSCRIPTION, + SUBSCRIPTION_HELP, DEST_LABELS_LIST); for (Map.Entry nme : instances.entrySet()) { final String destination = nme.getKey(); final MetaMetricsHolder nmh = nme.getValue(); + instanceInfo.addMetric(nmh.infoLabelValues, 1); List subs = nmh.metaManager.listAllSubscribeInfo(destination); int count = subs == null ? 0 : subs.size(); - instanceInfo.addMetric(nmh.infoLabelValues, count); + subsInfo.addMetric(nmh.destLabelValues, count); } mfs.add(instanceInfo); + mfs.add(subsInfo); return mfs; } @@ -63,6 +66,7 @@ public class MetaCollector extends Collector implements InstanceRegistry { MetaMetricsHolder holder = new MetaMetricsHolder(); String mode = (instance instanceof CanalInstanceWithSpring) ? "spring" : "manager"; holder.infoLabelValues = Arrays.asList(destination, mode); + holder.destLabelValues = Collections.singletonList(destination); holder.metaManager = instance.getMetaManager(); Preconditions.checkNotNull(holder.metaManager); MetaMetricsHolder old = instances.put(destination, holder); @@ -79,6 +83,7 @@ public class MetaCollector extends Collector implements InstanceRegistry { private class MetaMetricsHolder { private List infoLabelValues; + private List destLabelValues; private CanalMetaManager metaManager; } diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/ParserCollector.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/ParserCollector.java index 60906989..73102795 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/ParserCollector.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/ParserCollector.java @@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicLong; import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST; import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABELS_LIST; +import static java.util.concurrent.TimeUnit.NANOSECONDS; /** * @author Chuanyi Li @@ -28,11 +29,12 @@ import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABEL public class ParserCollector extends Collector implements InstanceRegistry { private static final Logger logger = LoggerFactory.getLogger(ParserCollector.class); + private static final long NANO_PER_MILLI = 1000 * 1000L; private static final String PUBLISH_BLOCKING = "canal_instance_publish_blocking_time"; private static final String RECEIVED_BINLOG = "canal_instance_received_binlog_bytes"; private static final String PARSER_MODE = "canal_instance_parser_mode"; private static final String MODE_LABEL = "parallel"; - private static final String PUBLISH_BLOCKING_HELP = "Publish blocking time of dump thread"; + private static final String PUBLISH_BLOCKING_HELP = "Publish blocking time of dump thread in milliseconds"; private static final String RECEIVED_BINLOG_HELP = "Received binlog bytes"; private static final String MODE_HELP = "Parser mode(parallel/serial) of instance"; private final List modeLabels = Arrays.asList(DEST, MODE_LABEL); @@ -60,7 +62,7 @@ public class ParserCollector extends Collector implements InstanceRegistry { PUBLISH_BLOCKING_HELP, DEST_LABELS_LIST); for (ParserMetricsHolder emh : instances.values()) { if (emh.isParallel) { - blockingCounter.addMetric(emh.destLabelValues, emh.eventsPublishBlockingTime.doubleValue()); + blockingCounter.addMetric(emh.destLabelValues, (emh.eventsPublishBlockingTime.doubleValue() / NANO_PER_MILLI)); hasParallel = true; } modeGauge.addMetric(emh.modeLabelValues, 1); diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusCanalEventDownStreamHandler.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusCanalEventDownStreamHandler.java index 6fc2f3d7..ebbbfa00 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusCanalEventDownStreamHandler.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusCanalEventDownStreamHandler.java @@ -1,5 +1,6 @@ package com.alibaba.otter.canal.prometheus.impl; +import com.alibaba.otter.canal.protocol.CanalEntry; import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; import com.alibaba.otter.canal.sink.AbstractCanalEventDownStreamHandler; import com.alibaba.otter.canal.store.model.Event; @@ -24,18 +25,28 @@ public class PrometheusCanalEventDownStreamHandler extends AbstractCanalEventDow for (Event e : events) { EntryType type = e.getEntryType(); if (type == null) continue; - long exec = e.getExecuteTime(); - if (exec > 0) localExecTime = exec; switch (type) { - case ROWDATA: + case TRANSACTIONBEGIN: { + long exec = e.getExecuteTime(); + if (exec > 0) localExecTime = exec; + break; + } + case ROWDATA: { + long exec = e.getExecuteTime(); + if (exec > 0) localExecTime = exec; // TODO 当前proto无法直接获得荣威change的变更行数(需要parse),可考虑放到header里面 break; - case TRANSACTIONEND: + } + case TRANSACTIONEND: { + long exec = e.getExecuteTime(); + if (exec > 0) localExecTime = exec; transactionCounter.incrementAndGet(); break; + } case HEARTBEAT: + // 发现canal自己的heartbeat是带有execTime的 // TODO 确认一下不是canal自己产生的 - // EventType eventType = e.getEventType(); + CanalEntry.EventType eventType = e.getEventType(); // TODO utilize MySQL master heartbeat packet to refresh delay if always no more events coming // see: https://dev.mysql.com/worklog/task/?id=342 // heartbeats are sent by the master only if there is no diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusClientInstanceProfiler.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusClientInstanceProfiler.java index 331897ee..da16f2db 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusClientInstanceProfiler.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/PrometheusClientInstanceProfiler.java @@ -15,6 +15,7 @@ import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABEL */ public class PrometheusClientInstanceProfiler implements ClientInstanceProfiler { + private static final long NANO_PER_MILLI = 1000 * 1000L; private static final String PACKET_TYPE = "canal_instance_client_packets"; private static final String OUTBOUND_BYTES = "canal_instance_client_bytes"; private static final String EMPTY_BATCHES = "canal_instance_client_empty_batches"; @@ -27,7 +28,15 @@ public class PrometheusClientInstanceProfiler implements ClientInstanceProfiler private final Histogram responseLatency; private volatile boolean running = false; - public PrometheusClientInstanceProfiler() { + private static class SingletonHolder { + private static final PrometheusClientInstanceProfiler SINGLETON = new PrometheusClientInstanceProfiler(); + } + + public static PrometheusClientInstanceProfiler instance() { + return SingletonHolder.SINGLETON; + } + + private PrometheusClientInstanceProfiler() { this.outboundCounter = Counter.build() .labelNames(DEST_LABELS) .name(OUTBOUND_BYTES) @@ -53,7 +62,7 @@ public class PrometheusClientInstanceProfiler implements ClientInstanceProfiler .name(LATENCY) .help("Client request latency.") // buckets in milliseconds - .buckets(1.0, 2.5, 5.0, 10.0, 25.0, 50.0, 100.0) + .buckets(2.5, 10.0, 25.0, 100.0) .create(); } @@ -68,7 +77,7 @@ public class PrometheusClientInstanceProfiler implements ClientInstanceProfiler errorsCounter.labels(destination, Short.toString(errorCode)).inc(); } long latency = result.getLatency(); - responseLatency.labels(destination).observe(latency / 1000000); + responseLatency.labels(destination).observe(((double) latency) / NANO_PER_MILLI); switch (type) { case GET: boolean empty = result.getEmpty(); diff --git a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/SinkCollector.java b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/SinkCollector.java index fc5ed3b2..61dc4d64 100644 --- a/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/SinkCollector.java +++ b/prometheus/src/main/java/com/alibaba/otter/canal/prometheus/impl/SinkCollector.java @@ -18,6 +18,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABELS_LIST; +import static java.util.concurrent.TimeUnit.NANOSECONDS; /** * @author Chuanyi Li @@ -25,8 +26,9 @@ import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABEL public class SinkCollector extends Collector implements InstanceRegistry { private static final Logger logger = LoggerFactory.getLogger(SinkCollector.class); + private static final long NANO_PER_MILLI = 1000 * 1000L; private static final String SINK_BLOCKING_TIME = "canal_instance_sink_blocking_time"; - private static final String SINK_BLOCK_TIME_HELP = "Total sink blocking time"; + private static final String SINK_BLOCK_TIME_HELP = "Total sink blocking time in milliseconds"; private final ConcurrentMap instances = new ConcurrentHashMap(); private SinkCollector() {} @@ -45,7 +47,7 @@ public class SinkCollector extends Collector implements InstanceRegistry { CounterMetricFamily blockingCounter = new CounterMetricFamily(SINK_BLOCKING_TIME, SINK_BLOCK_TIME_HELP, DEST_LABELS_LIST); for (SinkMetricsHolder smh : instances.values()) { - blockingCounter.addMetric(smh.destLabelValues, smh.eventsSinkBlockingTime.doubleValue()); + blockingCounter.addMetric(smh.destLabelValues, (smh.eventsSinkBlockingTime.doubleValue() / NANO_PER_MILLI)); } mfs.add(blockingCounter); return mfs; diff --git a/sink/src/main/java/com/alibaba/otter/canal/sink/entry/EntryEventSink.java b/sink/src/main/java/com/alibaba/otter/canal/sink/entry/EntryEventSink.java index 23c5071b..699b06a5 100644 --- a/sink/src/main/java/com/alibaba/otter/canal/sink/entry/EntryEventSink.java +++ b/sink/src/main/java/com/alibaba/otter/canal/sink/entry/EntryEventSink.java @@ -164,6 +164,11 @@ public class EntryEventSink extends AbstractCanalEventSink> handler : getHandlers()) {