mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
Canal metrics group mode support.
This commit is contained in:
@@ -38,6 +38,8 @@ public abstract class AbstractMysqlEventParser extends AbstractEventParser {
|
|||||||
protected boolean filterRows = false;
|
protected boolean filterRows = false;
|
||||||
protected boolean filterTableError = false;
|
protected boolean filterTableError = false;
|
||||||
protected boolean useDruidDdlFilter = true;
|
protected boolean useDruidDdlFilter = true;
|
||||||
|
// instance received binlog bytes
|
||||||
|
protected final AtomicLong receivedBinlogBytes = new AtomicLong(0L);
|
||||||
private final AtomicLong eventsPublishBlockingTime = new AtomicLong(0L);
|
private final AtomicLong eventsPublishBlockingTime = new AtomicLong(0L);
|
||||||
|
|
||||||
protected BinlogParser buildParser() {
|
protected BinlogParser buildParser() {
|
||||||
@@ -204,4 +206,8 @@ public abstract class AbstractMysqlEventParser extends AbstractEventParser {
|
|||||||
return this.eventsPublishBlockingTime;
|
return this.eventsPublishBlockingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AtomicLong getReceivedBinlogBytes() {
|
||||||
|
return this.receivedBinlogBytes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
private int dumpErrorCount = 0; // binlogDump失败异常计数
|
private int dumpErrorCount = 0; // binlogDump失败异常计数
|
||||||
private int dumpErrorCountThreshold = 2; // binlogDump失败异常计数阀值
|
private int dumpErrorCountThreshold = 2; // binlogDump失败异常计数阀值
|
||||||
|
|
||||||
// instance received binlog bytes
|
|
||||||
private final AtomicLong receivedBinlogBytes = new AtomicLong(0L);
|
|
||||||
|
|
||||||
protected ErosaConnection buildErosaConnection() {
|
protected ErosaConnection buildErosaConnection() {
|
||||||
return buildMysqlConnection(this.runningInfo);
|
return buildMysqlConnection(this.runningInfo);
|
||||||
}
|
}
|
||||||
@@ -907,8 +904,4 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
this.dumpErrorCountThreshold = dumpErrorCountThreshold;
|
this.dumpErrorCountThreshold = dumpErrorCountThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtomicLong getReceivedBinlogBytes() {
|
|
||||||
return this.receivedBinlogBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package com.alibaba.otter.canal.prometheus.impl;
|
package com.alibaba.otter.canal.prometheus.impl;
|
||||||
|
|
||||||
import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST;
|
import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST;
|
||||||
import static com.alibaba.otter.canal.prometheus.CanalInstanceExports.DEST_LABELS_LIST;
|
|
||||||
|
import com.alibaba.otter.canal.parse.inbound.group.GroupEventParser;
|
||||||
|
import com.alibaba.otter.canal.parse.inbound.mysql.AbstractMysqlEventParser;
|
||||||
import io.prometheus.client.Collector;
|
import io.prometheus.client.Collector;
|
||||||
import io.prometheus.client.CounterMetricFamily;
|
import io.prometheus.client.CounterMetricFamily;
|
||||||
import io.prometheus.client.GaugeMetricFamily;
|
import io.prometheus.client.GaugeMetricFamily;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
@@ -19,7 +20,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.alibaba.otter.canal.instance.core.CanalInstance;
|
import com.alibaba.otter.canal.instance.core.CanalInstance;
|
||||||
import com.alibaba.otter.canal.parse.CanalEventParser;
|
import com.alibaba.otter.canal.parse.CanalEventParser;
|
||||||
import com.alibaba.otter.canal.parse.inbound.mysql.MysqlEventParser;
|
|
||||||
import com.alibaba.otter.canal.prometheus.InstanceRegistry;
|
import com.alibaba.otter.canal.prometheus.InstanceRegistry;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
@@ -34,11 +34,13 @@ public class ParserCollector extends Collector implements InstanceRegistry {
|
|||||||
private static final String RECEIVED_BINLOG = "canal_instance_received_binlog_bytes";
|
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 PARSER_MODE = "canal_instance_parser_mode";
|
||||||
private static final String MODE_LABEL = "parallel";
|
private static final String MODE_LABEL = "parallel";
|
||||||
|
private static final String PARSER_LABEL = "parser";
|
||||||
private static final String PUBLISH_BLOCKING_HELP = "Publish blocking time of dump thread in milliseconds";
|
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 RECEIVED_BINLOG_HELP = "Received binlog bytes";
|
||||||
private static final String MODE_HELP = "Parser mode(parallel/serial) of instance";
|
private static final String MODE_HELP = "Parser mode(parallel/serial) of instance";
|
||||||
private final List<String> modeLabels = Arrays.asList(DEST, MODE_LABEL);
|
private final List<String> modeLabels = Arrays.asList(DEST, MODE_LABEL);
|
||||||
private final ConcurrentMap<String, ParserMetricsHolder> instances = new ConcurrentHashMap<String, ParserMetricsHolder>();
|
private final List<String> parserLabels = Arrays.asList(DEST, PARSER_LABEL);
|
||||||
|
private final ConcurrentMap<String, ParserMetricsHolder> instances = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private ParserCollector() {}
|
private ParserCollector() {}
|
||||||
|
|
||||||
@@ -52,53 +54,87 @@ public class ParserCollector extends Collector implements InstanceRegistry {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MetricFamilySamples> collect() {
|
public List<MetricFamilySamples> collect() {
|
||||||
List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
|
List<MetricFamilySamples> mfs = new ArrayList<>();
|
||||||
boolean hasParallel = false;
|
|
||||||
CounterMetricFamily bytesCounter = new CounterMetricFamily(RECEIVED_BINLOG,
|
CounterMetricFamily bytesCounter = new CounterMetricFamily(RECEIVED_BINLOG,
|
||||||
RECEIVED_BINLOG_HELP, DEST_LABELS_LIST);
|
RECEIVED_BINLOG_HELP, parserLabels);
|
||||||
GaugeMetricFamily modeGauge = new GaugeMetricFamily(PARSER_MODE,
|
GaugeMetricFamily modeGauge = new GaugeMetricFamily(PARSER_MODE,
|
||||||
MODE_HELP, modeLabels);
|
MODE_HELP, modeLabels);
|
||||||
CounterMetricFamily blockingCounter = new CounterMetricFamily(PUBLISH_BLOCKING,
|
CounterMetricFamily blockingCounter = new CounterMetricFamily(PUBLISH_BLOCKING,
|
||||||
PUBLISH_BLOCKING_HELP, DEST_LABELS_LIST);
|
PUBLISH_BLOCKING_HELP, parserLabels);
|
||||||
for (ParserMetricsHolder emh : instances.values()) {
|
for (ParserMetricsHolder emh : instances.values()) {
|
||||||
if (emh.isParallel) {
|
if (emh instanceof GroupParserMetricsHolder) {
|
||||||
blockingCounter.addMetric(emh.destLabelValues, (emh.eventsPublishBlockingTime.doubleValue() / NANO_PER_MILLI));
|
GroupParserMetricsHolder group = (GroupParserMetricsHolder) emh;
|
||||||
hasParallel = true;
|
for (ParserMetricsHolder semh : group.holders) {
|
||||||
|
singleCollect(bytesCounter, blockingCounter, modeGauge, semh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
singleCollect(bytesCounter, blockingCounter, modeGauge, emh);
|
||||||
}
|
}
|
||||||
modeGauge.addMetric(emh.modeLabelValues, 1);
|
|
||||||
bytesCounter.addMetric(emh.destLabelValues, emh.receivedBinlogBytes.doubleValue());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
mfs.add(bytesCounter);
|
mfs.add(bytesCounter);
|
||||||
mfs.add(modeGauge);
|
mfs.add(modeGauge);
|
||||||
if (hasParallel) {
|
if (!blockingCounter.samples.isEmpty()) {
|
||||||
mfs.add(blockingCounter);
|
mfs.add(blockingCounter);
|
||||||
}
|
}
|
||||||
return mfs;
|
return mfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void singleCollect(CounterMetricFamily bytesCounter, CounterMetricFamily blockingCounter, GaugeMetricFamily modeGauge, ParserMetricsHolder holder) {
|
||||||
|
if (holder.isParallel) {
|
||||||
|
blockingCounter.addMetric(holder.parserLabelValues, (holder.eventsPublishBlockingTime.doubleValue() / NANO_PER_MILLI));
|
||||||
|
}
|
||||||
|
modeGauge.addMetric(holder.modeLabelValues, 1);
|
||||||
|
bytesCounter.addMetric(holder.parserLabelValues, holder.receivedBinlogBytes.doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(CanalInstance instance) {
|
public void register(CanalInstance instance) {
|
||||||
final String destination = instance.getDestination();
|
final String destination = instance.getDestination();
|
||||||
ParserMetricsHolder holder = new ParserMetricsHolder();
|
ParserMetricsHolder holder;
|
||||||
CanalEventParser parser = instance.getEventParser();
|
CanalEventParser parser = instance.getEventParser();
|
||||||
if (!(parser instanceof MysqlEventParser)) {
|
if (parser instanceof AbstractMysqlEventParser) {
|
||||||
throw new IllegalArgumentException("CanalEventParser must be MysqlEventParser");
|
holder = singleHolder(destination, (AbstractMysqlEventParser)parser, "0");
|
||||||
|
} else if (parser instanceof GroupEventParser) {
|
||||||
|
holder = groupHolder(destination, (GroupEventParser)parser);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("CanalEventParser must be either AbstractMysqlEventParser or GroupEventParser.");
|
||||||
}
|
}
|
||||||
MysqlEventParser mysqlParser = (MysqlEventParser) parser;
|
Preconditions.checkNotNull(holder);
|
||||||
holder.destLabelValues = Collections.singletonList(destination);
|
|
||||||
holder.modeLabelValues = Arrays.asList(destination, Boolean.toString(mysqlParser.isParallel()));
|
|
||||||
holder.eventsPublishBlockingTime = mysqlParser.getEventsPublishBlockingTime();
|
|
||||||
holder.receivedBinlogBytes = mysqlParser.getReceivedBinlogBytes();
|
|
||||||
holder.isParallel = mysqlParser.isParallel();
|
|
||||||
Preconditions.checkNotNull(holder.eventsPublishBlockingTime);
|
|
||||||
Preconditions.checkNotNull(holder.receivedBinlogBytes);
|
|
||||||
ParserMetricsHolder old = instances.put(destination, holder);
|
ParserMetricsHolder old = instances.put(destination, holder);
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
logger.warn("Remove stale ParserCollector for instance {}.", destination);
|
logger.warn("Remove stale ParserCollector for instance {}.", destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ParserMetricsHolder singleHolder(String destination, AbstractMysqlEventParser parser, String id) {
|
||||||
|
ParserMetricsHolder holder = new ParserMetricsHolder();
|
||||||
|
holder.parserLabelValues = Arrays.asList(destination, id);
|
||||||
|
holder.modeLabelValues = Arrays.asList(destination, Boolean.toString(parser.isParallel()));
|
||||||
|
holder.eventsPublishBlockingTime = parser.getEventsPublishBlockingTime();
|
||||||
|
holder.receivedBinlogBytes = parser.getReceivedBinlogBytes();
|
||||||
|
holder.isParallel = parser.isParallel();
|
||||||
|
Preconditions.checkNotNull(holder.eventsPublishBlockingTime);
|
||||||
|
Preconditions.checkNotNull(holder.receivedBinlogBytes);
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupParserMetricsHolder groupHolder(String destination, GroupEventParser group) {
|
||||||
|
List<CanalEventParser> parsers = group.getEventParsers();
|
||||||
|
GroupParserMetricsHolder groupHolder = new GroupParserMetricsHolder();
|
||||||
|
int num = parsers.size();
|
||||||
|
for (int i = 0; i < num; i ++) {
|
||||||
|
CanalEventParser parser = parsers.get(i);
|
||||||
|
if (parser instanceof AbstractMysqlEventParser) {
|
||||||
|
ParserMetricsHolder single = singleHolder(destination, (AbstractMysqlEventParser)parser, Integer.toString(i + 1));
|
||||||
|
groupHolder.holders.add(single);
|
||||||
|
} else {
|
||||||
|
logger.warn("Null or non AbstractMysqlEventParser, ignore.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groupHolder;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregister(CanalInstance instance) {
|
public void unregister(CanalInstance instance) {
|
||||||
final String destination = instance.getDestination();
|
final String destination = instance.getDestination();
|
||||||
@@ -106,11 +142,17 @@ public class ParserCollector extends Collector implements InstanceRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ParserMetricsHolder {
|
private class ParserMetricsHolder {
|
||||||
private List<String> destLabelValues;
|
private List<String> parserLabelValues;
|
||||||
private List<String> modeLabelValues;
|
private List<String> modeLabelValues;
|
||||||
|
// metrics for single parser
|
||||||
private AtomicLong receivedBinlogBytes;
|
private AtomicLong receivedBinlogBytes;
|
||||||
private AtomicLong eventsPublishBlockingTime;
|
private AtomicLong eventsPublishBlockingTime;
|
||||||
|
// parser mode
|
||||||
private boolean isParallel;
|
private boolean isParallel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class GroupParserMetricsHolder extends ParserMetricsHolder {
|
||||||
|
private final List<ParserMetricsHolder> holders = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user