Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af44743104 | ||
|
|
6272cd69eb | ||
|
|
8ca430d9c3 | ||
|
|
870bd7c2f9 | ||
|
|
2daedbf880 | ||
|
|
27dff4dd42 | ||
|
|
6d8c2e4c84 |
No files matched your search
@@ -8,5 +8,4 @@ logs/
|
||||
server/pki/
|
||||
client/src/main/python/setup.py
|
||||
grafana/timely-app/yarn-error.log
|
||||
grafana/timely-app/data/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>timely-analytics</artifactId>
|
||||
<!--
|
||||
@@ -71,6 +71,8 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<compilerId>jdt</compilerId>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>timely-balancer</artifactId>
|
||||
<description>Timely Balancer</description>
|
||||
@@ -44,6 +44,10 @@
|
||||
<groupId>io.github.classgraph</groupId>
|
||||
<artifactId>classgraph</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-classes-epoll</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.javacsv</groupId>
|
||||
<artifactId>javacsv</artifactId>
|
||||
|
||||
@@ -62,7 +62,7 @@ timely:
|
||||
assignment-file: file://${java.io.tmpdir}/timely/balancer/assignments.csv
|
||||
server:
|
||||
ip: 127.0.0.1
|
||||
tcp-base-port: 9242
|
||||
tcp-base-port: 4242
|
||||
num-tcp-pools: 1
|
||||
tcp-buffer-size: 100
|
||||
tcp-client-pool:
|
||||
@@ -82,7 +82,7 @@ timely:
|
||||
jmx-enabled: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
udp-base-port: 9245
|
||||
udp-base-port: 4245
|
||||
udp-client-pool:
|
||||
min-idle-per-key: 0
|
||||
max-idle-per-key: 40
|
||||
@@ -103,7 +103,7 @@ timely:
|
||||
http:
|
||||
host: localhost
|
||||
ip: 127.0.0.1
|
||||
base-port: 9243
|
||||
base-port: 4243
|
||||
redirect-path: /secure-me
|
||||
strict-transport-max-age: 604800
|
||||
cors:
|
||||
@@ -132,7 +132,7 @@ timely:
|
||||
test-on-return: false
|
||||
websocket:
|
||||
ip: 127.0.0.1
|
||||
base-port: 9244
|
||||
base-port: 5244
|
||||
timeout: 60
|
||||
subscription-lag: 120
|
||||
scanner-batch-size: 10000
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>timely-client</artifactId>
|
||||
<properties>
|
||||
<!-- PEP 440 compliant version gets substituted into src/main/python/template/setup.py -->
|
||||
<!-- use .dev0 instead of -SNAPSHOT -->
|
||||
<python.client.version>2.2.0</python.client.version>
|
||||
<python.client.version>2.1.6.dev0</python.client.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -18,27 +18,18 @@ public class TcpClient implements AutoCloseable {
|
||||
private Socket sock = null;
|
||||
private BufferedWriter out = null;
|
||||
private long connectTime = 0L;
|
||||
private long INIT_BACKOFF = 1000;
|
||||
private long MAX_BACKOFF = 60000;
|
||||
private long backoff = INIT_BACKOFF;
|
||||
private int bufferSize;
|
||||
private long latency;
|
||||
private long backoff = 2000;
|
||||
private int bufferSize = -1;
|
||||
private int writesSinceFlush = 0;
|
||||
private long lastFlushTime = System.currentTimeMillis();
|
||||
|
||||
public TcpClient(String hostname, int port) {
|
||||
this(hostname, port, -1);
|
||||
}
|
||||
|
||||
public TcpClient(String hostname, int port, int bufferSize) {
|
||||
this(hostname, port, bufferSize, -1);
|
||||
}
|
||||
|
||||
public TcpClient(String hostname, int port, int bufferSize, long latency) {
|
||||
this.host = hostname;
|
||||
this.port = port;
|
||||
this.bufferSize = bufferSize;
|
||||
this.latency = latency;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,54 +54,20 @@ public class TcpClient implements AutoCloseable {
|
||||
if (connect() != 0) {
|
||||
throw new IOException();
|
||||
}
|
||||
try {
|
||||
out.write(metric);
|
||||
writesSinceFlush++;
|
||||
if (bufferSize > 0 && writesSinceFlush >= bufferSize) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace(String.format("Flushing buffer writesSinceFlush >= %d", writesSinceFlush));
|
||||
}
|
||||
flush();
|
||||
}
|
||||
if (latency > 0 && (System.currentTimeMillis() - lastFlushTime) >= latency) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace(String.format("Flushing buffer timeSinceFlush >= %d", latency));
|
||||
}
|
||||
flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
reset();
|
||||
throw e;
|
||||
out.write(metric);
|
||||
writesSinceFlush++;
|
||||
if (bufferSize > 0 && writesSinceFlush >= bufferSize) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void flush() throws IOException {
|
||||
if (null != out) {
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
out.flush();
|
||||
lastFlushTime = System.currentTimeMillis();
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace(String.format("Flushed %d metrics to socket in %d ms", writesSinceFlush, (lastFlushTime - start)));
|
||||
}
|
||||
writesSinceFlush = 0;
|
||||
} catch (IOException e) {
|
||||
log.error(String.format("Failed to flush %d metrics to socket", writesSinceFlush), e);
|
||||
reset();
|
||||
throw e;
|
||||
}
|
||||
out.flush();
|
||||
writesSinceFlush = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void reset() {
|
||||
out = null;
|
||||
sock = null;
|
||||
backoff = INIT_BACKOFF;
|
||||
writesSinceFlush = 0;
|
||||
lastFlushTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the tcp connection to Timely
|
||||
*
|
||||
@@ -118,8 +75,8 @@ public class TcpClient implements AutoCloseable {
|
||||
* if an error occurs
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
log.info(String.format("Shutting down connection to Timely at %s:%d", host, port));
|
||||
public void close() throws IOException {
|
||||
log.trace("Shutting down connection to Timely at {}:{}", host, port);
|
||||
if (null != sock) {
|
||||
try {
|
||||
if (null != out) {
|
||||
@@ -130,7 +87,7 @@ public class TcpClient implements AutoCloseable {
|
||||
}
|
||||
sock.close();
|
||||
} catch (IOException e) {
|
||||
log.error(String.format("Error closing connection to Timely at %s:%d", host, port), e);
|
||||
log.error("Error closing connection to Timely at " + host + ":" + port + ". Error: " + e.getMessage());
|
||||
} finally {
|
||||
sock = null;
|
||||
}
|
||||
@@ -146,10 +103,10 @@ public class TcpClient implements AutoCloseable {
|
||||
sock = new Socket(host, port);
|
||||
osw = new OutputStreamWriter(sock.getOutputStream(), StandardCharsets.UTF_8);
|
||||
out = new BufferedWriter(osw);
|
||||
backoff = INIT_BACKOFF;
|
||||
log.info(String.format("Connected to Timely at %s:%d", host, port));
|
||||
backoff = 2000;
|
||||
log.trace("Connected to Timely at {}:{}", host, port);
|
||||
} catch (Exception e) {
|
||||
log.error(String.format("Error connecting to Timely at %s:%d", host, port), e);
|
||||
log.error("Error connecting to Timely at {}:{} - {}", host, port, e.getMessage());
|
||||
if (sock != null) {
|
||||
try {
|
||||
sock.close();
|
||||
@@ -175,13 +132,12 @@ public class TcpClient implements AutoCloseable {
|
||||
out = null;
|
||||
}
|
||||
}
|
||||
backoff = Math.min(MAX_BACKOFF, backoff * 2);
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace(String.format("Will retry connection in %d ms", backoff));
|
||||
}
|
||||
backoff = backoff * 2;
|
||||
log.info("Will retry connection in {} ms.", backoff);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
log.warn("Not writing to Timely, waiting to reconnect");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -191,22 +147,4 @@ public class TcpClient implements AutoCloseable {
|
||||
public long getConnectTime() {
|
||||
return connectTime;
|
||||
}
|
||||
|
||||
public int getWritesSinceFlush() {
|
||||
return writesSinceFlush;
|
||||
}
|
||||
|
||||
public long getTimeSinceFlush() {
|
||||
return System.currentTimeMillis() - lastFlushTime;
|
||||
}
|
||||
|
||||
public synchronized boolean isConnected() {
|
||||
boolean isConnected = (null != sock && sock.isConnected());
|
||||
if (isConnected) {
|
||||
return true;
|
||||
} else {
|
||||
int status = connect();
|
||||
return status == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,18 +45,21 @@ public class MetricTest {
|
||||
public void testJson() throws IOException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
String expectedJson = "{\"name\":\"m1\",\"timestamp\":1,\"measure\":1.0,\"tags\":[{\"k1\":\"v1\"}]}";
|
||||
Long now = System.currentTimeMillis();
|
||||
String ts = Long.toString(now);
|
||||
|
||||
Metric m1 = Metric.newBuilder().name("m1").tag("k1", "v1").value(1, 1.0).build();
|
||||
String expectedJson = "{\"name\":\"m1\",\"timestamp\":" + ts + ",\"measure\":1.0,\"tags\":[{\"k1\":\"v1\"}]}";
|
||||
|
||||
Metric m1 = Metric.newBuilder().name("m1").tag("k1", "v1").value(now, 1.0).build();
|
||||
|
||||
Metric expectedMetric = mapper.readValue(expectedJson, Metric.class);
|
||||
|
||||
assertTrue(m1.equals(expectedMetric));
|
||||
|
||||
expectedJson = "{\"name\":\"m1\",\"tags\":[{\"k1\":\"v1\"}],\"timestamp\":5,\"measure\":5.0}";
|
||||
expectedJson = "{\"name\":\"m1\",\"tags\":[{\"k1\":\"v1\"}],\"timestamp\":" + ts + ",\"measure\":5.0}";
|
||||
expectedMetric = mapper.readValue(expectedJson, Metric.class);
|
||||
|
||||
assertEquals((long) expectedMetric.getValue().getTimestamp(), 5L);
|
||||
assertEquals(expectedMetric.getValue().getTimestamp(), now);
|
||||
assertEquals(expectedMetric.getValue().getMeasure(), 5.0D, 0.0);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,11 +14,32 @@ public class MetricParserTest {
|
||||
@Test
|
||||
public void testParseWithEscapedCharacters() {
|
||||
|
||||
Long now = System.currentTimeMillis();
|
||||
String ts = Long.toString(now);
|
||||
|
||||
MetricParser parser = new MetricParser();
|
||||
Metric m = parser.parse("put mymetric 12341234 5.0 tag1=value1,value1 tag2=value2=value2");
|
||||
Metric m = parser.parse("put mymetric " + ts + " 5.0 tag1=value1,value1 tag2=value2=value2");
|
||||
|
||||
Assert.assertEquals("mymetric", m.getName());
|
||||
Assert.assertEquals(12341234, (long) m.getValue().getTimestamp());
|
||||
Assert.assertEquals(now, m.getValue().getTimestamp());
|
||||
Assert.assertEquals(5.0, (double) m.getValue().getMeasure(), 0);
|
||||
List<Tag> expected = new ArrayList<>();
|
||||
expected.add(new Tag("tag1", "value1,value1"));
|
||||
expected.add(new Tag("tag2", "value2=value2"));
|
||||
Assert.assertEquals(expected, m.getTags());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseWithSecondsTimestamp() {
|
||||
|
||||
Long now = System.currentTimeMillis() / 1000;
|
||||
String ts = Long.toString(now);
|
||||
|
||||
MetricParser parser = new MetricParser();
|
||||
Metric m = parser.parse("put mymetric " + ts + " 5.0 tag1=value1,value1 tag2=value2=value2");
|
||||
|
||||
Assert.assertEquals("mymetric", m.getName());
|
||||
Assert.assertEquals((Long) (now * 1000L), m.getValue().getTimestamp());
|
||||
Assert.assertEquals(5.0, (double) m.getValue().getMeasure(), 0);
|
||||
List<Tag> expected = new ArrayList<>();
|
||||
expected.add(new Tag("tag1", "value1,value1"));
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>collectd-nsq-plugin</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>collectd</groupId>
|
||||
<artifactId>collectd-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>collectd-plugin-parent</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<includes />
|
||||
</artifactSet>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>**/module-info.class</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>shade</id>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>collectd-plugin-parent</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>collectd</groupId>
|
||||
<artifactId>collectd-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-easymock-release-full</artifactId>
|
||||
<classifier>full</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -10,14 +10,9 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.OConfigItem;
|
||||
import org.collectd.api.ValueList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import timely.util.Exclusions;
|
||||
|
||||
public abstract class CollectDPluginParent {
|
||||
|
||||
@@ -37,23 +32,19 @@ public abstract class CollectDPluginParent {
|
||||
private static final Pattern STATSD_PATTERN_3_GROUPS = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
|
||||
private static final Pattern STATSD_PATTERN_4_GROUPS = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
|
||||
private static final Pattern STATSD_PATTERN_6_GROUPS = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_#]+)\\.([\\w-_]+)");
|
||||
private static final Pattern ETHSTAT_QUEUE_PATTERN1 = Pattern.compile("([\\w-_]*)queue_([0-9]+)_([\\w-_]+)");
|
||||
private static final Pattern ETHSTAT_QUEUE_PATTERN2 = Pattern.compile("([\\w-_\\.]*)(tx|rx)([-_]?)([0-9]+)([._])([\\w-_]+)");
|
||||
private static final Pattern ETHSTAT_TRAFFIC_CLASS_PATTERN = Pattern.compile("([\\w-_\\.]*)(tc)([-_]?)([0-9]+)([._])([\\w-_]+)");
|
||||
private static final Pattern ETHSTAT_CHANNEL_PATTERN = Pattern.compile("(ch)([0-9]+)([._])([\\w-_]+)");
|
||||
private static final Pattern ETHSTAT_PATTERN = Pattern.compile("([\\w-_]+)_queue_([\\w-_]+)_([\\w-_]+)");
|
||||
private static final String STATSD_PREFIX = "statsd";
|
||||
private static final String NSQ_PREFIX = STATSD_PREFIX + ".nsq.";
|
||||
private static final Pattern HAPROXY_PATTERN = Pattern.compile("\\[([\\w-_=]+),([\\w-_=]+)\\]");
|
||||
private static final Logger log = LoggerFactory.getLogger(CollectDPluginParent.class);
|
||||
|
||||
private final SMARTCodeMapping smart = new SMARTCodeMapping();
|
||||
protected Map<String,String> addlTags = new TreeMap<>();
|
||||
private boolean debug = false;
|
||||
private Exclusions exclusions = new Exclusions();
|
||||
|
||||
public int config(OConfigItem config) {
|
||||
for (OConfigItem child : config.getChildren()) {
|
||||
switch (child.getKey().toLowerCase()) {
|
||||
switch (child.getKey()) {
|
||||
case "Tags":
|
||||
case "tags":
|
||||
String tagValue = child.getValues().get(0).getString();
|
||||
Arrays.stream(tagValue.split(",")).map(String::trim).forEach(p -> {
|
||||
@@ -63,12 +54,7 @@ public abstract class CollectDPluginParent {
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "filteredmetricsfile":
|
||||
setFilteredMetricsFile(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "filteredtagsfile":
|
||||
setFilteredTagsFile(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "Debug":
|
||||
case "debug":
|
||||
debug = child.getValues().get(0).getBoolean();
|
||||
break;
|
||||
@@ -78,18 +64,6 @@ public abstract class CollectDPluginParent {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setFilteredMetricsFile(String filteredMetricsFile) {
|
||||
if (StringUtils.isNotBlank(filteredMetricsFile)) {
|
||||
exclusions.setFilteredMetricsFile(filteredMetricsFile);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFilteredTagsFile(String filteredTagsFile) {
|
||||
if (StringUtils.isNotBlank(filteredTagsFile)) {
|
||||
exclusions.setFilteredTagsFile(filteredTagsFile);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void write(String metric, OutputStream out);
|
||||
|
||||
protected void addTag(Map<String,String> m, String k, String v) {
|
||||
@@ -150,7 +124,6 @@ public abstract class CollectDPluginParent {
|
||||
Matcher statsd_4_groups = STATSD_PATTERN_4_GROUPS.matcher(typeInstance);
|
||||
Matcher statsd_6_groups = STATSD_PATTERN_6_GROUPS.matcher(typeInstance);
|
||||
String instance = null;
|
||||
boolean defaultCase = false;
|
||||
if (!typeInstance.startsWith("nsq")) {
|
||||
String[] parts = typeInstance.split("\\.");
|
||||
if (parts.length >= 4 && (HADOOP_CONTEXTS.contains(parts[0]) || hadoop_4_groups.matches())) {
|
||||
@@ -199,23 +172,16 @@ public abstract class CollectDPluginParent {
|
||||
// and is dropped here. The serviceName is used as the instance.
|
||||
metric.append(STATSD_PREFIX).append(PERIOD).append(statsd_4_groups.group(2)).append(PERIOD).append(statsd_4_groups.group(4));
|
||||
instance = statsd_4_groups.group(1);
|
||||
} else {
|
||||
defaultCase = true;
|
||||
}
|
||||
} else if (statsd_3_groups.matches()) {
|
||||
metric.append(NSQ_PREFIX).append(statsd_3_groups.group(2)).append(PERIOD).append(statsd_3_groups.group(3));
|
||||
} else if (statsd_4_groups.matches()) {
|
||||
metric.append(NSQ_PREFIX).append(statsd_4_groups.group(2)).append(PERIOD).append(statsd_4_groups.group(4));
|
||||
instance = statsd_4_groups.group(3);
|
||||
} else if (statsd_6_groups.matches()) {
|
||||
metric.append(NSQ_PREFIX).append(statsd_6_groups.group(4)).append(PERIOD).append(statsd_6_groups.group(6));
|
||||
instance = statsd_6_groups.group(5);
|
||||
} else {
|
||||
if (statsd_3_groups.matches()) {
|
||||
metric.append(NSQ_PREFIX).append(statsd_3_groups.group(2)).append(PERIOD).append(statsd_3_groups.group(3));
|
||||
} else if (statsd_4_groups.matches()) {
|
||||
metric.append(NSQ_PREFIX).append(statsd_4_groups.group(2)).append(PERIOD).append(statsd_4_groups.group(4));
|
||||
instance = statsd_4_groups.group(3);
|
||||
} else if (statsd_6_groups.matches()) {
|
||||
metric.append(NSQ_PREFIX).append(statsd_6_groups.group(4)).append(PERIOD).append(statsd_6_groups.group(6));
|
||||
instance = statsd_6_groups.group(5);
|
||||
} else {
|
||||
defaultCase = true;
|
||||
}
|
||||
}
|
||||
if (defaultCase) {
|
||||
// Handle StatsD metrics of unknown formats. If there is a
|
||||
// period in the metric name, use everything up to that as
|
||||
// the instance.
|
||||
@@ -233,39 +199,13 @@ public abstract class CollectDPluginParent {
|
||||
break;
|
||||
case "ethstat":
|
||||
metric.append("sys.ethstat.");
|
||||
if (typeInstance.matches(ETHSTAT_QUEUE_PATTERN1.pattern())) {
|
||||
Matcher ethstat_m = ETHSTAT_QUEUE_PATTERN1.matcher(typeInstance);
|
||||
if (typeInstance.contains("queue")) {
|
||||
Matcher ethstat_m = ETHSTAT_PATTERN.matcher(typeInstance);
|
||||
if (ethstat_m.matches()) {
|
||||
metric.append(ethstat_m.group(1));
|
||||
metric.append("queue_");
|
||||
metric.append(ethstat_m.group(3));
|
||||
metric.append(ethstat_m.group(1)).append("_").append(ethstat_m.group(3));
|
||||
addTag(tagMap, "queue", ethstat_m.group(2));
|
||||
}
|
||||
} else if (typeInstance.matches(ETHSTAT_QUEUE_PATTERN2.pattern())) {
|
||||
Matcher ethstat_m = ETHSTAT_QUEUE_PATTERN2.matcher(typeInstance);
|
||||
if (ethstat_m.matches()) {
|
||||
metric.append(ethstat_m.group(1));
|
||||
metric.append(ethstat_m.group(2));
|
||||
metric.append("_queue_");
|
||||
metric.append(ethstat_m.group(6));
|
||||
addTag(tagMap, "queue", ethstat_m.group(4));
|
||||
}
|
||||
} else if (typeInstance.matches(ETHSTAT_TRAFFIC_CLASS_PATTERN.pattern())) {
|
||||
Matcher ethstat_m = ETHSTAT_TRAFFIC_CLASS_PATTERN.matcher(typeInstance);
|
||||
if (ethstat_m.matches()) {
|
||||
metric.append(ethstat_m.group(1));
|
||||
metric.append(ethstat_m.group(2));
|
||||
metric.append(ethstat_m.group(5));
|
||||
metric.append(ethstat_m.group(6));
|
||||
addTag(tagMap, "trafficClass", ethstat_m.group(4));
|
||||
}
|
||||
} else if (typeInstance.matches(ETHSTAT_CHANNEL_PATTERN.pattern())) {
|
||||
Matcher ethstat_m = ETHSTAT_CHANNEL_PATTERN.matcher(typeInstance);
|
||||
if (ethstat_m.matches()) {
|
||||
metric.append(ethstat_m.group(1));
|
||||
metric.append("_");
|
||||
metric.append(ethstat_m.group(4));
|
||||
addTag(tagMap, "channel", ethstat_m.group(2));
|
||||
} else {
|
||||
metric.append(typeInstance);
|
||||
}
|
||||
} else {
|
||||
metric.append(typeInstance);
|
||||
@@ -363,13 +303,8 @@ public abstract class CollectDPluginParent {
|
||||
typeInstance));
|
||||
} else {
|
||||
String datapoint = MessageFormat.format(PUT, metricName, timestamp.toString(), value.toString(), tagString);
|
||||
if (exclusions.filterMetric(datapoint)) {
|
||||
logDebug(String.format("Not writing excluded metric: %s", datapoint));
|
||||
} else {
|
||||
datapoint = exclusions.filterExcludedTags(datapoint);
|
||||
logDebug(String.format("Writing: %s", datapoint));
|
||||
write(datapoint + "\n", out);
|
||||
}
|
||||
logDebug(String.format("Writing: %s", datapoint));
|
||||
write(datapoint + "\n", out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.PooledObjectFactory;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.collectd.api.OConfigItem;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PooledCloseableHttpClientFactory implements PooledObjectFactory<CloseableHttpClient> {
|
||||
|
||||
private int connectionRequestTimeout = 10000; // 10 seconds in milliseconds
|
||||
private int connectTimeout = 30000; // 30 seconds in milliseconds
|
||||
private int socketTimeout = 60000; // 60 seconds in milliseconds
|
||||
private long connectionTimeToLive = 300000; // 300 seconds in milliseconds
|
||||
|
||||
public int config(OConfigItem config) {
|
||||
for (OConfigItem child : config.getChildren()) {
|
||||
switch (child.getKey()) {
|
||||
case "connectionRequestTimeout":
|
||||
case "ConnectionRequestTimeout":
|
||||
connectionRequestTimeout = Integer.parseInt(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "connectTimeout":
|
||||
case "ConnectTimeout":
|
||||
connectTimeout = Integer.parseInt(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "socketTimeout":
|
||||
case "SocketTimeout":
|
||||
socketTimeout = Integer.parseInt(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "connectionTimeToLive":
|
||||
case "ConnectionTimeToLive":
|
||||
connectionTimeToLive = Long.parseLong(child.getValues().get(0).getString());
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledObject<CloseableHttpClient> makeObject() throws Exception {
|
||||
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setConnectTimeout(connectTimeout)
|
||||
.setSocketTimeout(socketTimeout).build();
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setDefaultRequestConfig(requestConfig);
|
||||
builder.setConnectionTimeToLive(connectionTimeToLive, TimeUnit.MILLISECONDS);
|
||||
return new DefaultPooledObject<>(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyObject(PooledObject<CloseableHttpClient> pooledObject) throws Exception {
|
||||
try {
|
||||
pooledObject.getObject().close();
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
} finally {
|
||||
pooledObject.invalidate();
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateObject(PooledObject<CloseableHttpClient> pooledObject) {
|
||||
return pooledObject.getObject() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(PooledObject<CloseableHttpClient> pooledObject) throws Exception {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(PooledObject<CloseableHttpClient> pooledObject) throws Exception {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void setConnectionRequestTimeout(int connectionRequestTimeout) {
|
||||
this.connectionRequestTimeout = connectionRequestTimeout;
|
||||
}
|
||||
|
||||
public void setConnectTimeout(int connectTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
public void setSocketTimeout(int socketTimeout) {
|
||||
this.socketTimeout = socketTimeout;
|
||||
}
|
||||
|
||||
public void setConnectionTimeToLive(long connectionTimeToLive) {
|
||||
this.connectionTimeToLive = connectionTimeToLive;
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.entity.EntityBuilder;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.CollectdConfigInterface;
|
||||
import org.collectd.api.CollectdShutdownInterface;
|
||||
import org.collectd.api.CollectdWriteInterface;
|
||||
import org.collectd.api.OConfigItem;
|
||||
import org.collectd.api.ValueList;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
*
|
||||
* CollectD plugin that writes metrics collected by the StatsD plugin to NSQ. NSQ can be configured to write statsd metrics to CollectD. If you do this, set the
|
||||
* statsd prefix in NSQ to 'nsq'.
|
||||
*
|
||||
*/
|
||||
public class WriteNSQPlugin extends CollectDPluginParent implements CollectdConfigInterface, CollectdShutdownInterface, CollectdWriteInterface {
|
||||
|
||||
private String host = null;
|
||||
private int port = 0;
|
||||
private String topic = "metrics#ephemeral";
|
||||
private String endpoint = null;
|
||||
private GenericObjectPool<CloseableHttpClient> clientPool = null;
|
||||
private Random random = new Random();
|
||||
|
||||
// pool should be limited by the number of WriteThreads configured in
|
||||
// collectd
|
||||
static final private int POOL_MAX_SIZE = Integer.MAX_VALUE;
|
||||
|
||||
public WriteNSQPlugin() {
|
||||
Collectd.registerConfig(WriteNSQPlugin.class.getName(), this);
|
||||
Collectd.registerShutdown(WriteNSQPlugin.class.getName(), this);
|
||||
Collectd.registerWrite(WriteNSQPlugin.class.getName(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(ValueList vl) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(baos);
|
||||
super.process(vl, out);
|
||||
CloseableHttpClient client = null;
|
||||
try {
|
||||
out.flush();
|
||||
HttpPost post = new HttpPost(endpoint);
|
||||
EntityBuilder request = EntityBuilder.create();
|
||||
request.setBinary(baos.toByteArray());
|
||||
post.setEntity(request.build());
|
||||
client = clientPool.borrowObject();
|
||||
CloseableHttpResponse response = client.execute(post);
|
||||
try {
|
||||
int code = response.getStatusLine().getStatusCode();
|
||||
String msg = response.getStatusLine().getReasonPhrase();
|
||||
// Consume the entire response so the connection will be reused
|
||||
EntityUtils.consume(response.getEntity());
|
||||
if (code != HttpStatus.SC_OK) {
|
||||
Collectd.logInfo("Code: " + code + ", msg: " + msg);
|
||||
}
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Collectd.logError("Error sending metrics to NSQ: " + e.getMessage());
|
||||
if (client != null) {
|
||||
try {
|
||||
client.close();
|
||||
} catch (IOException e1) {}
|
||||
try {
|
||||
clientPool.invalidateObject(client);
|
||||
client = null;
|
||||
} catch (Exception e2) {}
|
||||
}
|
||||
} finally {
|
||||
if (client != null) {
|
||||
clientPool.returnObject(client);
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String metric, OutputStream out) {
|
||||
try {
|
||||
((DataOutputStream) out).writeBytes(metric);
|
||||
} catch (IOException e) {
|
||||
Collectd.logError("Error writing metric: " + e.getMessage());
|
||||
try {
|
||||
out.close(); // Should cause IOException in write.
|
||||
} catch (IOException e1) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int shutdown() {
|
||||
Collectd.logInfo("Shutting down connection to NSQ at " + host + ":" + port);
|
||||
clientPool.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int config(OConfigItem config) {
|
||||
super.config(config);
|
||||
GenericObjectPoolConfig<CloseableHttpClient> poolConfig = new GenericObjectPoolConfig<>();
|
||||
// use max size for maxTotal and maxIdle
|
||||
// no need to activate or passivate
|
||||
poolConfig.setMaxTotal(POOL_MAX_SIZE);
|
||||
poolConfig.setMaxIdle(POOL_MAX_SIZE);
|
||||
poolConfig.setTestOnReturn(true);
|
||||
PooledCloseableHttpClientFactory pooledCloseableHttpClientFactory = new PooledCloseableHttpClientFactory();
|
||||
pooledCloseableHttpClientFactory.config(config);
|
||||
|
||||
for (OConfigItem child : config.getChildren()) {
|
||||
switch (child.getKey()) {
|
||||
case "host":
|
||||
case "hostname":
|
||||
case "Host":
|
||||
case "HostName":
|
||||
String hostString = child.getValues().get(0).getString();
|
||||
String[] hosts = hostString.split(",");
|
||||
if (hosts.length == 1) {
|
||||
host = hosts[0];
|
||||
} else {
|
||||
host = hosts[random.nextInt(hosts.length)];
|
||||
}
|
||||
break;
|
||||
case "Port":
|
||||
case "port":
|
||||
port = Integer.parseInt(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "topic":
|
||||
case "Topic":
|
||||
topic = child.getValues().get(0).getString();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
if (host == null || port == 0 || topic == null) {
|
||||
Collectd.logError("NSQ host, port, and topic must be configured");
|
||||
return -1;
|
||||
}
|
||||
this.clientPool = new GenericObjectPool<>(pooledCloseableHttpClientFactory, poolConfig);
|
||||
this.endpoint = "http://" + host + ":" + port + "/mpub?topic=" + topic;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.CollectdConfigInterface;
|
||||
import org.collectd.api.CollectdShutdownInterface;
|
||||
import org.collectd.api.CollectdWriteInterface;
|
||||
import org.collectd.api.OConfigItem;
|
||||
import org.collectd.api.ValueList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
*
|
||||
* CollectD plugin that writes metrics collected by the StatsD plugin to Timely.
|
||||
*
|
||||
*/
|
||||
public class WriteTimelyPlugin extends CollectDPluginParent implements CollectdConfigInterface, CollectdShutdownInterface, CollectdWriteInterface {
|
||||
|
||||
private GenericObjectPool<Socket> socketPool = null;
|
||||
|
||||
// pool should be limited by the number of WriteThreads configured in
|
||||
// collectd
|
||||
static final private int POOL_MAX_SIZE = Integer.MAX_VALUE;
|
||||
|
||||
public WriteTimelyPlugin() {
|
||||
Collectd.registerConfig(WriteTimelyPlugin.class.getName(), this);
|
||||
Collectd.registerShutdown(WriteTimelyPlugin.class.getName(), this);
|
||||
Collectd.registerWrite(WriteTimelyPlugin.class.getName(), this);
|
||||
}
|
||||
|
||||
public int write(ValueList vl) {
|
||||
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = socketPool.borrowObject();
|
||||
if (socket == null) {
|
||||
return -1;
|
||||
}
|
||||
super.process(vl, socket.getOutputStream());
|
||||
} catch (Exception e) {
|
||||
Collectd.logWarning(e.getMessage());
|
||||
try {
|
||||
// close socket so that the object pool will discard it and
|
||||
// reconnect
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (IOException e1) {
|
||||
Collectd.logError(e1.getMessage());
|
||||
}
|
||||
return -1;
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
socketPool.returnObject(socket);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String metric, OutputStream out) {
|
||||
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8), false);
|
||||
printWriter.write(metric);
|
||||
printWriter.flush();
|
||||
if (printWriter.checkError()) {
|
||||
throw new RuntimeException("Error writing to Timely");
|
||||
}
|
||||
}
|
||||
|
||||
public int shutdown() {
|
||||
socketPool.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int config(OConfigItem config) {
|
||||
super.config(config);
|
||||
int retval = 0;
|
||||
PooledSocketFactory socketFactory = new PooledSocketFactory();
|
||||
retval = socketFactory.config(config);
|
||||
if (retval == 0) {
|
||||
GenericObjectPoolConfig<Socket> poolConfig = new GenericObjectPoolConfig<>();
|
||||
// use max size for maxTotal and maxIdle
|
||||
// no need to activate and passivate
|
||||
poolConfig.setMaxTotal(POOL_MAX_SIZE);
|
||||
poolConfig.setMaxIdle(POOL_MAX_SIZE);
|
||||
poolConfig.setTestOnReturn(true);
|
||||
socketPool = new GenericObjectPool<>(socketFactory, poolConfig);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package timely.collectd.plugin;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.collectd.api.Collectd;
|
||||
@@ -14,13 +13,14 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.api.easymock.PowerMock;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import net.jcip.annotations.NotThreadSafe;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PowerMockIgnore("jdk.internal.reflect.*")
|
||||
@PrepareForTest({Collectd.class})
|
||||
@NotThreadSafe
|
||||
public class PluginParentTest {
|
||||
|
||||
public class TestPlugin extends CollectDPluginParent {
|
||||
@@ -41,13 +41,12 @@ public class PluginParentTest {
|
||||
public String result = null;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
result = null;
|
||||
public void setup() throws Exception {
|
||||
PowerMock.suppress(PowerMock.everythingDeclaredIn(Collectd.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatsDHadoopFormat() {
|
||||
public void testStatsDHadoopFormat() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("statsd");
|
||||
@@ -61,11 +60,11 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put statsd.dfs.BlocksRead 1456156976840 1.0 addl1=foo host=r01n01 instance=DataNode rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put statsd.dfs.BlocksRead 1456156976840 1.0 host=r01n01 rack=r01 addl1=foo instance=DataNode sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatsDUnknownFormat() {
|
||||
public void testStatsDUnknownFormat() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("statsd");
|
||||
@@ -79,11 +78,11 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put statsd.baz 1456156976840 1.0 addl1=foo host=r01n01 rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put statsd.baz 1456156976840 1.0 host=r01n01 rack=r01 addl1=foo sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatsDUnknownFormat2() {
|
||||
public void testStatsDUnknownFormat2() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("statsd");
|
||||
@@ -97,11 +96,11 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put statsd.baz 1456156976840 1.0 addl1=foo host=r01n01 instance=bar rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put statsd.baz 1456156976840 1.0 host=r01n01 rack=r01 addl1=foo instance=bar sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHddTemp() {
|
||||
public void testHddTemp() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("hddtemp");
|
||||
@@ -115,11 +114,11 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.hddtemp.temperature 1456156976840 35.0 addl1=foo host=r01n01 instance=sda rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.hddtemp.temperature 1456156976840 35.0 host=r01n01 rack=r01 addl1=foo instance=sda sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmart1() {
|
||||
public void testSmart1() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("smart");
|
||||
@@ -133,11 +132,11 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.smart.smart_badsectors 1456156976840 0.0 addl1=foo host=r01n01 instance=sda rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.smart.smart_badsectors 1456156976840 0.0 host=r01n01 rack=r01 addl1=foo instance=sda sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmart2() {
|
||||
public void testSmart2() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("smart");
|
||||
@@ -152,11 +151,11 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.smart.raw-read-error-rate 1456156976840 0.0 addl1=foo host=r01n01 instance=sda rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.smart.raw-read-error-rate 1456156976840 0.0 host=r01n01 rack=r01 addl1=foo instance=sda sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartCode() {
|
||||
public void testSmartCode() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("smart");
|
||||
@@ -171,11 +170,12 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.smart.Total_LBAs_Read 1456156976840 0.0 addl1=foo code=242 host=r01n01 instance=sda rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.smart.Total_LBAs_Read 1456156976840 0.0 host=r01n01 rack=r01 addl1=foo code=242 instance=sda sample=value sampleType=GAUGE\n",
|
||||
result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSnmp() {
|
||||
public void testSnmp() throws Exception {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("snmp");
|
||||
@@ -190,7 +190,7 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.snmp.if_octets 1456156976840 0.0 addl1=foo host=r01n01 instance=Ethernet1 rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.snmp.if_octets 1456156976840 0.0 host=r01n01 rack=r01 addl1=foo instance=Ethernet1 sample=value sampleType=GAUGE\n", result);
|
||||
|
||||
}
|
||||
|
||||
@@ -210,7 +210,8 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.sensors.temperature.coretemp-isa-0000 1456156976840 35.0 addl1=foo host=r01n01 instance=1 rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.sensors.temperature.coretemp-isa-0000 1456156976840 35.0 host=r01n01 rack=r01 addl1=foo instance=1 sample=value sampleType=GAUGE\n",
|
||||
result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -228,7 +229,7 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.haproxy.run_queue 1456156976840 0.0 addl1=foo host=r01n01 rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.haproxy.run_queue 1456156976840 0.0 host=r01n01 rack=r01 addl1=foo sample=value sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -247,7 +248,7 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.haproxy.queue_current 1456156976840 0.0 addl1=foo host=r01n01 proxy_name=proxy1 rack=r01 sampleType=GAUGE service_name=server1\n",
|
||||
assertEquals("put sys.haproxy.queue_current 1456156976840 0.0 host=r01n01 rack=r01 addl1=foo proxy_name=proxy1 service_name=server1 sample=value sampleType=GAUGE\n",
|
||||
result);
|
||||
}
|
||||
|
||||
@@ -267,103 +268,29 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.tx_comp_queue_full 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 rack=r01 sampleType=GAUGE\n", result);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEthstatWithQueueStyle1() {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("ethstat");
|
||||
vl.setPluginInstance("eth0");
|
||||
vl.setTime(TIME);
|
||||
vl.setType("derive");
|
||||
vl.setTypeInstance("rx_queue_15_bytes");
|
||||
vl.setValues(Collections.singletonList((Number) 6.0D));
|
||||
DataSet ds = new DataSet("DERIVE");
|
||||
ds.addDataSource(new DataSource("value", 1, 6.0D, 100.0D));
|
||||
vl.setDataSet(ds);
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.rx_queue_bytes 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 queue=15 rack=r01 sampleType=GAUGE\n", result);
|
||||
|
||||
result = null;
|
||||
vl.setTypeInstance("queue_7_tx_bytes");
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.queue_tx_bytes 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 queue=7 rack=r01 sampleType=GAUGE\n", result);
|
||||
|
||||
result = null;
|
||||
vl.setTypeInstance("queue_7_rx_xdp_drop");
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.queue_rx_xdp_drop 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 queue=7 rack=r01 sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEthstatWithQueueStyle2() {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("ethstat");
|
||||
vl.setPluginInstance("eth0");
|
||||
vl.setTime(TIME);
|
||||
vl.setType("derive");
|
||||
vl.setTypeInstance("rx-15.bytes");
|
||||
vl.setValues(Collections.singletonList((Number) 6.0D));
|
||||
DataSet ds = new DataSet("DERIVE");
|
||||
ds.addDataSource(new DataSource("value", 1, 6.0D, 100.0D));
|
||||
vl.setDataSet(ds);
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.rx_queue_bytes 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 queue=15 rack=r01 sampleType=GAUGE\n", result);
|
||||
|
||||
result = null;
|
||||
vl.setTypeInstance("tx15_xdp_err");
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.tx_queue_xdp_err 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 queue=15 rack=r01 sampleType=GAUGE\n", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEthstatWithTrafficClass() {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("ethstat");
|
||||
vl.setPluginInstance("eth0");
|
||||
vl.setTime(TIME);
|
||||
vl.setType("derive");
|
||||
vl.setTypeInstance("veb.tc_15_tx_bytes");
|
||||
vl.setValues(Collections.singletonList((Number) 6.0D));
|
||||
DataSet ds = new DataSet("DERIVE");
|
||||
ds.addDataSource(new DataSource("value", 1, 6.0D, 100.0D));
|
||||
vl.setDataSet(ds);
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.veb.tc_tx_bytes 1456156976840 6.0 addl1=foo host=r01n01 instance=eth0 rack=r01 sampleType=GAUGE trafficClass=15\n",
|
||||
assertEquals("put sys.ethstat.tx_comp_queue_full 1456156976840 6.0 host=r01n01 rack=r01 addl1=foo instance=eth0 sample=value sampleType=GAUGE\n",
|
||||
result);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEthstatWithChannel() {
|
||||
public void testEthStatWithQueue() {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("ethstat");
|
||||
vl.setPluginInstance("eth0");
|
||||
vl.setTime(TIME);
|
||||
vl.setType("derive");
|
||||
vl.setTypeInstance("ch44_events");
|
||||
vl.setTypeInstance("rx_queue_1_bytes");
|
||||
vl.setValues(Collections.singletonList((Number) 6.0D));
|
||||
DataSet ds = new DataSet("DERIVE");
|
||||
ds.addDataSource(new DataSource("value", 1, 6.0D, 100.0D));
|
||||
vl.setDataSet(ds);
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.ch_events 1456156976840 6.0 addl1=foo channel=44 host=r01n01 instance=eth0 rack=r01 sampleType=GAUGE\n", result);
|
||||
assertEquals("put sys.ethstat.rx_bytes 1456156976840 6.0 host=r01n01 rack=r01 addl1=foo queue=1 instance=eth0 sample=value sampleType=GAUGE\n", result);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -381,37 +308,9 @@ public class PluginParentTest {
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ipmi.temperature 1456156976840 6.0 addl1=foo host=r01n01 instance=LAN_NIC_Temp_system_board_(3.2) rack=r01 sampleType=GAUGE\n",
|
||||
assertEquals("put sys.ipmi.temperature 1456156976840 6.0 host=r01n01 rack=r01 addl1=foo instance=LAN_NIC_Temp_system_board_(3.2) sample=value sampleType=GAUGE\n",
|
||||
result);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExclusions() {
|
||||
ValueList vl = new ValueList();
|
||||
vl.setHost(HOST);
|
||||
vl.setPlugin("ethstat");
|
||||
vl.setPluginInstance("eth0");
|
||||
vl.setTime(TIME);
|
||||
vl.setType("derive");
|
||||
vl.setTypeInstance("rx_queue_1_bytes");
|
||||
vl.setValues(Collections.singletonList((Number) 6.0D));
|
||||
DataSet ds = new DataSet("DERIVE");
|
||||
ds.addDataSource(new DataSource("value", 1, 6.0D, 100.0D));
|
||||
vl.setDataSet(ds);
|
||||
|
||||
TestPlugin test = new TestPlugin();
|
||||
URL filteredMetricsFile = getClass().getClassLoader().getResource("filteredMetrics.txt");
|
||||
test.setFilteredMetricsFile(filteredMetricsFile.getPath());
|
||||
URL filteredTagsFile = getClass().getClassLoader().getResource("filteredTags.txt");
|
||||
test.setFilteredTagsFile(filteredTagsFile.getPath());
|
||||
|
||||
test.process(vl, null);
|
||||
assertEquals("put sys.ethstat.rx_queue_bytes 1456156976840 6.0 addl1=foo host=r01n01 queue=1 rack=r01\n", result);
|
||||
|
||||
result = null;
|
||||
vl.setPlugin("interface");
|
||||
vl.setTypeInstance("if_octets");
|
||||
assertNull(result);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>timely-collectd</artifactId>
|
||||
<artifactId>collectd-timely-plugin</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>collectd</groupId>
|
||||
@@ -16,23 +16,25 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely-common</artifactId>
|
||||
<artifactId>collectd-plugin-parent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-easymock-release-full</artifactId>
|
||||
@@ -47,17 +49,7 @@
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>com.google.guava:guava</include>
|
||||
<include>commons-codec:commons-codec</include>
|
||||
<include>org.apache.commons:commons-lang3</include>
|
||||
<include>org.apache.commons:commons-pool2</include>
|
||||
<include>org.apache.httpcomponents:httpclient</include>
|
||||
<include>org.apache.httpcomponents:httpcore</include>
|
||||
<include>org.slf4j:jcl-over-slf4j</include>
|
||||
<include>org.slf4j:slf4j-api</include>
|
||||
<include>timely:timely-common</include>
|
||||
</includes>
|
||||
<includes />
|
||||
</artifactSet>
|
||||
<filters>
|
||||
<filter>
|
||||
@@ -1,13 +1,13 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.PooledObjectFactory;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.OConfigItem;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
public class PooledSocketFactory implements PooledObjectFactory<Socket> {
|
||||
|
||||
private String host = null;
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<FindBugsFilter>
|
||||
<Match>
|
||||
<Bug pattern="DM_DEFAULT_ENCODING"/>
|
||||
<Method name="connect" />
|
||||
<Class name="timely.collectd.plugin.WriteTimelyPlugin"/>
|
||||
</Match>
|
||||
</FindBugsFilter>
|
||||
@@ -1,6 +1,12 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import net.jcip.annotations.NotThreadSafe;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.DataSet;
|
||||
import org.collectd.api.DataSource;
|
||||
@@ -15,12 +21,7 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Collections;
|
||||
import net.jcip.annotations.NotThreadSafe;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({Collectd.class})
|
||||
@@ -0,0 +1,24 @@
|
||||
Configuration:
|
||||
status: warn
|
||||
monitorInterval: 60
|
||||
|
||||
Properties:
|
||||
Property:
|
||||
- name: PID
|
||||
value: "????"
|
||||
- name: LOG_PATTERN
|
||||
value: "%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%wEx"
|
||||
|
||||
Appenders:
|
||||
Console:
|
||||
name: Console
|
||||
target: SYSTEM_OUT
|
||||
follow: true
|
||||
PatternLayout:
|
||||
pattern: "${LOG_PATTERN}"
|
||||
|
||||
Loggers:
|
||||
Root:
|
||||
level: warn
|
||||
AppenderRef:
|
||||
- ref: Console
|
||||
@@ -1,122 +0,0 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.PooledObjectFactory;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.OConfigItem;
|
||||
|
||||
public class PooledSocketFactory implements PooledObjectFactory<Socket> {
|
||||
|
||||
private String host = null;
|
||||
private int port = 0;
|
||||
private static final long initialBackoff = 2000;
|
||||
private int socketTimeout = 60000; // 60 seconds in milliseconds
|
||||
private long connectionTimeToLive = 300000; // 300 seconds in milliseconds
|
||||
|
||||
public int config(OConfigItem config) {
|
||||
for (OConfigItem child : config.getChildren()) {
|
||||
switch (child.getKey()) {
|
||||
case "host":
|
||||
case "hostname":
|
||||
case "Host":
|
||||
case "HostName":
|
||||
host = child.getValues().get(0).getString();
|
||||
break;
|
||||
case "Port":
|
||||
case "port":
|
||||
port = Integer.parseInt(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "socketTimeout":
|
||||
case "SocketTimeout":
|
||||
socketTimeout = Integer.parseInt(child.getValues().get(0).getString());
|
||||
break;
|
||||
case "connectionTimeToLive":
|
||||
case "ConnectionTimeToLive":
|
||||
connectionTimeToLive = Long.parseLong(child.getValues().get(0).getString());
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
if (null != host) {
|
||||
return 0;
|
||||
}
|
||||
if (host == null) {
|
||||
Collectd.logError("Timely host must be configured");
|
||||
}
|
||||
if (port == 0) {
|
||||
Collectd.logError("Timely port must be configured");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Socket connect() {
|
||||
|
||||
Socket socket = null;
|
||||
long currentBackoff = initialBackoff;
|
||||
while (socket == null) {
|
||||
try {
|
||||
socket = new Socket(host, port);
|
||||
if (socketTimeout > -1) {
|
||||
socket.setSoTimeout(socketTimeout);
|
||||
}
|
||||
Collectd.logInfo("Connected to Timely at " + host + ":" + port + " from local port:" + socket.getLocalPort());
|
||||
} catch (Exception e) {
|
||||
Collectd.logError("Error connecting to Timely at " + host + ":" + port + ". Error: " + e.getMessage() + ". Will retry connection in "
|
||||
+ currentBackoff + " ms.");
|
||||
try {
|
||||
Thread.sleep(currentBackoff);
|
||||
} catch (InterruptedException e1) {
|
||||
|
||||
}
|
||||
// max out reconnect period at one minute
|
||||
currentBackoff = (currentBackoff * 2 > 60000) ? 60000 : currentBackoff * 2;
|
||||
}
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledObject<Socket> makeObject() {
|
||||
return new DefaultPooledObject<>(connect());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyObject(PooledObject<Socket> pooledObject) {
|
||||
try {
|
||||
Collectd.logDebug("Shutting down connection to Timely at " + host + ":" + port);
|
||||
Socket socket = pooledObject.getObject();
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Collectd.logError("Error closing connection to Timely at " + host + ":" + port + ". Error: " + e.getMessage());
|
||||
} finally {
|
||||
pooledObject.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateObject(PooledObject<Socket> pooledObject) {
|
||||
if (connectionTimeToLive > -1) {
|
||||
if (System.currentTimeMillis() > pooledObject.getCreateTime() + connectionTimeToLive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Socket socket = pooledObject.getObject();
|
||||
return socket != null && !socket.isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(PooledObject<Socket> pooledObject) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(PooledObject<Socket> pooledObject) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
package timely.collectd.plugin;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.collectd.api.Collectd;
|
||||
import org.collectd.api.DataSet;
|
||||
import org.collectd.api.DataSource;
|
||||
import org.collectd.api.OConfigItem;
|
||||
import org.collectd.api.ValueList;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.api.easymock.PowerMock;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({Collectd.class})
|
||||
@PowerMockIgnore({"javax.management.*", "jdk.internal.reflect.*"})
|
||||
public class WriteTimelyPluginTest {
|
||||
|
||||
private WriteTimelyPlugin plugin = null;
|
||||
private FakeServer server = null;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
PowerMock.suppress(PowerMock.everythingDeclaredIn(Collectd.class));
|
||||
server = new FakeServer();
|
||||
}
|
||||
|
||||
private ValueList createMetric() {
|
||||
ValueList val = new ValueList();
|
||||
val.setHost("r001n01.localdomain");
|
||||
val.setTime(System.currentTimeMillis());
|
||||
val.setPlugin("hddtemp");
|
||||
val.setPluginInstance(null);
|
||||
val.setType("temperature");
|
||||
val.setTypeInstance("sda");
|
||||
val.setValues(Collections.singletonList((Number) new Double(2.0)));
|
||||
DataSet ds = new DataSet("test");
|
||||
ds.addDataSource(new DataSource("test", DataSource.TYPE_COUNTER, 0, 100));
|
||||
val.setDataSet(ds);
|
||||
return val;
|
||||
}
|
||||
|
||||
private void setupPlugin() throws Exception {
|
||||
OConfigItem host = new OConfigItem("Host");
|
||||
host.addValue(server.getHost());
|
||||
OConfigItem port = new OConfigItem("Port");
|
||||
port.addValue(Integer.toString(server.getPort()));
|
||||
OConfigItem config = new OConfigItem("");
|
||||
config.addChild(host);
|
||||
config.addChild(port);
|
||||
plugin = new WriteTimelyPlugin();
|
||||
Assert.assertEquals(0, plugin.config(config));
|
||||
// Seed with one metric to create the connection
|
||||
Assert.assertEquals(0, plugin.write(createMetric()));
|
||||
Thread.sleep(100);
|
||||
Assert.assertTrue(server.messageReceived());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrite() throws Exception {
|
||||
Thread t = new Thread(server);
|
||||
t.start();
|
||||
setupPlugin();
|
||||
while (!server.ready()) {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
Assert.assertEquals(0, plugin.write(createMetric()));
|
||||
Thread.sleep(100);
|
||||
Assert.assertTrue(server.messageReceived());
|
||||
plugin.shutdown();
|
||||
server.shutdown();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAfterServerRestart() throws Exception {
|
||||
Thread t = new Thread(server);
|
||||
t.start();
|
||||
setupPlugin();
|
||||
while (!server.ready()) {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
Assert.assertEquals(0, plugin.write(createMetric()));
|
||||
Thread.sleep(100);
|
||||
Assert.assertTrue(server.messageReceived());
|
||||
server.shutdown();
|
||||
t.join();
|
||||
Thread.sleep(2000);
|
||||
|
||||
server.create();
|
||||
Thread t2 = new Thread(server);
|
||||
t2.start();
|
||||
// Need to call this again because the server is not guaranteed to be
|
||||
// listening on the same local port as the first time that it was
|
||||
// started
|
||||
setupPlugin();
|
||||
while (!server.ready()) {
|
||||
Thread.sleep(1000);
|
||||
// Keep sending metrics to plugin to force reconnect
|
||||
int result = plugin.write(createMetric());
|
||||
System.out.println("Wrote to client, result: " + result);
|
||||
Assert.assertEquals(0, result);
|
||||
}
|
||||
Assert.assertEquals(0, plugin.write(createMetric()));
|
||||
Thread.sleep(1000);
|
||||
Assert.assertTrue(server.messageReceived());
|
||||
plugin.shutdown();
|
||||
server.shutdown();
|
||||
t2.join();
|
||||
}
|
||||
|
||||
private static class FakeServer implements Runnable {
|
||||
|
||||
private ServerSocket server = null;
|
||||
private BufferedReader reader = null;
|
||||
private String host = null;
|
||||
private int port = 0;
|
||||
private Socket s = null;
|
||||
private boolean received = false;
|
||||
|
||||
public FakeServer() throws Exception {
|
||||
create();
|
||||
}
|
||||
|
||||
public void create() throws Exception {
|
||||
server = new ServerSocket(port);
|
||||
server.setReceiveBufferSize(8192);
|
||||
host = server.getInetAddress().getHostAddress();
|
||||
port = server.getLocalPort();
|
||||
System.out.println("Local port " + port);
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void shutdown() throws Exception {
|
||||
System.out.println("Closing server.");
|
||||
s.close();
|
||||
s = null;
|
||||
reader.close();
|
||||
reader = null;
|
||||
server.close();
|
||||
server = null;
|
||||
}
|
||||
|
||||
public boolean ready() throws Exception {
|
||||
return (s != null && s.isConnected());
|
||||
}
|
||||
|
||||
synchronized public boolean messageReceived() {
|
||||
try {
|
||||
return Boolean.valueOf(this.received);
|
||||
} finally {
|
||||
this.received = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
s = server.accept();
|
||||
System.out.println("Client connected.");
|
||||
reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
while (server != null && !server.isClosed() && s != null && s.isConnected()) {
|
||||
String line;
|
||||
try {
|
||||
line = reader.readLine();
|
||||
} catch (Exception e) {
|
||||
// Might have been closed
|
||||
System.out.println("Closed by Exception: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
if (null != line) {
|
||||
synchronized (this) {
|
||||
this.received = true;
|
||||
}
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
System.out.println("Exiting run method.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
sys.ethstat.*_to_.*
|
||||
sys.interface.if_packets
|
||||
sys.interface.if_octets
|
||||
@@ -1,3 +0,0 @@
|
||||
sys.interface.if_packets sampleType,instance
|
||||
sys.interface.if_octets sampleType,instance
|
||||
sys.ethstat.rx_queue_bytes sampleType,instance
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>timely-common</artifactId>
|
||||
<dependencies>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package timely.common.configuration;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import timely.util.Exclusions;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({AccumuloProperties.class, CacheProperties.class, CorsProperties.class, HttpProperties.class, MetaCacheProperties.class,
|
||||
RestClientProperties.class, ScanProperties.class, SecurityProperties.class, ServerProperties.class, SslClientProperties.class,
|
||||
@@ -14,15 +10,4 @@ import timely.util.Exclusions;
|
||||
|
||||
public class TimelyCommonConfiguration {
|
||||
|
||||
@Bean
|
||||
public Exclusions exclusions(TimelyProperties timelyProperties) {
|
||||
Exclusions exclusions = new Exclusions();
|
||||
if (StringUtils.isNotBlank(timelyProperties.getFilteredMetricsFile())) {
|
||||
exclusions.setFilteredMetricsFile(timelyProperties.getFilteredMetricsFile());
|
||||
}
|
||||
if (StringUtils.isNotBlank(timelyProperties.getFilteredTagsFile())) {
|
||||
exclusions.setFilteredTagsFile(timelyProperties.getFilteredTagsFile());
|
||||
}
|
||||
return exclusions;
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,6 @@ public class TimelyProperties {
|
||||
private int instance = 1;
|
||||
private int portIncrement = 100;
|
||||
private String defaultVisibility = null;
|
||||
private int tagFilterCacheSize = 10000;
|
||||
private String filteredMetricsFile = null;
|
||||
private String filteredTagsFile = null;
|
||||
|
||||
public boolean isTest() {
|
||||
return test;
|
||||
@@ -94,28 +91,4 @@ public class TimelyProperties {
|
||||
this.metricsReportIgnoredTags = metricsReportIgnoredTags;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setTagFilterCacheSize(int tagFilterCacheSize) {
|
||||
this.tagFilterCacheSize = tagFilterCacheSize;
|
||||
}
|
||||
|
||||
public int getTagFilterCacheSize() {
|
||||
return tagFilterCacheSize;
|
||||
}
|
||||
|
||||
public void setFilteredMetricsFile(String filteredMetricsFile) {
|
||||
this.filteredMetricsFile = filteredMetricsFile;
|
||||
}
|
||||
|
||||
public String getFilteredMetricsFile() {
|
||||
return filteredMetricsFile;
|
||||
}
|
||||
|
||||
public void setFilteredTagsFile(String filteredTagsFile) {
|
||||
this.filteredTagsFile = filteredTagsFile;
|
||||
}
|
||||
|
||||
public String getFilteredTagsFile() {
|
||||
return filteredTagsFile;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package timely.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
@@ -24,6 +25,12 @@ import timely.model.parse.TagParser;
|
||||
@JsonPropertyOrder({"name"})
|
||||
public class Metric implements Serializable {
|
||||
|
||||
// Capture the time that this class is loaded by the JVM for the purposes of
|
||||
// comparing the timestamp. Some systems, like Telegraf's OpenTSDB output
|
||||
// plugin, send the timestamp in seconds.
|
||||
private static final long TIME_LOADED = System.currentTimeMillis();
|
||||
private static final long TS_THRESHOLD = Duration.ofMillis(TIME_LOADED).minusDays(365).toMillis();
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String name;
|
||||
@@ -176,6 +183,9 @@ public class Metric implements Serializable {
|
||||
}
|
||||
|
||||
public Builder value(long timestamp, double measure) {
|
||||
if (timestamp <= TS_THRESHOLD) {
|
||||
timestamp = timestamp * 1000;
|
||||
}
|
||||
metric.setValue(new Value(timestamp, measure));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
@@ -91,7 +90,7 @@ public class Tag implements Comparable<Tag>, Serializable {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(this.key).append(this.value).toHashCode();
|
||||
return this.toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import timely.model.Tag;
|
||||
|
||||
@@ -25,7 +24,9 @@ public class TagListParser implements Parser<List<Tag>>, Combiner<Collection<Tag
|
||||
if (!p.isEmpty()) {
|
||||
Tag tag = tagParser.parse(p);
|
||||
// unescape commas in the key and value of the tag
|
||||
tags.add(unescapeCommas(tag));
|
||||
tag.setKey(tag.getKey().replaceAll("\\\\,", ","));
|
||||
tag.setValue(tag.getValue().replaceAll("\\\\,", ","));
|
||||
tags.add(tag);
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
@@ -35,9 +36,7 @@ public class TagListParser implements Parser<List<Tag>>, Combiner<Collection<Tag
|
||||
public String combine(Collection<Tag> tags) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (!tags.isEmpty()) {
|
||||
tags.forEach(p -> {
|
||||
builder.append(tagParser.combine(escapeCommas(p))).append(',');
|
||||
});
|
||||
tags.forEach(p -> builder.append(tagParser.combine(p)).append(','));
|
||||
builder.setLength(builder.length() - 1);
|
||||
}
|
||||
return builder.toString();
|
||||
@@ -49,26 +48,11 @@ public class TagListParser implements Parser<List<Tag>>, Combiner<Collection<Tag
|
||||
* @return string representation
|
||||
*/
|
||||
public String combine(Map<String,String> tags) {
|
||||
return combine(tags.entrySet().stream().map(e -> new Tag(e.getKey(), e.getValue())).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private Tag escapeCommas(Tag tag) {
|
||||
return escapeCommas(tag.getKey(), tag.getValue());
|
||||
}
|
||||
|
||||
private Tag escapeCommas(String k, String v) {
|
||||
k = k.replaceAll(",", "\\\\,");
|
||||
v = v.replaceAll(",", "\\\\,");
|
||||
return new Tag(k, v);
|
||||
}
|
||||
|
||||
private Tag unescapeCommas(Tag tag) {
|
||||
return unescapeCommas(tag.getKey(), tag.getValue());
|
||||
}
|
||||
|
||||
private Tag unescapeCommas(String k, String v) {
|
||||
k = k.replaceAll("\\\\,", ",");
|
||||
v = v.replaceAll("\\\\,", ",");
|
||||
return new Tag(k, v);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (!tags.isEmpty()) {
|
||||
tags.forEach((k, v) -> builder.append(tagParser.combine(new Tag(k, v))).append(','));
|
||||
builder.setLength(builder.length() - 1);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
package timely.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import timely.model.Metric;
|
||||
import timely.model.Tag;
|
||||
import timely.model.parse.MetricParser;
|
||||
|
||||
public class Exclusions {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Exclusions.class);
|
||||
private static final MetricParser metricParser = new MetricParser();
|
||||
private List<String> filteredMetrics = new ArrayList<>();
|
||||
private Map<String,Set<String>> filteredTags = new LinkedHashMap<>();
|
||||
|
||||
public interface LineHandler {
|
||||
void handleLine(String line);
|
||||
}
|
||||
|
||||
public void readFile(String file, LineHandler lineHandler) {
|
||||
File f = new File(file);
|
||||
if (f.exists() && f.isFile() && f.canRead()) {
|
||||
try (InputStream iStream = new FileInputStream(f);
|
||||
InputStreamReader streamReader = new InputStreamReader(iStream, StandardCharsets.UTF_8);
|
||||
BufferedReader reader = new BufferedReader(streamReader)) {
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
lineHandler.handleLine(line);
|
||||
} catch (Exception e) {
|
||||
log.error(MessageFormat.format("Error reading line {0}", line), e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(MessageFormat.format("Error reading file {0}", file), e);
|
||||
}
|
||||
} else {
|
||||
log.error(MessageFormat.format("File ''{0}'' either does not exist or is not readable", file));
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getFilteredMetrics(String filteredMetricsFile) {
|
||||
List<String> filteredMetricRegexes = new ArrayList<>();
|
||||
readFile(filteredMetricsFile, (line) -> {
|
||||
if (!line.endsWith(".*")) {
|
||||
line = line + ".*";
|
||||
}
|
||||
filteredMetricRegexes.add(line);
|
||||
});
|
||||
return filteredMetricRegexes;
|
||||
}
|
||||
|
||||
public Map<String,Set<String>> getFilteredTags(String filteredTagsFile) {
|
||||
Map<String,Set<String>> filteredTagsForMetrics = new LinkedHashMap<>();
|
||||
readFile(filteredTagsFile, (line) -> {
|
||||
int x = line.indexOf(" ");
|
||||
String metric = line.substring(0, x);
|
||||
String tags = line.substring(x + 1).trim();
|
||||
Set<String> tagSet = Arrays.stream(tags.split(",")).map(tag -> tag.trim()).collect(Collectors.toSet());
|
||||
filteredTagsForMetrics.put(metric, tagSet);
|
||||
});
|
||||
return filteredTagsForMetrics;
|
||||
}
|
||||
|
||||
public void setFilteredMetricsFile(String filteredMetricsFile) {
|
||||
this.filteredMetrics = getFilteredMetrics(filteredMetricsFile);
|
||||
}
|
||||
|
||||
public void setFilteredTagsFile(String filteredTagsFile) {
|
||||
this.filteredTags = getFilteredTags(filteredTagsFile);
|
||||
}
|
||||
|
||||
// format put metric timestamp value tag1=value1 tag2=value2 tag3=value3
|
||||
// where the tags are sorted
|
||||
public boolean filterMetric(String metricPutLine) {
|
||||
String metricLine = buildMetricLine(metricPutLine);
|
||||
for (String filteredRegex : filteredMetrics) {
|
||||
if (metricLine.matches(filteredRegex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean filterMetric(Metric metric) {
|
||||
String metricLine = buildMetricLine(metric);
|
||||
for (String filteredRegex : filteredMetrics) {
|
||||
if (metricLine.matches(filteredRegex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String buildMetricLine(String metricPutLine) {
|
||||
Metric metric = metricParser.parse(metricPutLine);
|
||||
return buildMetricLine(metric);
|
||||
}
|
||||
|
||||
protected String buildMetricLine(Metric metric) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(metric.getName()).append(" ");
|
||||
metric.getTags().stream().forEach(t -> sb.append(t.join()).append(" "));
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
public String filterExcludedTags(String metricLineOrig) {
|
||||
if (filteredTags.isEmpty()) {
|
||||
return metricLineOrig;
|
||||
}
|
||||
Metric metric = metricParser.parse(metricLineOrig);
|
||||
filterExcludedTags(metric);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("put ");
|
||||
sb.append(metric.getName()).append(" ");
|
||||
sb.append(metric.getValue().getTimestamp()).append(" ");
|
||||
sb.append(metric.getValue().getMeasure()).append(" ");
|
||||
metric.getTags().stream().forEach(t -> sb.append(t.join()).append(" "));
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
public void filterExcludedTags(Metric metric) {
|
||||
if (!filteredTags.isEmpty()) {
|
||||
Set<String> tags = filteredTags.get(metric.getName());
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
List<Tag> filteredTags = metric.getTags().stream().filter(t -> !tags.contains(t.getKey())).collect(Collectors.toList());
|
||||
metric.setTags(filteredTags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,13 +84,13 @@ public class MetricAdapterTest {
|
||||
|
||||
@Test
|
||||
public void testParse() throws Exception {
|
||||
Long ts = System.currentTimeMillis();
|
||||
PairLexicoder<String,Long> rowCoder = new PairLexicoder<>(new StringLexicoder(), new LongLexicoder());
|
||||
byte[] row = rowCoder.encode(new ComparablePair<>("sys.cpu.user", 1000L));
|
||||
byte[] row = rowCoder.encode(new ComparablePair<>("sys.cpu.user", ts));
|
||||
byte[] value = new byte[Double.BYTES];
|
||||
ByteBuffer.wrap(value).putDouble(2.0D);
|
||||
PairLexicoder<Long,String> colQualCoder = new PairLexicoder<>(new LongLexicoder(), new StringLexicoder());
|
||||
Key k = new Key(row, "tag1=value1".getBytes(), colQualCoder.encode(new ComparablePair<>(new Long(1000), "tag2=value2,tag3=value3")),
|
||||
"(a&b)|(c&d)".getBytes(), 1000);
|
||||
Key k = new Key(row, "tag1=value1".getBytes(), colQualCoder.encode(new ComparablePair<>(ts, "tag2=value2,tag3=value3")), "(a&b)|(c&d)".getBytes(), ts);
|
||||
Value v = new Value(value);
|
||||
Metric m = MetricAdapter.parse(k, v);
|
||||
Assert.assertEquals("sys.cpu.user", m.getName());
|
||||
@@ -99,19 +99,20 @@ public class MetricAdapterTest {
|
||||
tags.add(new Tag("tag2=value2"));
|
||||
tags.add(new Tag("tag3=value3"));
|
||||
Assert.assertEquals(tags, m.getTags());
|
||||
Assert.assertEquals(new Long(1000), m.getValue().getTimestamp());
|
||||
Assert.assertEquals(ts, m.getValue().getTimestamp());
|
||||
Assert.assertEquals(2.0D, m.getValue().getMeasure(), 0.0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseWithEscapes() {
|
||||
Long ts = System.currentTimeMillis();
|
||||
PairLexicoder<String,Long> rowCoder = new PairLexicoder<>(new StringLexicoder(), new LongLexicoder());
|
||||
byte[] row = rowCoder.encode(new ComparablePair<>("sys.cpu.user", 1000L));
|
||||
byte[] row = rowCoder.encode(new ComparablePair<>("sys.cpu.user", ts));
|
||||
byte[] value = new byte[Double.BYTES];
|
||||
ByteBuffer.wrap(value).putDouble(2.0D);
|
||||
PairLexicoder<Long,String> colQualCoder = new PairLexicoder<>(new LongLexicoder(), new StringLexicoder());
|
||||
Key k = new Key(row, "tag1=value1".getBytes(), colQualCoder.encode(new ComparablePair<>(new Long(1000), "tag2=test\\,value2,tag3=val\\=ue3")),
|
||||
"(a&b)|(c&d)".getBytes(), 1000);
|
||||
Key k = new Key(row, "tag1=value1".getBytes(), colQualCoder.encode(new ComparablePair<>(ts, "tag2=test\\,value2,tag3=val\\=ue3")),
|
||||
"(a&b)|(c&d)".getBytes(), ts);
|
||||
Value v = new Value(value);
|
||||
Metric m = MetricAdapter.parse(k, v);
|
||||
Assert.assertEquals("sys.cpu.user", m.getName());
|
||||
@@ -120,19 +121,19 @@ public class MetricAdapterTest {
|
||||
tags.add(new Tag("tag2=test,value2"));
|
||||
tags.add(new Tag("tag3=val\\=ue3"));
|
||||
Assert.assertEquals(tags, m.getTags());
|
||||
Assert.assertEquals(new Long(1000), m.getValue().getTimestamp());
|
||||
Assert.assertEquals(ts, m.getValue().getTimestamp());
|
||||
Assert.assertEquals(2.0D, m.getValue().getMeasure(), 0.0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseWithViz() throws Exception {
|
||||
Long ts = System.currentTimeMillis();
|
||||
PairLexicoder<String,Long> rowCoder = new PairLexicoder<>(new StringLexicoder(), new LongLexicoder());
|
||||
byte[] row = rowCoder.encode(new ComparablePair<>("sys.cpu.user", 1000L));
|
||||
byte[] row = rowCoder.encode(new ComparablePair<>("sys.cpu.user", ts));
|
||||
byte[] value = new byte[Double.BYTES];
|
||||
ByteBuffer.wrap(value).putDouble(2.0D);
|
||||
PairLexicoder<Long,String> colQualCoder = new PairLexicoder<>(new LongLexicoder(), new StringLexicoder());
|
||||
Key k = new Key(row, "tag1=value1".getBytes(), colQualCoder.encode(new ComparablePair<>(new Long(1000), "tag2=value2,tag3=value3")),
|
||||
"(a&b)|(c&d)".getBytes(), 1000);
|
||||
Key k = new Key(row, "tag1=value1".getBytes(), colQualCoder.encode(new ComparablePair<>(ts, "tag2=value2,tag3=value3")), "(a&b)|(c&d)".getBytes(), ts);
|
||||
Value v = new Value(value);
|
||||
Metric m = MetricAdapter.parse(k, v, true);
|
||||
Assert.assertEquals("sys.cpu.user", m.getName());
|
||||
@@ -142,7 +143,7 @@ public class MetricAdapterTest {
|
||||
tags.add(new Tag("tag3=value3"));
|
||||
tags.add(new Tag("viz=(a&b)|(c&d)"));
|
||||
Assert.assertEquals(tags, m.getTags());
|
||||
Assert.assertEquals(new Long(1000), m.getValue().getTimestamp());
|
||||
Assert.assertEquals(ts, m.getValue().getTimestamp());
|
||||
Assert.assertEquals(2.0D, m.getValue().getMeasure(), 0.0D);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package timely.util;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExclusionTest {
|
||||
|
||||
@Test
|
||||
public void testLoadFilteredMetricsFile() {
|
||||
Exclusions exclusions = new Exclusions();
|
||||
URL url = getClass().getClassLoader().getResource("filteredMetrics.txt");
|
||||
List<String> metricExclusions = exclusions.getFilteredMetrics(url.getFile());
|
||||
Assert.assertEquals(4, metricExclusions.size());
|
||||
System.out.println(metricExclusions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadFilteredTagsFile() {
|
||||
Exclusions exclusions = new Exclusions();
|
||||
URL url = getClass().getClassLoader().getResource("filteredTags.txt");
|
||||
Map<String,Set<String>> filteredTags = exclusions.getFilteredTags(url.getFile());
|
||||
Assert.assertEquals(2, filteredTags.size());
|
||||
System.out.println(filteredTags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetricExclusions() {
|
||||
Exclusions exclusions = new Exclusions();
|
||||
URL filteredMetrics = getClass().getClassLoader().getResource("filteredMetrics.txt");
|
||||
URL filteredTags = getClass().getClassLoader().getResource("filteredTags.txt");
|
||||
exclusions.setFilteredMetricsFile(filteredMetrics.getFile());
|
||||
exclusions.setFilteredTagsFile(filteredTags.getFile());
|
||||
|
||||
String metric1 = "put sys.interface.if_octets 1740090590221 71838.0 host=localhost instance=veth88545ad sampleType=DERIVE";
|
||||
Assert.assertTrue(exclusions.filterMetric(metric1));
|
||||
String metric2 = "put sys.interface.if_errors 1740090590221 71838.0 host=localhost instance=veth88545ad sampleType=DERIVE";
|
||||
Assert.assertFalse(exclusions.filterMetric(metric2));
|
||||
Assert.assertEquals("put sys.interface.if_octets 1740090590221 71838.0 host=localhost", exclusions.filterExcludedTags(metric1));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
sys.ethstat.(tx|rx)[-]?[0-9]+[_.]
|
||||
sys.ethstat.*_to_.*
|
||||
sys.interface.if_packets
|
||||
sys.interface.if_octets
|
||||
@@ -1,2 +0,0 @@
|
||||
sys.interface.if_packets sampleType,instance
|
||||
sys.interface.if_octets sampleType,instance
|
||||
@@ -7,9 +7,9 @@
|
||||
</formats>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>timely-datasource/dist</directory>
|
||||
<outputDirectory>timely-datasource</outputDirectory>
|
||||
<directory>timely-app/dist</directory>
|
||||
<outputDirectory>timely-app</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
</assembly>
|
||||
</assembly>
|
||||
@@ -4,9 +4,9 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>timely-datasource</artifactId>
|
||||
<artifactId>timely-app</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
...require('@grafana/toolkit/src/config/prettier.plugin.config.json'),
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
httpProperties://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
@@ -192,10 +192,10 @@
|
||||
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
|
||||
httpProperties://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.
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,18 @@
|
||||
//+build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
// mage:import
|
||||
_ "github.com/grafana/grafana-plugin-sdk-go/build"
|
||||
)
|
||||
|
||||
// CheckCheck builds production back-end components.
|
||||
func CheckCheck() {
|
||||
fmt.Println("hello! TODO.... (the other commands are imported)")
|
||||
}
|
||||
|
||||
// Default configures the default target.
|
||||
var Default = CheckCheck
|
||||
@@ -0,0 +1,6 @@
|
||||
# Timely Data Source Plugin
|
||||
|
||||
Timely is a time series database application that provides secure access to time
|
||||
series data. Timely is written in Java, uses
|
||||
[Apache Accumulo](https://accumuloProperties.apache.org/) for backend storage, and has
|
||||
a configurable length memory cache.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Test against the latest version of this Node.js version
|
||||
environment:
|
||||
nodejs_version: '10'
|
||||
|
||||
# Local NPM Modules
|
||||
cache:
|
||||
- node_modules
|
||||
|
||||
# Install scripts. (runs after repo cloning)
|
||||
install:
|
||||
# Get the latest stable version of Node.js or io.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
# install modules
|
||||
- npm install -g yarn --quiet
|
||||
- yarn install --pure-lockfile
|
||||
|
||||
# Post-install test scripts.
|
||||
test_script:
|
||||
# Output useful info for debugging.
|
||||
- node --version
|
||||
- npm --version
|
||||
|
||||
# Run the build
|
||||
build_script:
|
||||
- yarn dev # This will also run prettier!
|
||||
- yarn build # make sure both scripts work
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="jest tests" tests="1" failures="0" time="1.179">
|
||||
<testsuite name="placeholder test" errors="0" failures="0" skipped="0" timestamp="2021-10-22T20:15:17" time="0.552" tests="1">
|
||||
<testcase classname="placeholder test should return true" name="placeholder test should return true" time="0.003">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
@@ -198,4 +198,4 @@
|
||||
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.
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Timely Data Source Plugin
|
||||
|
||||
Timely is a time series database application that provides secure access to time
|
||||
series data. Timely is written in Java, uses
|
||||
[Apache Accumulo](https://accumulo.apache.org/) for backend storage, and has
|
||||
a configurable length memory cache.
|
||||
@@ -0,0 +1,2 @@
|
||||
define((function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=71)}({71:function(e,t,n){}})}));
|
||||
//# sourceMappingURL=dark.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///webpack/bootstrap"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s"],"mappings":"sCACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,IAIjBlC,EAAoBA,EAAoBmC,EAAI,I","file":"dark.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 71);\n"],"sourceRoot":""}
|
||||
@@ -0,0 +1,2 @@
|
||||
define((function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=70)}({70:function(e,t,n){}})}));
|
||||
//# sourceMappingURL=light.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///webpack/bootstrap"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s"],"mappings":"sCACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,IAIjBlC,EAAoBA,EAAoBmC,EAAI,I","file":"light.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 70);\n"],"sourceRoot":""}
|
||||
@@ -0,0 +1,3 @@
|
||||
/*! For license information please see module.js.LICENSE.txt */
|
||||
define(["react","@grafana/ui","react-dom","lodash","@grafana/runtime","@grafana/data"],(function(e,t,n,r,o,i){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=72)}([function(t,n){t.exports=e},function(e,t,n){e.exports=n(48)()},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},e.exports.default=e.exports,e.exports.__esModule=!0,n.apply(this,arguments)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){var r;!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var i=typeof r;if("string"===i||"number"===i)e.push(r);else if(Array.isArray(r)){if(r.length){var a=o.apply(null,r);a&&e.push(a)}}else if("object"===i)if(r.toString===Object.prototype.toString)for(var s in r)n.call(r,s)&&r[s]&&e.push(s);else e.push(r.toString())}}return e.join(" ")}e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()},function(e,n){e.exports=t},function(e,t,n){var r=n(50);e.exports=function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)},e.exports.default=e.exports,e.exports.__esModule=!0},,function(e,t){e.exports=n},function(e,t){e.exports=r},function(e,t){e.exports=o},function(e,t,n){"use strict";e.exports=function e(t,n){if(t===n)return!0;if(t&&n&&"object"==typeof t&&"object"==typeof n){if(t.constructor!==n.constructor)return!1;var r,o,i;if(Array.isArray(t)){if((r=t.length)!=n.length)return!1;for(o=r;0!=o--;)if(!e(t[o],n[o]))return!1;return!0}if(t.constructor===RegExp)return t.source===n.source&&t.flags===n.flags;if(t.valueOf!==Object.prototype.valueOf)return t.valueOf()===n.valueOf();if(t.toString!==Object.prototype.toString)return t.toString()===n.toString();if((r=(i=Object.keys(t)).length)!==Object.keys(n).length)return!1;for(o=r;0!=o--;)if(!Object.prototype.hasOwnProperty.call(n,i[o]))return!1;for(o=r;0!=o--;){var a=i[o];if(!e(t[a],n[a]))return!1}return!0}return t!=t&&n!=n}},function(e,t,n){"use strict";e.exports=function(e,t,n,r,o,i,a,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,o,i,a,s],c=0;(l=new Error(t.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},function(e,t,n){"use strict";var r=n(26),o="function"==typeof Symbol&&"symbol"==typeof Symbol("foo"),i=Object.prototype.toString,a=Array.prototype.concat,s=Object.defineProperty,l=s&&function(){var e={};try{for(var t in s(e,"x",{enumerable:!1,value:e}),e)return!1;return e.x===e}catch(e){return!1}}(),u=function(e,t,n,r){var o;(!(t in e)||"function"==typeof(o=r)&&"[object Function]"===i.call(o)&&r())&&(l?s(e,t,{configurable:!0,enumerable:!1,value:n,writable:!0}):e[t]=n)},c=function(e,t){var n=arguments.length>2?arguments[2]:{},i=r(t);o&&(i=a.call(i,Object.getOwnPropertySymbols(t)));for(var s=0;s<i.length;s+=1)u(e,i[s],t[i[s]],n[i[s]])};c.supportsDescriptors=!!l,e.exports=c},function(e,t,n){"use strict";var r=function(){};e.exports=r},function(e,t,n){"use strict";function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}n.d(t,"a",(function(){return r}))},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeoLine truncated
|
||||
//# sourceMappingURL=module.js.map
|
||||
@@ -0,0 +1,87 @@
|
||||
/*!
|
||||
Copyright (c) 2018 Jed Watson.
|
||||
Licensed under the MIT License (MIT), see
|
||||
http://jedwatson.github.io/classnames
|
||||
*/
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
/**
|
||||
* A better abstraction over CSS.
|
||||
*
|
||||
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
|
||||
* @website https://github.com/cssinjs/jss
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/** @license React v16.13.1
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**!
|
||||
* @fileOverview Kickass library to create and place poppers near their reference elements.
|
||||
* @version 1.16.1
|
||||
* @license
|
||||
* Copyright (c) 2016 Federico Zivolo and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**!
|
||||
* @fileOverview Kickass library to create and place poppers near their reference elements.
|
||||
* @version 1.16.1-lts
|
||||
* @license
|
||||
* Copyright (c) 2016 Federico Zivolo and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///external \"react\"","webpack:///../node_modules/prop-types/index.js","webpack:///../node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack:///../node_modules/@babel/runtime/helpers/defineProperty.js","webpack:///../node_modules/@babel/runtime/helpers/extends.js","webpack:///../node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js","webpack:///../node_modules/classnames/index.js","webpack:///external \"@grafana/ui\"","webpack:///../node_modules/@babel/runtime/helpers/inheritsLoose.js","webpack:///external \"react-dom\"","webpack:///external \"lodash\"","webpack:///external \"@grafana/runtime\"","webpack:///../node_modules/fast-deep-equal/index.js","webpack:///../node_modules/invariant/browser.js","webpack:///../node_modules/define-properties/index.js","webpack:///../node_modules/warning/warning.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///../node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js","webpack:///../node_modules/function-bind/index.js","webpack:///../node_modules/call-bind/index.js","webpack:///../node_modules/popper.js/dist/esm/popper.js","webpack:///../node_modules/@hypnosphi/create-react-context/lib/index.js","webpack:///../node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js","webpack:///../node_modules/object-keys/index.js","webpack:///../node_modules/object-keys/isArguments.js","webpack:///../node_modules/call-bind/callBound.js","webpack:///../node_modules/get-intrinsic/index.js","webpack:///../node_modules/has-symbols/shams.js","webpack:///../node_modules/object-is/implementation.js","webpack:///../node_modules/object-is/polyfill.js","webpack:///../node_modules/regexp.prototype.flags/implementation.js","webpack:///../node_modules/regexp.prototype.flags/polyfill.js","webpack:///../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js","webpack:///../node_modules/css-loader/dist/runtime/api.js","webpack:///external \"@grafana/data\"","webpack:///../node_modules/dayjs/dayjs.min.js","webpack:///../node_modules/lodash.debounce/index.js","webpack:///../node_modules/deep-equal/index.js","webpack:///../node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js","webpack:///../node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack:///../node_modules/@babel/runtime/helpers/esm/iterableToArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js","webpack:///../node_modules/@babel/runtime/helpers/esm/nonIterableRest.js","webpack:///../node_modules/@material-ui/core/node_modules/popper.js/dist/esm/popper.js","webpack:///../node_modules/prop-types/factoryWithThrowingShims.js","webpack:///../node_modules/prop-types/lib/ReactPropTypesSecret.js","webpack:///../node_modules/@babel/runtime/helpers/setPrototypeOf.js","webpack:///../node_modules/object-keys/implementation.js","webpack:///../node_modules/is-arguments/index.js","webpack:///../node_modules/has-symbols/index.js","webpack:///../node_modules/function-bind/implementation.js","webpack:///../node_modules/has/src/index.js","webpack:///../node_modules/object-is/index.js","webpack:///../node_modules/object-is/shim.js","webpack:///../node_modules/is-regex/index.js","webpack:///../node_modules/regexp.prototype.flags/index.js","webpack:///../node_modules/regexp.prototype.flags/shim.js","webpack:///../node_modules/is-date-object/index.js","webpack:///../node_modules/@hypnosphi/create-react-context/lib/implementation.js","webpack:///../node_modules/gud/index.js","webpack:///../node_modules/react-is/index.js","webpack:///../node_modules/react-is/cjs/react-is.production.min.js","webpack:///./static/css/timely-bootstrap.css?617f","webpack:///./static/css/timely-bootstrap.css","webpack:///./static/css/timely.css?f98e","webpack:///./static/css/timely.css","webpack:///../node_modules/tslib/tslib.es6.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/isFunction.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/lift.js","webpack:///../node_modules/rxjs/node_modules/tslib/tslib.es6.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/arrRemove.js","webpack:///../node_modules/rxjs/dist/esm5/internal/Subscription.js","webpack:///../node_modules/rxjs/dist/esm5/internal/config.js","webpack:///../node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/noop.js","webpack:///../node_modules/rxjs/dist/esm5/internal/NotificationFactories.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/errorContext.js","webpack:///../node_modules/rxjs/dist/esm5/inteLine truncated
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"type": "datasource",
|
||||
"name": "Timely",
|
||||
"id": "nsa-timely-datasource",
|
||||
"category": "tsdb",
|
||||
"metrics": true,
|
||||
"backend": true,
|
||||
"alerting": true,
|
||||
"executable": "timely_datasource_backend",
|
||||
"info": {
|
||||
"description": "Open source time series database backed by Accumulo",
|
||||
"author": {
|
||||
"name": "National Security Agency"
|
||||
},
|
||||
"keywords": ["Simple"],
|
||||
"logos": {
|
||||
"small": "static/img/timely_square_small.png",
|
||||
"large": "static/img/timely_square_large.png"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"name": "Website",
|
||||
"url": "https://code.nsa.gov/timely"
|
||||
},
|
||||
{
|
||||
"name": "License",
|
||||
"url": "https://github.com/NationalSecurityAgency/timely/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"screenshots": [],
|
||||
"version": "2.1.6-SNAPSHOT",
|
||||
"updated": "2024-04-10"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "2.2.6",
|
||||
"slate-plain-serializer": "0.7.10",
|
||||
"grafanaVersion": "6.5.x",
|
||||
"plugins": []
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@ div.timely input:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.timely-edior-row div.gf-form-inline {
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
div.timely input.form-control {
|
||||
border-color: rgb(44, 50, 53);
|
||||
border-top-color: rgb(44, 50, 53);
|
||||
@@ -52,10 +56,6 @@ div.timely.tag.addtag svg {
|
||||
color: #62a562;
|
||||
}
|
||||
|
||||
div.timely.tag.deletetag svg {
|
||||
color: #d9162d;
|
||||
}
|
||||
|
||||
button[title='Move query down'] div svg {
|
||||
color: #b3bfbd;
|
||||
}
|
||||
@@ -75,36 +75,3 @@ button[title='Disable/enable query'] div svg {
|
||||
button[title='Remove query'] div svg {
|
||||
color: #d9162d;
|
||||
}
|
||||
|
||||
.queryErrorFieldRow {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.queryErrorContainer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.queryErrorIconDiv {
|
||||
background-color: rgb(209, 14, 92);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.queryErrorIcon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
line-height: 0;
|
||||
vertical-align: middle;
|
||||
fill: rgb(255, 255, 255);
|
||||
overflow-clip-margin: content-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.queryErrorText {
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
font-size: 0.857143rem;
|
||||
font-family: "Roboto Mono", monospace;
|
||||
padding: 8px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,54 @@
|
||||
$box-shadow-dimensions: 0 0 0 0.2rem;
|
||||
$placeholder-color: #6c757d;
|
||||
|
||||
.rbt {
|
||||
&-input-multi {
|
||||
// Bootstrap 4 focus style
|
||||
&.focus {
|
||||
background-color: #fff;
|
||||
border-color: #80bdff;
|
||||
box-shadow: $box-shadow-dimensions rgba(0, 123, 255, 0.25);
|
||||
color: #495057;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&.is-invalid.focus {
|
||||
border-color: #dc3545;
|
||||
box-shadow: $box-shadow-dimensions rgba(220, 53, 69, 0.25);
|
||||
}
|
||||
|
||||
&.is-valid.focus {
|
||||
border-color: #28a745;
|
||||
box-shadow: $box-shadow-dimensions rgba(40, 167, 69, 0.25);
|
||||
}
|
||||
|
||||
input {
|
||||
// Firefox
|
||||
&::-moz-placeholder {
|
||||
color: $placeholder-color;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Internet Explorer 10+
|
||||
&:-ms-input-placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
|
||||
// Safari and Chrome
|
||||
&::-webkit-input-placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
// Override height in main CSS file :/
|
||||
& .rbt-input-main,
|
||||
&.form-control-lg .rbt-input-main,
|
||||
&.form-control-sm .rbt-input-main {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-token {
|
||||
margin: 1px 3px 2px 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
.rbt .rbt-input-main::-ms-clear {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu
|
||||
*/
|
||||
.rbt-menu {
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.rbt-menu > .dropdown-item {
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
.rbt-menu > .dropdown-item:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.rbt-menu-pagination-option {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-select Input
|
||||
*/
|
||||
.rbt-input-multi {
|
||||
cursor: text !important;
|
||||
overflow: hidden !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.focus {
|
||||
border-color: #80bdff !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
||||
color: #495057 !important;
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.form-control {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.form-control[disabled] {
|
||||
background-color: #e9ecef !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.is-invalid.focus {
|
||||
border-color: #dc3545 !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.is-valid.focus {
|
||||
border-color: #28a745 !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi input::-moz-placeholder {
|
||||
color: #6c757d !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi input:-ms-input-placeholder {
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi input::-webkit-input-placeholder {
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi .rbt-input-wrapper {
|
||||
align-items: flex-start !important;
|
||||
display: flex !important;
|
||||
flex-wrap: wrap !important;
|
||||
margin-bottom: -4px !important;
|
||||
margin-top: -1px !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi .rbt-input-main {
|
||||
margin: 1px 0 4px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Button
|
||||
*/
|
||||
.rbt-close {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
|
||||
.rbt-close-lg {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token
|
||||
*/
|
||||
.rbt-token {
|
||||
background-color: #e7f4ff !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0.25rem !important;
|
||||
color: #007bff !important;
|
||||
display: inline-block !important;
|
||||
line-height: 1em !important;
|
||||
margin: 1px 3px 2px 0 !important;
|
||||
padding: 4px 7px !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.rbt-token-disabled {
|
||||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||||
color: #495057 !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.rbt-token-removeable {
|
||||
cursor: pointer !important;
|
||||
padding-right: 21px !important;
|
||||
}
|
||||
|
||||
.rbt-token-active {
|
||||
background-color: #007bff !important;
|
||||
color: #fff !important;
|
||||
outline: none !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.rbt-token .rbt-token-remove-button {
|
||||
bottom: 0 !important;
|
||||
color: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: normal !important;
|
||||
opacity: 1 !important;
|
||||
outline: none !important;
|
||||
padding: 3px 7px !important;
|
||||
position: absolute !important;
|
||||
right: 0 !important;
|
||||
text-shadow: none !important;
|
||||
top: -2px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loader + CloseButton container
|
||||
*/
|
||||
.rbt-aux {
|
||||
align-items: center !important;
|
||||
display: flex !important;
|
||||
bottom: 0 !important;
|
||||
justify-content: center !important;
|
||||
pointer-events: none !important;
|
||||
/* Don't block clicks on the input */
|
||||
position: absolute !important;
|
||||
right: 0 !important;
|
||||
top: 0 !important;
|
||||
width: 34px !important;
|
||||
}
|
||||
|
||||
.rbt-aux-lg {
|
||||
width: 46px !important;
|
||||
}
|
||||
|
||||
.rbt-aux .rbt-close {
|
||||
margin-top: -4px !important;
|
||||
pointer-events: auto !important;
|
||||
/* Override pointer-events: none; above */
|
||||
}
|
||||
|
||||
.has-aux .rbt-input {
|
||||
padding-right: 34px !important;
|
||||
}
|
||||
|
||||
.rbt-highlight-text {
|
||||
background-color: inherit !important;
|
||||
color: inherit !important;
|
||||
font-weight: bold !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input Groups
|
||||
*/
|
||||
.input-group > .rbt {
|
||||
flex: 1 !important;
|
||||
}
|
||||
|
||||
.input-group > .rbt .rbt-input-hint,
|
||||
.input-group > .rbt .rbt-aux {
|
||||
z-index: 5 !important;
|
||||
}
|
||||
|
||||
.input-group > .rbt:not(:first-child) .form-control {
|
||||
border-top-left-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
}
|
||||
|
||||
.input-group > .rbt:not(:last-child) .form-control {
|
||||
border-top-right-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
$animation: loader-animation 600ms infinite linear;
|
||||
$inset: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
$placeholder-color: #999;
|
||||
|
||||
.rbt {
|
||||
&-menu {
|
||||
margin-bottom: 2px; // Spacing for dropup
|
||||
|
||||
& > li a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-pagination-option {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide IE's native "clear" button
|
||||
& .rbt-input-main::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-input-multi {
|
||||
cursor: text;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: auto;
|
||||
|
||||
// Apply Bootstrap focus styles
|
||||
&.focus {
|
||||
box-shadow: $inset, 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
border-color: #66afe9;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
// BS4 uses the :disabled pseudo-class, which doesn't work with non-inputs.
|
||||
&.form-control[disabled] {
|
||||
background-color: #e9ecef;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Apply Bootstrap placeholder styles
|
||||
input {
|
||||
// Firefox
|
||||
&::-moz-placeholder {
|
||||
color: $placeholder-color;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Internet Explorer 10+
|
||||
&:-ms-input-placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
|
||||
// Safari and Chrome
|
||||
&::-webkit-input-placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
.rbt-input-wrapper {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: -4px;
|
||||
margin-top: -1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rbt-input-main {
|
||||
// Set input height for cross-browser consistency
|
||||
height: 20px;
|
||||
margin: 1px 0 4px;
|
||||
}
|
||||
|
||||
&.input,
|
||||
&.form-control {
|
||||
&-lg {
|
||||
.rbt-input-main {
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&-sm {
|
||||
.rbt-input-main {
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-close {
|
||||
z-index: 1;
|
||||
|
||||
&-lg {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&-token {
|
||||
background-color: #e7f4ff;
|
||||
border: 0;
|
||||
border-radius: 2px;
|
||||
color: #1f8dd6;
|
||||
display: inline-block;
|
||||
line-height: 1em;
|
||||
margin: 0 3px 3px 0;
|
||||
padding: 4px 7px;
|
||||
position: relative;
|
||||
|
||||
&-disabled {
|
||||
background-color: #ddd;
|
||||
color: #888;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&-removeable {
|
||||
cursor: pointer;
|
||||
padding-right: 21px;
|
||||
}
|
||||
|
||||
&-active {
|
||||
background-color: #1f8dd6;
|
||||
color: #fff;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
& &-remove-button {
|
||||
bottom: 0;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: normal;
|
||||
opacity: 1;
|
||||
outline: none;
|
||||
padding: 3px 7px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
text-shadow: none;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
&-loader {
|
||||
-moz-animation: $animation;
|
||||
-webkit-animation: $animation;
|
||||
animation: $animation;
|
||||
border: 1px solid #d5d5d5;
|
||||
border-radius: 50%;
|
||||
border-top-color: #1f8dd6;
|
||||
display: block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
||||
&-lg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&-aux {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
bottom: 0;
|
||||
justify-content: center;
|
||||
pointer-events: none; /* Don't block clicks on the input */
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 34px;
|
||||
|
||||
&-lg {
|
||||
width: 46px;
|
||||
}
|
||||
|
||||
& .rbt-close {
|
||||
margin-top: -4px;
|
||||
pointer-events: auto; /* Override pointer-events: none; above */
|
||||
}
|
||||
}
|
||||
|
||||
.has-aux &-input {
|
||||
padding-right: 34px;
|
||||
}
|
||||
|
||||
&-highlight-text {
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Input Groups */
|
||||
.input-group > .rbt {
|
||||
flex: 1;
|
||||
|
||||
// Form-controls within input-groups have a higher z-index.
|
||||
& .rbt-input-hint,
|
||||
& .rbt-aux {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
&:not(:first-child) .form-control {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
&:not(:last-child) .form-control {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validation States */
|
||||
.has-error .rbt-input-multi.focus {
|
||||
border-color: #843534;
|
||||
box-shadow: $inset, 0 0 6px #ce8483;
|
||||
}
|
||||
|
||||
.has-warning .rbt-input-multi.focus {
|
||||
border-color: #66512c;
|
||||
box-shadow: $inset, 0 0 6px #c0a16b;
|
||||
}
|
||||
|
||||
.has-success .rbt-input-multi.focus {
|
||||
border-color: #2b542c;
|
||||
box-shadow: $inset, 0 0 6px #67b168;
|
||||
}
|
||||
|
||||
@keyframes loader-animation {
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
div.timely .dropdown-item,div.timely .dropdown-item-text,div.timely input.form-control{color:#c7d0d9;background-color:#0b0c0e}.dropdown-item:active,.dropdown-item:focus,div.timely .dropdown-item.active,div.timely .dropdown-item:hover{background-color:#4f5255}.dropdown-item:disabled,div.timely .dropdown-header,div.timely .dropdown-item.disabled{color:#0b0c0e}div.timely .dropdown-menu{background-color:#0b0c0e;box-shadow:0 2px 2px 2px #31343b}div.timely input.form-control:focus{color:#c7d0d9;outline:0;box-shadow:0 0 0 2px #141619,0 0 0 4px #1f60c4;outline-offset:2px;transition:all .2s cubic-bezier(.19,1,.22,1) 0s}div.timely mark.rbt-highlight-text{background:linear-gradient(90deg,#56585c,#4c5057);color:#ff0}
|
||||
@@ -0,0 +1 @@
|
||||
div.timely input.form-control{color:#464c54;background-color:#fff}div.timely .dropdown-item,div.timely .dropdown-item-text{color:#464c54}.dropdown-item:active,.dropdown-item:focus,div.timely .dropdown-item.active,div.timely .dropdown-item:hover{color:#464c54;background-color:#e3e6e9}.dropdown-item:disabled,div.timely .dropdown-item.disabled{color:#abadaf}div.timely .dropdown-header{color:#464c54}div.timely .dropdown-menu{box-shadow:0 4px 2px 0 #cbcbcb}div.timely input.form-control:focus{color:#464c54;outline:0;box-shadow:0 0 0 2px #fff,0 0 0 4px #5794f2;outline-offset:2px;transition:all .2s cubic-bezier(.19,1,.22,1) 0s}div.timely mark.rbt-highlight-text{background:linear-gradient(90deg,#bfc0c1,#abadaf);color:#ff0}
|
||||
@@ -0,0 +1,11 @@
|
||||
module github.com/NationalSecurityAgency/timely-datasource
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.111.0
|
||||
github.com/hashicorp/go-hclog v0.16.1
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/prometheus/common v0.29.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,780 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20210223225224-5bea62493d91 h1:rbe942bXzd2vnds4y9fYQL8X4yFltXoZsKW7KtG+TFM=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20210223225224-5bea62493d91/go.mod h1:c9sxoIT3YgLxH4UhLOCKaBlEojuMhVYpk4Ntv3opUTQ=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1 h1:jAbXjIeW2ZSW2AwFxlGTDoc2CjI2XujLkV3ArsZFCvc=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/flatbuffers v1.11.0 h1:O7CEyB8Cb3/DmtxODGtLHcEvpr81Jm5qLg/hsHnxA2A=
|
||||
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.111.0 h1:7eqLgAdDYeELVokRCeDEobYQJy5/E5C43tZkb/xH66Q=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.111.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o=
|
||||
github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-plugin v1.2.2 h1:mgDpq0PkoK5gck2w4ivaMpWRHv/matdOR4xmeScmf/w=
|
||||
github.com/hashicorp/go-plugin v1.2.2/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
|
||||
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=
|
||||
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
|
||||
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.23.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE=
|
||||
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f h1:Yv4xsIx7HZOoyUGSJ2ksDyWE2qIBXROsZKt2ny3hCGM=
|
||||
google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.37.1 h1:ARnQJNWxGyYJpdf/JXscNlQr/uv607ZPU9Z7ogHi+iI=
|
||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
@@ -0,0 +1,8 @@
|
||||
// This file is needed because it is used by vscode and other tools that
|
||||
// call `jest` directly. However, unless you are doing anything special
|
||||
// do not edit this file
|
||||
|
||||
const standard = require('@grafana/toolkit/src/config/jest.plugin.config');
|
||||
|
||||
// This process will use the same config that `yarn test` is using
|
||||
module.exports = standard.jestConfig();
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "timely-datasource",
|
||||
"version": "2.1.6-SNAPSHOT",
|
||||
"description": "Timely",
|
||||
"backend": true,
|
||||
"alerting": true,
|
||||
"executable": "timely_datasource_backend",
|
||||
"scripts": {
|
||||
"build": "grafana-toolkit plugin:build",
|
||||
"test": "grafana-toolkit plugin:test",
|
||||
"dev": "grafana-toolkit plugin:dev",
|
||||
"watch": "grafana-toolkit plugin:dev --watch"
|
||||
},
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@grafana/toolkit": "^8.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12 <17"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grafana/data": "^8.4.5",
|
||||
"@grafana/runtime": "^8.4.5",
|
||||
"@grafana/slate-react": "0.22.10-grafana",
|
||||
"@grafana/ui": "^8.4.5",
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@types/classnames": "2.3.1",
|
||||
"@types/lodash": "4.14.176",
|
||||
"@types/react-bootstrap-typeahead": "5.1.8",
|
||||
"@types/slate-plain-serializer": "0.7.1",
|
||||
"@types/slate-react": "0.50.1",
|
||||
"classnames": "2.3.1",
|
||||
"dayjs": "1.10.7",
|
||||
"react-bootstrap-typeahead": "5.1.1",
|
||||
"rxjs": "7.3.0",
|
||||
"slate-plain-serializer": "0.7.13",
|
||||
"tmpl": "1.0.5",
|
||||
"tslib": "^2.3.1",
|
||||
"ws": "5.2.3"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package backend
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -6,32 +6,23 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"net/url"
|
||||
)
|
||||
"github.com/hashicorp/go-hclog"
|
||||
|
||||
// Make sure Datasource implements required interfaces. This is important to do
|
||||
// since otherwise we will only get a not implemented error response from plugin in
|
||||
// runtime. In this example datasource instance implements backend.QueryDataHandler,
|
||||
// backend.CheckHealthHandler interfaces. Plugin should not implement all these
|
||||
// interfaces - only those which are required for a particular task.
|
||||
var (
|
||||
_ backend.QueryDataHandler = (*TimelyDatasource)(nil)
|
||||
_ backend.CheckHealthHandler = (*TimelyDatasource)(nil)
|
||||
_ instancemgmt.InstanceDisposer = (*TimelyDatasource)(nil)
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/httpProperties"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -52,17 +43,52 @@ type TimelyDatasource struct {
|
||||
ClientCertificatePath string
|
||||
ClientKeyPath string
|
||||
CertificateAuthorityPath string
|
||||
Mutex sync.Mutex
|
||||
Mutex *sync.Mutex
|
||||
}
|
||||
|
||||
//type TimelyDatasourceInstanceSettings struct {
|
||||
type TimelyDatasourceInstanceSettings struct {
|
||||
}
|
||||
|
||||
func newDataSourceInstance(setting backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
return &TimelyDatasourceInstanceSettings{}, nil
|
||||
}
|
||||
|
||||
func (s *TimelyDatasourceInstanceSettings) Dispose() {
|
||||
// Called before creating a new instance to allow plugin authors
|
||||
// to cleanup.
|
||||
}
|
||||
|
||||
func getServeOpts() datasource.ServeOpts {
|
||||
// creates a instance manager for your plugin. The function passed
|
||||
// into `NewInstanceManger` is called when the instance is created
|
||||
// for the first time or when a datasource configuration changed.
|
||||
im := datasource.NewInstanceManager(newDataSourceInstance)
|
||||
ds := &TimelyDatasource{
|
||||
im: im,
|
||||
CertPool: nil,
|
||||
Certificate: nil,
|
||||
ClientCertificatePath: "",
|
||||
ClientKeyPath: "",
|
||||
CertificateAuthorityPath: "",
|
||||
Mutex: &sync.Mutex{},
|
||||
}
|
||||
|
||||
return datasource.ServeOpts{
|
||||
CheckHealthHandler: ds,
|
||||
CallResourceHandler: ds,
|
||||
QueryDataHandler: ds,
|
||||
}
|
||||
}
|
||||
|
||||
//func (ds *TimelyDatasource) getSettings(pluginContext backend.PluginContext) (*TimelyDatasourceInstanceSettings, error) {
|
||||
// iface, err := ds.im.Get(pluginContext)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// return iface.(*TimelyDatasourceInstanceSettings), nil
|
||||
//}
|
||||
|
||||
// NewDatasource creates a new datasource instance.
|
||||
func NewDatasource(_ context.Context, _ backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
return &TimelyDatasource{}, nil
|
||||
}
|
||||
|
||||
// CheckHealth handles health checks sent from Grafana to the plugin.
|
||||
// The main use case for these health checks is the test button on the
|
||||
// datasource configuration page which allows users to verify that
|
||||
@@ -86,7 +112,7 @@ func (td *TimelyDatasource) CallResource(ctx context.Context, request *backend.C
|
||||
}
|
||||
var response backend.CallResourceResponse
|
||||
pluginContext := request.PluginContext
|
||||
var httpResponse *http.Response
|
||||
var httpResponse *httpProperties.Response
|
||||
var timelyDataSourceOptions TimelyDataSourceOptions
|
||||
err := json.Unmarshal(pluginContext.DataSourceInstanceSettings.JSONData, &timelyDataSourceOptions)
|
||||
if err != nil {
|
||||
@@ -99,11 +125,11 @@ func (td *TimelyDatasource) CallResource(ctx context.Context, request *backend.C
|
||||
logger.Error("Error getting httpClient", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.HasPrefix(request.Path, "/api/aggregators") ||
|
||||
strings.HasPrefix(request.Path, "/api/suggest") ||
|
||||
strings.HasPrefix(request.Path, "/api/search/lookup") {
|
||||
|
||||
var timelyUrl *url.URL
|
||||
if request.Method == "GET" {
|
||||
var x = strings.Index(request.URL, request.Path)
|
||||
finalParams := ""
|
||||
@@ -114,36 +140,26 @@ func (td *TimelyDatasource) CallResource(ctx context.Context, request *backend.C
|
||||
finalParams = params
|
||||
}
|
||||
}
|
||||
timelyUrl, err = url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + strconv.Itoa(int(timelyDataSourceOptions.HttpsPort)) + request.Path + finalParams)
|
||||
url, err := url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + timelyDataSourceOptions.HttpsPort + request.Path + finalParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
httpResponse, err = httpClient.Get(timelyUrl.String())
|
||||
httpResponse, err = httpClient.Get(url.String())
|
||||
} else if request.Method == "POST" {
|
||||
timelyUrl, err = url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + strconv.Itoa(int(timelyDataSourceOptions.HttpsPort)) + request.Path)
|
||||
url, err := url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + timelyDataSourceOptions.HttpsPort + request.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
httpResponse, err = httpClient.Post(timelyUrl.String(), "application/json", bytes.NewReader(request.Body))
|
||||
httpResponse, err = httpClient.Post(url.String(), "application/json", bytes.NewReader(request.Body))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Error("Error fetching resource", "url", timelyUrl.String(), "error", err)
|
||||
logger.Error("Error calling for resource", "Path", request.Path, "error", err)
|
||||
return err
|
||||
}
|
||||
if httpResponse == nil {
|
||||
logger.Error("Error fetching resource, httpResponse null", "url", timelyUrl.String())
|
||||
return fmt.Errorf("Error fetching resource url:%s, httpResponse null", timelyUrl.String())
|
||||
}
|
||||
|
||||
if httpResponse.StatusCode != 200 {
|
||||
logger.Error("Error fetching resource", "url", timelyUrl.String(), "responseCode", httpResponse.StatusCode)
|
||||
return fmt.Errorf("Error fetching resource url:%s responseCode:%d", timelyUrl.String(), httpResponse.StatusCode)
|
||||
}
|
||||
|
||||
bytes, err := io.ReadAll(httpResponse.Body)
|
||||
bytes, err := ioutil.ReadAll(httpResponse.Body)
|
||||
if err != nil {
|
||||
logger.Error("Error reading resource", "url", timelyUrl, "error", err)
|
||||
logger.Error("Error reading resource", "Path", request.Path, "error", err)
|
||||
return err
|
||||
}
|
||||
response.Status = 200
|
||||
@@ -161,7 +177,6 @@ func (td *TimelyDatasource) CallResource(ctx context.Context, request *backend.C
|
||||
// The QueryDataResponse contains a map of RefID to the response for each query, and each response
|
||||
// contains Frames ([]*Frame).
|
||||
func (td *TimelyDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
logger.Info("QueryData called with:", "Request", req)
|
||||
// create response struct
|
||||
response := backend.NewQueryDataResponse()
|
||||
|
||||
@@ -210,7 +225,6 @@ func (td *TimelyDatasource) Query(queryDataRequest *backend.QueryDataRequest, da
|
||||
Tags: timelyQueryServer.Tags,
|
||||
Filters: timelyQueryServer.Filters,
|
||||
ShouldComputeRate: timelyQueryServer.ShouldComputeRate,
|
||||
RateInterval: timelyQueryServer.RateInterval,
|
||||
IsCounter: timelyQueryServer.IsCounter,
|
||||
CounterMax: timelyQueryServer.CounterMax,
|
||||
CounterResetValue: timelyQueryServer.CounterResetValue,
|
||||
@@ -229,6 +243,11 @@ func (td *TimelyDatasource) Query(queryDataRequest *backend.QueryDataRequest, da
|
||||
return nil, err
|
||||
}
|
||||
|
||||
timelyQuery := td.convertTimelyQuery(&timelyQueryForm)
|
||||
timelyRequest.Queries = append(timelyRequest.Queries, *timelyQuery)
|
||||
|
||||
logger.Debug("Query", "timelyRequest", timelyRequest)
|
||||
|
||||
var timelyDatasourceOptions TimelyDataSourceOptions
|
||||
|
||||
err = json.Unmarshal(queryDataRequest.PluginContext.DataSourceInstanceSettings.JSONData, &timelyDatasourceOptions)
|
||||
@@ -237,12 +256,7 @@ func (td *TimelyDatasource) Query(queryDataRequest *backend.QueryDataRequest, da
|
||||
return nil, err
|
||||
}
|
||||
|
||||
timelyQuery := td.convertTimelyQuery(&timelyQueryForm, timelyDatasourceOptions)
|
||||
timelyRequest.Queries = append(timelyRequest.Queries, *timelyQuery)
|
||||
|
||||
logger.Debug("Query", "timelyRequest", timelyRequest)
|
||||
|
||||
var httpRequest *http.Request
|
||||
var httpRequest *httpProperties.Request
|
||||
httpRequest, err = td.createRequest(timelyDatasourceOptions, timelyRequest)
|
||||
if err != nil {
|
||||
logger.Error("Error creating httpRequest", "error", err)
|
||||
@@ -269,15 +283,8 @@ func (td *TimelyDatasource) Query(queryDataRequest *backend.QueryDataRequest, da
|
||||
return td.parseResponse(res)
|
||||
}
|
||||
|
||||
// Dispose here tells plugin SDK that plugin wants to clean up resources when a new instance
|
||||
// created. As soon as datasource settings change detected by SDK old datasource instance will
|
||||
// be disposed and a new one will be created using NewSampleDatasource factory function.
|
||||
func (d *TimelyDatasource) Dispose() {
|
||||
// Clean up datasource instance resources.
|
||||
}
|
||||
|
||||
func (td *TimelyDatasource) createRequest(tdo TimelyDataSourceOptions, timelyRequest TimelyRequest) (*http.Request, error) {
|
||||
u, err := url.Parse("https://" + tdo.TimelyHost + ":" + strconv.Itoa(int(tdo.HttpsPort)) + "/api/query")
|
||||
func (td *TimelyDatasource) createRequest(tdo TimelyDataSourceOptions, timelyRequest TimelyRequest) (*httpProperties.Request, error) {
|
||||
u, err := url.Parse("https://" + tdo.TimelyHost + ":" + tdo.HttpsPort + "/api/query")
|
||||
if err != nil {
|
||||
logger.Error("Failed creating query url", "error", err)
|
||||
return nil, fmt.Errorf("Failed creating query url. error: %v", err)
|
||||
@@ -287,7 +294,7 @@ func (td *TimelyDatasource) createRequest(tdo TimelyDataSourceOptions, timelyReq
|
||||
logger.Error("Failed marshaling timelyRequest", "error", err)
|
||||
return nil, fmt.Errorf("Failed to create request. error: %v", err)
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodPost, u.String(), bytes.NewReader(postData))
|
||||
req, err := httpProperties.NewRequest(httpProperties.MethodPost, u.String(), bytes.NewReader(postData))
|
||||
if err != nil {
|
||||
logger.Error("Failed to create request", "error", err)
|
||||
return nil, fmt.Errorf("Failed to create request. error: %v", err)
|
||||
@@ -303,9 +310,9 @@ func (td *TimelyDatasource) createRequest(tdo TimelyDataSourceOptions, timelyReq
|
||||
return req, err
|
||||
}
|
||||
|
||||
func (td *TimelyDatasource) parseResponse(res *http.Response) (*backend.DataResponse, error) {
|
||||
func (td *TimelyDatasource) parseResponse(res *httpProperties.Response) (*backend.DataResponse, error) {
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
defer res.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -362,7 +369,7 @@ func (td *TimelyDatasource) parseResponse(res *http.Response) (*backend.DataResp
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func (td *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm, datasourceOptions TimelyDataSourceOptions) *TimelyQuery {
|
||||
func (td *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm) *TimelyQuery {
|
||||
|
||||
if timelyQueryForm == nil {
|
||||
return nil
|
||||
@@ -378,13 +385,6 @@ func (td *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm,
|
||||
Tsuids: timelyQueryForm.Tsuids,
|
||||
}
|
||||
|
||||
for i := 0; i < len(timelyQueryForm.DatasourceTags); i++ {
|
||||
tagKey := timelyQueryForm.DatasourceTags[i]
|
||||
if _, ok := datasourceOptions.DatasourceTags[tagKey]; ok {
|
||||
timelyQuery.Tags[tagKey] = datasourceOptions.DatasourceTags[tagKey]
|
||||
}
|
||||
}
|
||||
|
||||
// future work - replace scopedVariables in metric, tags, filters, aggregator
|
||||
|
||||
timelyQuery.Aggregator = "avg"
|
||||
@@ -395,7 +395,6 @@ func (td *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm,
|
||||
|
||||
if timelyQueryForm.ShouldComputeRate {
|
||||
timelyQuery.Rate = true
|
||||
timelyQuery.RateOptions.Interval = timelyQueryForm.RateInterval
|
||||
timelyQuery.RateOptions.Counter = timelyQueryForm.IsCounter
|
||||
}
|
||||
|
||||
@@ -435,17 +434,17 @@ func (td *TimelyDatasource) clientSslSettingsChanged(settings TimelyDataSourceOp
|
||||
certificateAuthorityPath != td.CertificateAuthorityPath
|
||||
}
|
||||
|
||||
func (td *TimelyDatasource) GetHttpClient(settings TimelyDataSourceOptions, useClientCertIfAvailable bool) (*http.Client, error) {
|
||||
func (td *TimelyDatasource) GetHttpClient(settings TimelyDataSourceOptions, useClientCertIfAvailable bool) (*httpProperties.Client, error) {
|
||||
|
||||
// handle call back
|
||||
logger.Debug("Getting client", "allowInsecureSsl", strconv.FormatBool(settings.AllowInsecureSsl))
|
||||
tr := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
tr := &httpProperties.Transport{
|
||||
Proxy: httpProperties.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: settings.AllowInsecureSsl,
|
||||
},
|
||||
}
|
||||
httpClient := &http.Client{
|
||||
httpClient := &httpProperties.Client{
|
||||
Transport: tr,
|
||||
}
|
||||
|
||||
@@ -512,3 +511,16 @@ func (td *TimelyDatasource) GetHttpClient(settings TimelyDataSourceOptions, useC
|
||||
td.Mutex.Unlock()
|
||||
return httpClient, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Start listening to requests send from Grafana. This call is blocking so
|
||||
// it wont finish until Grafana shutsdown the process or the plugin choose
|
||||
// to exit close down by itself
|
||||
err := datasource.Serve(getServeOpts())
|
||||
|
||||
// Log any error if we could not start the plugin.
|
||||
if err != nil {
|
||||
logger.Error("Plugin failed to start", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
type TimelyQueryForm struct {
|
||||
Metric string `json:"metric"`
|
||||
Alias string `json:"alias"`
|
||||
Aggregator string `json:"aggregator"`
|
||||
DisableDownsampling bool `json:"disableDownsampling"`
|
||||
DownsampleAggregator string `json:"downsampleAggregator"`
|
||||
DownsampleFillPolicy string `json:"downsampleFillPolicy"`
|
||||
DownsampleInterval string `json:"downsampleInterval"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
Filters []Filter `json:"filters"`
|
||||
ShouldComputeRate bool `json:"shouldComputeRate"`
|
||||
IsCounter bool `json:"isCounter"`
|
||||
CounterMax string `json:"counterMax"`
|
||||
CounterResetValue string `json:"counterResetValue"`
|
||||
Tsuids []string `json:"tsuids"`
|
||||
QueryType string `json:"queryType"`
|
||||
RefId string `json:"refId"`
|
||||
Datasource string `json:"datasource"`
|
||||
DatasourceId int64 `json:"datasourceId"`
|
||||
IntervalMs int64 `json:"intervalMs"`
|
||||
MaxDataPoints int64 `json:"maxDataPoints"`
|
||||
OrgId int64 `json:"ordId"`
|
||||
}
|
||||
|
||||
type TimelyQueryServer struct {
|
||||
Metric string `json:"metric"`
|
||||
Aggregator string `json:"aggregator"`
|
||||
DisableDownsampling bool `json:"disableDownsampling"`
|
||||
DownsampleAggregator string `json:"downsampleAggregator"`
|
||||
DownsampleFillPolicy string `json:"downsampleFillPolicy"`
|
||||
DownsampleInterval string `json:"downsampleInterval"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
Filters []Filter `json:"filters"`
|
||||
ShouldComputeRate bool `json:"shouldComputeRate"`
|
||||
IsCounter bool `json:"isCounter"`
|
||||
CounterMax string `json:"counterMax"`
|
||||
CounterResetValue string `json:"counterResetValue"`
|
||||
Tsuids []string `json:"tsuids"`
|
||||
QueryType string `json:"queryType"`
|
||||
RefId string `json:"refId"`
|
||||
}
|
||||
|
||||
type Filter struct {
|
||||
Type string `json:"type"`
|
||||
TagK string `json:"tagk"`
|
||||
Filter string `json:"filter"`
|
||||
GroupBy bool `json:"groupBy"`
|
||||
}
|
||||
|
||||
type RateOptions struct {
|
||||
Counter bool `json:"counter"`
|
||||
CounterMax int32 `json:"counterMax"`
|
||||
ResetValue int32 `json:"resetValue"`
|
||||
}
|
||||
|
||||
type TimelyQuery struct {
|
||||
Metric string `json:"metric"`
|
||||
Aggregator string `json:"aggregator"`
|
||||
Rate bool `json:"rate"`
|
||||
RateOptions RateOptions `json:"rateOptions"`
|
||||
Downsample string `json:"downsample"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
Filters []Filter `json:"filters"`
|
||||
Tsuids []string `json:"tsuids"`
|
||||
}
|
||||
|
||||
type TimelyRequest struct {
|
||||
MsResolution bool `json:"msResolution"`
|
||||
GlobalAnnotations bool `json:"globalAnnotations"`
|
||||
Start int64 `json:"start"`
|
||||
End int64 `json:"end"`
|
||||
Queries []TimelyQuery `json:"queries"`
|
||||
}
|
||||
|
||||
type TimelyResponse struct {
|
||||
Metric string `json:"metric"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
AggregatedTags []string `json:"aggregatedTags"`
|
||||
DataPoints map[int64]float64 `json:"dps"`
|
||||
}
|
||||
|
||||
type TimelyDataSourceOptions struct {
|
||||
TimelyHost string `json:"timelyHost"`
|
||||
HttpsPort string `json:"httpsPort"`
|
||||
OauthPassThru bool `json:"oauthPassThru"`
|
||||
UseClientCertWhenOAuthMissing bool `json:"useClientCertWhenOAuthMissing"`
|
||||
ClientCertificatePath string `json:"clientCertificatePath"`
|
||||
ClientKeyPath string `json:"clientKeyPath"`
|
||||
CertificateAuthorityPath string `json:"certificateAuthorityPath"`
|
||||
AllowInsecureSsl bool `json:"allowInsecureSsl"`
|
||||
}
|
||||
|
||||
type TimelyErrorResponse struct {
|
||||
ResponseCode int32 `json:responseCode`
|
||||
Message string `json:message`
|
||||
DetailMessage string `json:detailMessage`
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
||||
import { LegacyForms } from '@grafana/ui';
|
||||
import { TimelyDataSourceOptions } from './types';
|
||||
import * as React from 'react';
|
||||
|
||||
const { FormField, Switch } = LegacyForms;
|
||||
|
||||
interface Props extends DataSourcePluginOptionsEditorProps<TimelyDataSourceOptions> {}
|
||||
|
||||
interface State {}
|
||||
|
||||
export class ConfigEditor extends React.PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
onTimelyHostChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
timelyHost: event.target.value,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onHttpsPortChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
httpsPort: event.target.value,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onUseOAuthChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
oauthPassThru: event.currentTarget.checked,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onUseClientCertWhenOAuthMissingChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
useClientCertWhenOAuthMissing: event.currentTarget.checked,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onClientCertificatePathChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
clientCertificatePath: event.target.value,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onClientKeyPathChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
clientKeyPath: event.target.value,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onCertificateAuthorityPathChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
certificateAuthorityPath: event.target.value,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
onAllowInsecureSslChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const { onOptionsChange, options } = this.props;
|
||||
const jsonData = {
|
||||
...options.jsonData,
|
||||
allowInsecureSsl: event.currentTarget.checked,
|
||||
};
|
||||
onOptionsChange({ ...options, jsonData });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { options } = this.props;
|
||||
const { jsonData } = options;
|
||||
|
||||
return (
|
||||
<div className="gf-form-group">
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label={'Hostname or IP'}
|
||||
labelWidth={10}
|
||||
inputWidth={20}
|
||||
disabled={false}
|
||||
onChange={this.onTimelyHostChange}
|
||||
tooltip={'Hostname or IP of Timely Server'}
|
||||
value={jsonData.timelyHost || ''}
|
||||
placeholder={'localhost'}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label={'Https port'}
|
||||
labelWidth={10}
|
||||
inputWidth={20}
|
||||
onChange={this.onHttpsPortChange}
|
||||
value={jsonData.httpsPort || ''}
|
||||
placeholder={'4243'}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<Switch
|
||||
label={'Use OAuth token'}
|
||||
labelClass="width-10"
|
||||
tooltipPlacement={'top'}
|
||||
tooltip={'Send OAuth token if available'}
|
||||
checked={jsonData.oauthPassThru || false}
|
||||
onChange={this.onUseOAuthChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<Switch
|
||||
label={'Client cert for users'}
|
||||
labelClass="width-10"
|
||||
tooltipPlacement={'top'}
|
||||
tooltip={'If user is missing OAuth token, use client cert instead'}
|
||||
checked={jsonData.useClientCertWhenOAuthMissing || false}
|
||||
onChange={this.onUseClientCertWhenOAuthMissingChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label={'Client cert path'}
|
||||
labelWidth={10}
|
||||
inputWidth={30}
|
||||
disabled={false}
|
||||
onChange={this.onClientCertificatePathChange}
|
||||
tooltip={'Full path to client certificate'}
|
||||
value={jsonData.clientCertificatePath || ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label={'Client key path'}
|
||||
labelWidth={10}
|
||||
inputWidth={30}
|
||||
disabled={false}
|
||||
onChange={this.onClientKeyPathChange}
|
||||
tooltip={'Full path to client key'}
|
||||
value={jsonData.clientKeyPath || ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label={'CA path'}
|
||||
labelWidth={10}
|
||||
inputWidth={30}
|
||||
disabled={false}
|
||||
onChange={this.onCertificateAuthorityPathChange}
|
||||
tooltip={'Full path to certificate authority'}
|
||||
value={jsonData.certificateAuthorityPath || ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<Switch
|
||||
label={'Allow insecure ssl'}
|
||||
labelClass="width-10"
|
||||
tooltipPlacement={'top'}
|
||||
tooltip={'Allow ssl connection with unverified or self-signed certificates'}
|
||||
checked={jsonData.allowInsecureSsl || false}
|
||||
onChange={this.onAllowInsecureSslChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
import _ from 'lodash';
|
||||
import { QueryEditorProps } from '@grafana/data';
|
||||
import { Input, Select, LegacyForms } from '@grafana/ui';
|
||||
import React, { Component } from 'react';
|
||||
import { TimelyDataSource } from './TimelyDataSource';
|
||||
import { TimelyDataSourceOptions, TimelyErrors, TimelyQueryForm } from './types';
|
||||
import { SelectableValue } from '@grafana/data/types/select';
|
||||
import dayjs from 'dayjs';
|
||||
import { TagEditor } from './TagEditor';
|
||||
import { AsyncTypeahead, TypeaheadModel } from 'react-bootstrap-typeahead';
|
||||
|
||||
const { Switch } = LegacyForms;
|
||||
|
||||
export type Props = QueryEditorProps<TimelyDataSource, TimelyQueryForm, TimelyDataSourceOptions>;
|
||||
|
||||
interface State {
|
||||
aggregatorTypes: string[];
|
||||
errors: TimelyErrors;
|
||||
query: TimelyQueryForm;
|
||||
queryOptionsLoading: boolean;
|
||||
queryOptions: TypeaheadModel[];
|
||||
}
|
||||
|
||||
export class QueryEditor extends Component<Props, State> {
|
||||
metricArray: string[] = [];
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
const defaultQuery: Partial<TimelyQueryForm> = {
|
||||
metric: '',
|
||||
alias: '',
|
||||
aggregator: 'none',
|
||||
refId: 'A',
|
||||
queryType: 'metricQuery',
|
||||
disableDownsampling: false,
|
||||
downsampleFillPolicy: 'none',
|
||||
downsampleInterval: '1m',
|
||||
downsampleAggregator: 'avg',
|
||||
shouldComputeRate: false,
|
||||
isCounter: false,
|
||||
tags: {},
|
||||
};
|
||||
this.state = {
|
||||
aggregatorTypes: ['none', 'avg', 'dev', 'max', 'min', 'sum', 'count'],
|
||||
errors: {
|
||||
downsample: undefined,
|
||||
},
|
||||
query: Object.assign({}, defaultQuery, props.query),
|
||||
queryOptionsLoading: false,
|
||||
queryOptions: [],
|
||||
};
|
||||
this.getAggregators();
|
||||
this.getMetrics();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
onMetricTextChange = (value: string) => {
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { metric: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onAliasChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { alias: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onAggregatorChange = (option: SelectableValue<string>) => {
|
||||
if (option.value) {
|
||||
const value = option.value;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { aggregator: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onDownsampleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { downsampleInterval: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onDownsampleAggregatorChange = (option: SelectableValue<string>) => {
|
||||
if (option.value) {
|
||||
const value = option.value;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { downsampleAggregator: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onDisableDownsamplingChange = (option: React.FormEvent<HTMLInputElement>) => {
|
||||
const checked = option.currentTarget.checked;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { disableDownsampling: checked });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onRateChange = (option: React.FormEvent<HTMLInputElement>) => {
|
||||
const checked = option.currentTarget.checked;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { shouldComputeRate: checked });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onCounterChange = (option: React.FormEvent<HTMLInputElement>) => {
|
||||
const checked = option.currentTarget.checked;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { isCounter: checked });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onCounterMaxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { counterMax: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
onCounterResetValueChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { counterResetValue: value });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
updateQuery = (query: TimelyQueryForm) => {
|
||||
this.props.onChange(query);
|
||||
this.props.onRunQuery();
|
||||
};
|
||||
|
||||
updateQueryFromState = () => {
|
||||
const query = this.state.query;
|
||||
this.props.onChange(query);
|
||||
this.props.onRunQuery();
|
||||
};
|
||||
|
||||
validate = () => {
|
||||
const { disableDownsampling, downsampleInterval } = this.state.query;
|
||||
|
||||
if (!disableDownsampling) {
|
||||
try {
|
||||
let valid = false;
|
||||
if (downsampleInterval) {
|
||||
valid = dayjs('', '').isValid();
|
||||
}
|
||||
if (!valid) {
|
||||
this.setState((state, props) => {
|
||||
this.setState(
|
||||
{
|
||||
errors: {
|
||||
downsample: "You must supply a downsample interval (e.g. '1m' or '1h').",
|
||||
},
|
||||
},
|
||||
this.updateQueryFromState
|
||||
);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.setState(
|
||||
{
|
||||
errors: {
|
||||
downsample: "You must supply a downsample interval (e.g. '1m' or '1h').",
|
||||
},
|
||||
},
|
||||
this.updateQueryFromState
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getAggregators = () => {
|
||||
this.props.datasource.getResource('/api/aggregators').then((result: any) => {
|
||||
if (result && _.isArray(result)) {
|
||||
this.setState({ aggregatorTypes: result }, this.updateQueryFromState);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getMetrics = () => {
|
||||
this.props.datasource.getResource('/api/suggest', { type: 'metrics', max: '-1' }).then((result: any) => {
|
||||
if (result && _.isArray(result)) {
|
||||
const metrics: string[] = result;
|
||||
this.metricArray = metrics
|
||||
.map((value) => {
|
||||
return value;
|
||||
})
|
||||
.concat();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
updateTags = (tags: { [key: string]: string }) => {
|
||||
this.setState((state, props) => {
|
||||
var query = Object.assign(state.query, { tags: tags });
|
||||
this.updateQuery(query);
|
||||
return { query: query };
|
||||
});
|
||||
};
|
||||
|
||||
handleSearch = (query: string) => {
|
||||
const results = this.metricArray
|
||||
.filter((metric) => query === '' || metric.toLowerCase().includes(query.toLowerCase()))
|
||||
.map((value) => {
|
||||
return value;
|
||||
});
|
||||
this.setState({ queryOptions: results });
|
||||
};
|
||||
|
||||
getInputValue = (id: string): string | null => {
|
||||
var fullId = 'div#' + id + ' div div input.rbt-input-main';
|
||||
var inputElement = document.querySelector(fullId);
|
||||
if (inputElement !== null) {
|
||||
return (inputElement as HTMLInputElement).value;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
render() {
|
||||
var queryEditorId = Math.random().toString(36).substr(2, 9);
|
||||
const { metric, aggregator, alias } = this.state.query;
|
||||
const { downsampleInterval, downsampleAggregator, disableDownsampling } = this.state.query;
|
||||
const { tags } = this.state.query;
|
||||
const { shouldComputeRate, isCounter, counterResetValue, counterMax } = this.state.query;
|
||||
const aggregatorOptions: Array<{}> = _.map(this.state.aggregatorTypes, (value: string) => ({
|
||||
label: value,
|
||||
value: value,
|
||||
}));
|
||||
const { queryOptionsLoading, queryOptions } = this.state;
|
||||
|
||||
var multiplier = 7.5;
|
||||
var metricWidth = 300;
|
||||
if (metric !== undefined && metric!.length * multiplier > metricWidth) {
|
||||
metricWidth = Math.ceil(metric!.length * multiplier);
|
||||
}
|
||||
var aliasWidth = 175;
|
||||
if (alias !== undefined && alias!.length * multiplier > aliasWidth) {
|
||||
aliasWidth = Math.ceil(alias!.length * multiplier);
|
||||
}
|
||||
|
||||
var dynamicStyle =
|
||||
'div.timely-query input.form-control, div#timelyQuery-' +
|
||||
queryEditorId +
|
||||
' { ' +
|
||||
'width:' +
|
||||
metricWidth +
|
||||
'px!important ' +
|
||||
'}';
|
||||
|
||||
dynamicStyle += '#timelyAlias-' + queryEditorId + ' { ' + 'width:' + aliasWidth + 'px!important ' + '}';
|
||||
|
||||
return (
|
||||
<div className="timely-edior-row">
|
||||
<div className="gf-form-inline">
|
||||
<style>{dynamicStyle}</style>
|
||||
<div className="gf-form timely">
|
||||
<label className="gf-form-label width-10">Metric</label>
|
||||
<div id={'timelyQuery-' + queryEditorId} className="timely timely-query">
|
||||
<AsyncTypeahead
|
||||
id={'timelyQuery-' + queryEditorId + '-Typeahead'}
|
||||
inputProps={{ spellCheck: false }}
|
||||
defaultInputValue={metric}
|
||||
isLoading={queryOptionsLoading}
|
||||
onSearch={(query) => {
|
||||
this.setState({ queryOptionsLoading: true });
|
||||
this.handleSearch(query);
|
||||
this.setState({ queryOptionsLoading: false });
|
||||
}}
|
||||
onChange={(e) => {
|
||||
var inputValue = this.getInputValue('timelyQuery-' + queryEditorId);
|
||||
if (inputValue !== null) {
|
||||
this.onMetricTextChange(inputValue);
|
||||
}
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
var inputValue = this.getInputValue('timelyQuery-' + queryEditorId);
|
||||
if (inputValue !== null) {
|
||||
this.onMetricTextChange(inputValue);
|
||||
}
|
||||
}}
|
||||
onFocus={(e) => {
|
||||
var inputValue = this.getInputValue('timelyQuery-' + queryEditorId);
|
||||
if (queryOptions.length === 0 || inputValue === null || inputValue.length === 0) {
|
||||
this.handleSearch('');
|
||||
}
|
||||
}}
|
||||
options={queryOptions}
|
||||
selectHintOnEnter={true}
|
||||
align={'left'}
|
||||
allowNew={true}
|
||||
newSelectionPrefix={''}
|
||||
paginate={true}
|
||||
paginationText={'more'}
|
||||
minLength={0}
|
||||
maxResults={100}
|
||||
caseSensitive={false}
|
||||
placeholder={'metric'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gf-form timely">
|
||||
<label className="gf-form-label width-5">Alias</label>
|
||||
<Input
|
||||
id={'timelyAlias-' + queryEditorId}
|
||||
className="min-width-10 flex-grow-1"
|
||||
spellCheck={false}
|
||||
value={alias || ''}
|
||||
onChange={this.onAliasChange}
|
||||
placeholder={'series alias'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<TagEditor tags={tags} parent={this} />
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form timely">
|
||||
<label className="gf-form-label width-10">Downsample</label>
|
||||
<Input
|
||||
className={'min-width-5 flex-grow-1'}
|
||||
spellCheck={false}
|
||||
value={downsampleInterval || ''}
|
||||
onChange={this.onDownsampleChange}
|
||||
placeholder={'interval'}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form timely">
|
||||
<label className="gf-form-label width-10">Downsample Aggregator</label>
|
||||
<Select
|
||||
className={'min-width-5 flex-grow-1'}
|
||||
isSearchable={false}
|
||||
options={aggregatorOptions}
|
||||
value={downsampleAggregator}
|
||||
placeholder={'aggregator'}
|
||||
onChange={this.onDownsampleAggregatorChange}
|
||||
menuPlacement={'bottom'}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form timely">
|
||||
<Switch
|
||||
label={'Disable downsampling'}
|
||||
labelClass="width-10"
|
||||
checked={disableDownsampling || false}
|
||||
onChange={this.onDisableDownsamplingChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form timely">
|
||||
<label className="gf-form-label width-10">All Results Aggregator</label>
|
||||
<Select
|
||||
className={'min-width-5 flex-grow-1'}
|
||||
isSearchable={false}
|
||||
options={aggregatorOptions}
|
||||
value={aggregator}
|
||||
placeholder={'aggregator'}
|
||||
onChange={this.onAggregatorChange}
|
||||
menuPlacement={'bottom'}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form timely">
|
||||
<Switch
|
||||
label={'Rate'}
|
||||
labelClass="width-5"
|
||||
checked={shouldComputeRate || false}
|
||||
onChange={this.onRateChange}
|
||||
/>
|
||||
<div hidden={!shouldComputeRate}>
|
||||
<Switch
|
||||
label={'Counter'}
|
||||
labelClass="width-10"
|
||||
checked={isCounter || false}
|
||||
onChange={this.onCounterChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form timely" hidden={!shouldComputeRate || !isCounter}>
|
||||
<label className="gf-form-label width-10">Max Value</label>
|
||||
<Input
|
||||
className={'min-width-6 flex-grow-1'}
|
||||
spellCheck={false}
|
||||
value={counterMax || ''}
|
||||
onChange={this.onCounterMaxChange}
|
||||
placeholder={'max value'}
|
||||
/>
|
||||
<label className="gf-form-label width-10">Reset Value</label>
|
||||
<Input
|
||||
className={'min-width-6 flex-grow-1'}
|
||||
spellCheck={false}
|
||||
value={counterResetValue || ''}
|
||||
onChange={this.onCounterResetValueChange}
|
||||
placeholder={'reset value'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,519 @@
|
||||
import React, { Component } from 'react';
|
||||
import { QueryEditor } from './QueryEditor';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import { Tooltip } from '@material-ui/core';
|
||||
import { Icon } from '@grafana/ui';
|
||||
import _ from 'lodash';
|
||||
import { AsyncTypeahead, TypeaheadModel } from 'react-bootstrap-typeahead';
|
||||
|
||||
export interface Props {
|
||||
tags: { [key: string]: string };
|
||||
parent: QueryEditor;
|
||||
}
|
||||
|
||||
interface State {
|
||||
tags: Tag[];
|
||||
tagKeyOptionsLoading: boolean;
|
||||
tagKeyOptions: TypeaheadModel[];
|
||||
tagValueOptionsLoading: boolean;
|
||||
tagValueOptions: TypeaheadModel[];
|
||||
}
|
||||
|
||||
interface Tag {
|
||||
key: string;
|
||||
value: string;
|
||||
editing: boolean;
|
||||
errors: string[] | undefined;
|
||||
}
|
||||
|
||||
const HtmlTooltip = withStyles((theme) => ({
|
||||
tooltip: {
|
||||
backgroundColor: '#f5f5f9',
|
||||
color: 'rgba(0, 0, 0, 0.87)',
|
||||
maxWidth: 220,
|
||||
fontSize: theme.typography.pxToRem(12),
|
||||
border: '1px solid #dadde9',
|
||||
},
|
||||
}))(Tooltip);
|
||||
|
||||
export class TagEditor extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
tags: Object.entries(props.tags)
|
||||
.map(([key, value]) => ({
|
||||
key: key,
|
||||
value: value,
|
||||
editing: false,
|
||||
errors: undefined,
|
||||
}))
|
||||
.concat(),
|
||||
tagKeyOptionsLoading: false,
|
||||
tagKeyOptions: [],
|
||||
tagValueOptionsLoading: false,
|
||||
tagValueOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
validateTags = (tags: Tag[], tagNumber: number): boolean => {
|
||||
var count = new Map<string, number>();
|
||||
var anyErrors = false;
|
||||
tags.forEach((tag) => {
|
||||
var n = count.get(tag.key);
|
||||
if (n === undefined) {
|
||||
count.set(tag.key, 1);
|
||||
} else {
|
||||
count.set(tag.key, n! + 1);
|
||||
}
|
||||
});
|
||||
|
||||
var tagsToValidate: Tag[];
|
||||
if (tagNumber === undefined) {
|
||||
tagsToValidate = tags;
|
||||
} else {
|
||||
tagsToValidate = tags.filter((t, i) => i === tagNumber);
|
||||
}
|
||||
|
||||
tagsToValidate.forEach((tag, i) => {
|
||||
tag.errors = [];
|
||||
if (tag.key.length > 0 && count.get(tag.key)! > 1) {
|
||||
tag.errors.push("duplicate tag key '" + tag.key + "'");
|
||||
anyErrors = true;
|
||||
}
|
||||
if (tag.key.length === 0) {
|
||||
tag.errors.push('tag key can not be empty');
|
||||
anyErrors = true;
|
||||
}
|
||||
if (tag.value.length === 0) {
|
||||
tag.errors.push('tag value can not be empty');
|
||||
anyErrors = true;
|
||||
}
|
||||
if (tag.errors.length === 0) {
|
||||
tag.errors = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
return anyErrors;
|
||||
};
|
||||
|
||||
addTag = () => {
|
||||
this.setState((state, props) => {
|
||||
const stateTags = state.tags;
|
||||
var tags = [
|
||||
...stateTags,
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
editing: true,
|
||||
errors: ['tag key can not be empty', 'tag value can not be empty'],
|
||||
},
|
||||
];
|
||||
return { tags: tags };
|
||||
});
|
||||
};
|
||||
|
||||
removeTag = (tagNumber: number) => {
|
||||
this.setState((state, props) => {
|
||||
const tags = state.tags;
|
||||
tags.splice(tagNumber, 1);
|
||||
this.updateTags(tags);
|
||||
return { tags: tags };
|
||||
});
|
||||
};
|
||||
|
||||
beginEdit = (tagNumber: number) => {
|
||||
this.setState((state, props) => {
|
||||
const tags = state.tags;
|
||||
var tag = tags.filter((t, i) => i === tagNumber).pop();
|
||||
if (tag !== undefined) {
|
||||
tag.editing = true;
|
||||
}
|
||||
return { tags: tags };
|
||||
});
|
||||
};
|
||||
|
||||
endEdit = (tagNumber: number) => {
|
||||
this.setState((state, props) => {
|
||||
const tags = state.tags;
|
||||
var tag = tags.filter((t, i) => i === tagNumber).pop();
|
||||
if (tag !== undefined && this.validateTags(tags, tagNumber) === false) {
|
||||
tag.editing = false;
|
||||
this.updateTags(tags);
|
||||
}
|
||||
return { tags: tags };
|
||||
});
|
||||
};
|
||||
|
||||
updateTagKey = (tagNumber: number, newKey: string) => {
|
||||
this.setState((state, props) => {
|
||||
var tags = state.tags;
|
||||
var tag = tags.filter((t, i) => i === tagNumber).pop();
|
||||
if (tag !== undefined) {
|
||||
tag.key = newKey;
|
||||
}
|
||||
this.validateTags(tags, tagNumber);
|
||||
return { tags: tags };
|
||||
});
|
||||
};
|
||||
|
||||
updateTagValue = (tagNumber: number, newValue: string) => {
|
||||
this.setState((state, props) => {
|
||||
var tags = state.tags;
|
||||
var tag = tags.filter((t, i) => i === tagNumber).pop();
|
||||
if (tag !== undefined) {
|
||||
tag.value = newValue;
|
||||
}
|
||||
this.validateTags(tags, tagNumber);
|
||||
return { tags: tags };
|
||||
});
|
||||
};
|
||||
|
||||
updateTags = (tags: Tag[]) => {
|
||||
var entries = Object.fromEntries([...tags.values()].map((tag) => [tag.key, tag.value]).concat());
|
||||
this.props.parent.updateTags(entries);
|
||||
};
|
||||
|
||||
handleTagKeySearch = (query: string, metric: string | undefined) => {
|
||||
if (metric !== undefined) {
|
||||
this.props.parent.props.datasource
|
||||
.postResource('/api/suggest', {
|
||||
type: 'tagk',
|
||||
m: metric,
|
||||
max: '1000',
|
||||
})
|
||||
.then((result: any) => {
|
||||
if (result && _.isArray(result)) {
|
||||
const tagKeyArray: string[] = result;
|
||||
var tags = this.state.tags;
|
||||
|
||||
// find all tag keys that are being used in non-edited tags
|
||||
var existingTags = tags
|
||||
.filter((t) => t.editing === false)
|
||||
.map((t) => {
|
||||
return t.key;
|
||||
})
|
||||
.concat();
|
||||
|
||||
// exclude keys that are bing used
|
||||
var filteredResults = tagKeyArray.filter((t) => {
|
||||
return existingTags.find((existing) => t === existing) === undefined;
|
||||
});
|
||||
|
||||
// exclude keys that don't match the search (if there is one)
|
||||
filteredResults = filteredResults
|
||||
.filter((tagKey) => query === '' || tagKey.toLowerCase().includes(query.toLowerCase()))
|
||||
.map((value) => {
|
||||
return value;
|
||||
});
|
||||
this.setState({ tagKeyOptions: filteredResults });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleTagValueSearch = (query: string, metric: string | undefined, tagKey: string | undefined) => {
|
||||
if (metric !== undefined && tagKey !== undefined) {
|
||||
this.props.parent.props.datasource
|
||||
.postResource('/api/suggest', {
|
||||
type: 'tagv',
|
||||
m: metric,
|
||||
t: tagKey,
|
||||
max: '1000',
|
||||
})
|
||||
.then((result: any) => {
|
||||
if (result && _.isArray(result)) {
|
||||
const tagValueArray: string[] = ['.*', ...result];
|
||||
const filteredResults = tagValueArray
|
||||
.filter((tagValue) => query === '' || tagValue.toLowerCase().includes(query.toLowerCase()))
|
||||
.map((value) => {
|
||||
return value;
|
||||
});
|
||||
this.setState({ tagValueOptions: filteredResults });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getInputValue = (id: string): string | null => {
|
||||
var fullId = 'div#' + id + ' div div input.rbt-input-main';
|
||||
var inputElement = document.querySelector(fullId);
|
||||
if (inputElement !== null) {
|
||||
return (inputElement as HTMLInputElement).value;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { tagKeyOptionsLoading, tagKeyOptions, tagValueOptionsLoading, tagValueOptions } = this.state;
|
||||
var { tags } = this.state;
|
||||
var tagEditorId = Math.random().toString(36).substr(2, 9);
|
||||
var lastSearchMetric: string;
|
||||
const { metric } = this.props.parent.state.query;
|
||||
var allowAddNewTag = tags.filter((t) => t.editing === true).length === 0;
|
||||
|
||||
return (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form timely">
|
||||
<label className="gf-form-label width-10">Tags</label>
|
||||
{[...tags.values()].map((tag, tagNum) => (
|
||||
<div key={tagNum.toString()} id={'timelytag-' + tagNum.toString()}>
|
||||
<div hidden={tag.editing}>
|
||||
<label className="gf-form-label">
|
||||
{tag.key} = {tag.value}
|
||||
<div className="timely tag edit">
|
||||
<HtmlTooltip title={'edit tag'} placement={'bottom'}>
|
||||
<Icon
|
||||
name="edit"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
this.beginEdit(tagNum);
|
||||
}}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.beginEdit(tagNum);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</HtmlTooltip>
|
||||
</div>
|
||||
<div className="timely tag delete">
|
||||
<HtmlTooltip title={'delete tag'} placement={'bottom'}>
|
||||
<Icon
|
||||
name="trash-alt"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
this.removeTag(tagNum);
|
||||
}}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.removeTag(tagNum);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</HtmlTooltip>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div className="gf-form" hidden={!tag.editing}>
|
||||
<div
|
||||
id={'timelyTagKey-' + tagEditorId + '-' + tagNum.toString()}
|
||||
className="timely timely-tag-key"
|
||||
onMouseLeave={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (inputValue !== null) {
|
||||
this.updateTagKey(tagNum, inputValue);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<AsyncTypeahead
|
||||
id={'timelyTagKey-' + tagEditorId + '-Typeahead'}
|
||||
selected={[tag.key]}
|
||||
isLoading={tagKeyOptionsLoading}
|
||||
inputProps={{ spellCheck: false }}
|
||||
onSearch={(query) => {
|
||||
this.setState({ tagKeyOptionsLoading: true });
|
||||
lastSearchMetric = metric!;
|
||||
this.handleTagKeySearch(query, metric);
|
||||
this.setState({ tagKeyOptionsLoading: false });
|
||||
}}
|
||||
onChange={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (inputValue !== null) {
|
||||
this.updateTagKey(tagNum, inputValue);
|
||||
}
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (inputValue !== null) {
|
||||
this.updateTagKey(tagNum, inputValue);
|
||||
}
|
||||
}}
|
||||
onFocus={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (
|
||||
tagKeyOptions.length === 0 ||
|
||||
inputValue === null ||
|
||||
inputValue.length === 0 ||
|
||||
metric !== lastSearchMetric
|
||||
) {
|
||||
this.setState({ tagKeyOptionsLoading: true });
|
||||
lastSearchMetric = metric!;
|
||||
this.handleTagKeySearch('', metric);
|
||||
this.setState({ tagKeyOptionsLoading: false });
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (
|
||||
tagKeyOptions.length === 0 ||
|
||||
inputValue === null ||
|
||||
inputValue.length === 0 ||
|
||||
metric !== lastSearchMetric
|
||||
) {
|
||||
this.setState({ tagKeyOptionsLoading: true });
|
||||
lastSearchMetric = metric!;
|
||||
this.handleTagKeySearch('', metric);
|
||||
this.setState({ tagKeyOptionsLoading: false });
|
||||
}
|
||||
}}
|
||||
autoFocus={tag.key.length === 0}
|
||||
options={tagKeyOptions}
|
||||
selectHintOnEnter={false}
|
||||
align={'left'}
|
||||
allowNew={true}
|
||||
newSelectionPrefix={''}
|
||||
paginate={true}
|
||||
paginationText={'more'}
|
||||
minLength={0}
|
||||
maxResults={100}
|
||||
caseSensitive={false}
|
||||
placeholder={'key'}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id={'timelyTagValue-' + tagEditorId + '-' + tagNum.toString()}
|
||||
className="timely timely-tag-value"
|
||||
onMouseLeave={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (inputValue !== null) {
|
||||
this.updateTagValue(tagNum, inputValue);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<AsyncTypeahead
|
||||
id={'timelyTagValue-' + tagEditorId + '-Typeahead'}
|
||||
selected={[tag.value]}
|
||||
isLoading={tagValueOptionsLoading}
|
||||
inputProps={{ spellCheck: false }}
|
||||
onSearch={(query) => {
|
||||
this.setState({ tagValueOptionsLoading: true });
|
||||
this.handleTagValueSearch(query, metric, tag.key);
|
||||
this.setState({ tagValueOptionsLoading: false });
|
||||
}}
|
||||
onChange={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (inputValue !== null) {
|
||||
this.updateTagValue(tagNum, inputValue);
|
||||
}
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (inputValue !== null) {
|
||||
this.updateTagValue(tagNum, inputValue);
|
||||
}
|
||||
}}
|
||||
onFocus={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (tagValueOptions.length === 0 || inputValue === null || inputValue.length === 0) {
|
||||
this.setState({ tagValueOptionsLoading: true });
|
||||
this.handleTagValueSearch('', metric, tag.key);
|
||||
this.setState({ tagValueOptionsLoading: false });
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
|
||||
if (tagValueOptions.length === 0 || inputValue === null || inputValue.length === 0) {
|
||||
this.setState({ tagValueOptionsLoading: true });
|
||||
this.handleTagValueSearch('', metric, tag.key);
|
||||
this.setState({ tagValueOptionsLoading: false });
|
||||
}
|
||||
}}
|
||||
options={tagValueOptions}
|
||||
selectHintOnEnter={false}
|
||||
align={'left'}
|
||||
allowNew={true}
|
||||
newSelectionPrefix={''}
|
||||
paginate={true}
|
||||
paginationText={'more'}
|
||||
minLength={0}
|
||||
maxResults={100}
|
||||
caseSensitive={false}
|
||||
placeholder={'value'}
|
||||
/>
|
||||
</div>
|
||||
<label className="gf-form-label max-width-5 flex-shrink-1">
|
||||
{tag.errors !== undefined && (
|
||||
<div className="timely tag error">
|
||||
<HtmlTooltip
|
||||
title={
|
||||
<React.Fragment>
|
||||
<ul>
|
||||
{tag.errors.map((error) => {
|
||||
return <li key={error}>{error}</li>;
|
||||
})}
|
||||
</ul>
|
||||
</React.Fragment>
|
||||
}
|
||||
placement={'bottom'}
|
||||
>
|
||||
<Icon name="exclamation-triangle" />
|
||||
</HtmlTooltip>
|
||||
</div>
|
||||
)}
|
||||
{tag.errors === undefined && (
|
||||
<div className="timely tag save">
|
||||
<HtmlTooltip title={'save tag'} placement={'bottom'}>
|
||||
<Icon
|
||||
name="save"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
this.endEdit(tagNum);
|
||||
}}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.endEdit(tagNum);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</HtmlTooltip>
|
||||
</div>
|
||||
)}
|
||||
<div className="timely tag delete">
|
||||
<HtmlTooltip title={'delete tag'} placement={'bottom'}>
|
||||
<Icon
|
||||
name="trash-alt"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
this.removeTag(tagNum);
|
||||
}}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.removeTag(tagNum);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</HtmlTooltip>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="gf-form" hidden={!allowAddNewTag}>
|
||||
<label className="gf-form-label">
|
||||
<div className="timely tag addtag">
|
||||
<HtmlTooltip title={'add tag'} placement={'bottom'}>
|
||||
<Icon
|
||||
name="plus"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
this.addTag();
|
||||
}}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.addTag();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</HtmlTooltip>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,24 @@
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
AdHocVariableFilter,
|
||||
DataFrame,
|
||||
DataQuery,
|
||||
DataQueryRequest,
|
||||
DataQueryResponse,
|
||||
DataSourceInstanceSettings,
|
||||
Field,
|
||||
Labels,
|
||||
MetricFindValue,
|
||||
ScopedVars, TestDataSourceResponse,
|
||||
} from '@grafana/data';
|
||||
import { DataQuery } from '@grafana/schema';
|
||||
import { DataSourceWithBackend, HealthCheckResult, getTemplateSrv } from '@grafana/runtime';
|
||||
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
|
||||
import { TimelyDataSourceOptions, TimelyQueryForm } from './types';
|
||||
import { Observable } from 'rxjs';
|
||||
import { HealthCheckResult } from '@grafana/runtime/utils/DataSourceWithBackend';
|
||||
import { DataFrame } from '@grafana/data/types/dataFrame';
|
||||
import { ScopedVars } from '@grafana/data/types/ScopedVars';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, TimelyDataSourceOptions> {
|
||||
|
||||
instanceSettings: DataSourceInstanceSettings<TimelyDataSourceOptions>
|
||||
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<TimelyDataSourceOptions>) {
|
||||
super(instanceSettings);
|
||||
this.instanceSettings = instanceSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,9 +26,9 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
*/
|
||||
query(request: DataQueryRequest<TimelyQueryForm>): Observable<DataQueryResponse> {
|
||||
// match query refId to TimelyQueryForm for correlation to results
|
||||
let targetIndex: { [key: string]: TimelyQueryForm } = {};
|
||||
var targetIndex: { [key: string]: TimelyQueryForm } = {};
|
||||
request.targets.forEach((target) => {
|
||||
let query = target as TimelyQueryForm;
|
||||
var query = target as TimelyQueryForm;
|
||||
targetIndex[query.refId] = query;
|
||||
});
|
||||
|
||||
@@ -42,8 +38,8 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
return super.query(request).pipe(
|
||||
map((dataQueryResponse) => {
|
||||
dataQueryResponse.data.forEach((data) => {
|
||||
let dataFrame = data as DataFrame;
|
||||
let currentQuery = targetIndex[dataFrame.refId!];
|
||||
var dataFrame = data as DataFrame;
|
||||
var currentQuery = targetIndex[dataFrame.refId!];
|
||||
// prevent grafana from prepending the dataFrame name
|
||||
// to the series names by naming them all the same
|
||||
dataFrame.fields.forEach((field) => {
|
||||
@@ -77,12 +73,12 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}
|
||||
|
||||
setSeriesName(query: TimelyQueryForm, scopedVars: ScopedVars, field: Field, alias: string | undefined) {
|
||||
let title: string | null = null;
|
||||
var title: string | null = null;
|
||||
if (alias === undefined || alias === '') {
|
||||
if (field.labels === undefined) {
|
||||
title = query.metric!;
|
||||
} else {
|
||||
let singleTagName = this.getSingleLabelName(field.labels);
|
||||
var singleTagName = this.getSingleLabelName(field.labels);
|
||||
if (singleTagName === null) {
|
||||
title = query.metric! + this.joinLabels(field.labels);
|
||||
} else {
|
||||
@@ -90,7 +86,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let newScopedVars = _.clone(scopedVars || {});
|
||||
var newScopedVars = _.clone(scopedVars || {});
|
||||
for (const labelKey in field.labels) {
|
||||
newScopedVars['tag_' + labelKey] = {
|
||||
text: field.labels[labelKey],
|
||||
@@ -108,8 +104,8 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
};
|
||||
}
|
||||
|
||||
applyTemplateVariables(query: DataQuery, scopedVars: ScopedVars, filters?: AdHocVariableFilter[]) {
|
||||
let timelyQuery = query as TimelyQueryForm;
|
||||
applyTemplateVariables(query: DataQuery): DataQuery {
|
||||
var timelyQuery = query as TimelyQueryForm;
|
||||
if (timelyQuery.metric !== undefined) {
|
||||
timelyQuery.metric = getTemplateSrv().replace(timelyQuery.metric);
|
||||
for (let tagsKey in timelyQuery.tags) {
|
||||
@@ -141,7 +137,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
});
|
||||
}
|
||||
|
||||
let interpolated;
|
||||
var interpolated;
|
||||
try {
|
||||
interpolated = getTemplateSrv().replace(query);
|
||||
} catch (err) {
|
||||
@@ -150,22 +146,22 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
});
|
||||
}
|
||||
|
||||
let responseTransform = function (result: string[]): MetricFindValue[] {
|
||||
var responseTransform = function (result: string[]): MetricFindValue[] {
|
||||
return _.map(result, function (value) {
|
||||
let mfv: MetricFindValue = {
|
||||
var mfv: MetricFindValue = {
|
||||
text: value,
|
||||
};
|
||||
return mfv;
|
||||
}).concat();
|
||||
};
|
||||
|
||||
let metrics_regex = /metrics\((.*)\)/;
|
||||
let tag_names_suggest_regex = /suggest_tagk\((.*)\)/;
|
||||
let tag_values_suggest_regex = /suggest_tagv\((.*?),\s?(.*)\)/;
|
||||
let tag_names_regex = /tag_names\((.*)\)/;
|
||||
let tag_values_regex = /tag_values\((.*?),\s?(.*)\)/;
|
||||
var metrics_regex = /metrics\((.*)\)/;
|
||||
var tag_names_suggest_regex = /suggest_tagk\((.*)\)/;
|
||||
var tag_values_suggest_regex = /suggest_tagv\((.*?),\s?(.*)\)/;
|
||||
var tag_names_regex = /tag_names\((.*)\)/;
|
||||
var tag_values_regex = /tag_values\((.*?),\s?(.*)\)/;
|
||||
|
||||
let metrics_query = interpolated.match(metrics_regex);
|
||||
var metrics_query = interpolated.match(metrics_regex);
|
||||
if (metrics_query) {
|
||||
return this._performSuggestQuery({
|
||||
type: 'metrics',
|
||||
@@ -174,7 +170,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}).then(responseTransform);
|
||||
}
|
||||
|
||||
let tag_names_suggest_query = interpolated.match(tag_names_suggest_regex);
|
||||
var tag_names_suggest_query = interpolated.match(tag_names_suggest_regex);
|
||||
if (tag_names_suggest_query) {
|
||||
return this._performSuggestQuery({
|
||||
type: 'tagk',
|
||||
@@ -183,7 +179,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}).then(responseTransform);
|
||||
}
|
||||
|
||||
let tag_values_suggest_query = interpolated.match(tag_values_suggest_regex);
|
||||
var tag_values_suggest_query = interpolated.match(tag_values_suggest_regex);
|
||||
if (tag_values_suggest_query) {
|
||||
return this._performSuggestQuery({
|
||||
type: 'tagv',
|
||||
@@ -193,7 +189,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}).then(responseTransform);
|
||||
}
|
||||
|
||||
let tag_names_query = interpolated.match(tag_names_regex);
|
||||
var tag_names_query = interpolated.match(tag_names_regex);
|
||||
if (tag_names_query) {
|
||||
return this._performSuggestQuery({
|
||||
type: 'tagk',
|
||||
@@ -202,7 +198,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}).then(responseTransform);
|
||||
}
|
||||
|
||||
let tag_values_query = interpolated.match(tag_values_regex);
|
||||
var tag_values_query = interpolated.match(tag_values_regex);
|
||||
if (tag_values_query) {
|
||||
return this._performSuggestQuery({
|
||||
type: 'tagv',
|
||||
@@ -223,18 +219,8 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
}
|
||||
|
||||
// DataSourceApi
|
||||
testDatasource(): Promise<TestDataSourceResponse> {
|
||||
try {
|
||||
return this.getResource('/api/suggest', { type: 'metrics', max: '-1' }).then((result: any) => {
|
||||
if (result && _.isArray(result)) {
|
||||
return Promise.resolve({ message: 'Data source is working', status: 'Data source is working' });
|
||||
} else {
|
||||
return Promise.reject({ message: 'Data source failed: ' + result.message, status: 'Data source failed' });
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
return Promise.reject({ message: 'Data source failed', status: 'Data source failed', error: e });
|
||||
}
|
||||
testDatasource(): Promise<any> {
|
||||
return super.testDatasource();
|
||||
}
|
||||
|
||||
// DataSourceApi
|
||||
@@ -244,7 +230,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
const metrics: string[] = result;
|
||||
return metrics
|
||||
.map((value) => {
|
||||
let mfv: MetricFindValue = {
|
||||
var mfv: MetricFindValue = {
|
||||
text: value,
|
||||
};
|
||||
return mfv;
|
||||
@@ -263,7 +249,7 @@ export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, Tim
|
||||
const metrics: string[] = result;
|
||||
return metrics
|
||||
.map((value) => {
|
||||
let mfv: MetricFindValue = {
|
||||
var mfv: MetricFindValue = {
|
||||
text: value,
|
||||
};
|
||||
return mfv;
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('placeholder test', () => {
|
||||
it('should return true', () => {
|
||||
expect(true).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DataSourcePlugin } from '@grafana/data';
|
||||
import { TimelyDataSource } from './TimelyDataSource';
|
||||
import { ConfigEditor } from './components/ConfigEditor';
|
||||
import { QueryEditor } from './components/QueryEditor';
|
||||
import { ConfigEditor } from './ConfigEditor';
|
||||
import { QueryEditor } from './QueryEditor';
|
||||
import { TimelyDataSourceOptions, TimelyQueryForm } from './types';
|
||||
import 'static/css/timely-bootstrap.css';
|
||||
import 'static/css/timely.css';
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/grafana/grafana/main/docs/sources/developers/plugins/plugin.schema.json",
|
||||
"type": "datasource",
|
||||
"name": "Timely",
|
||||
"id": "nsa-timely-datasource",
|
||||
@@ -7,13 +6,13 @@
|
||||
"metrics": true,
|
||||
"backend": true,
|
||||
"alerting": true,
|
||||
"executable": "timely_datasource",
|
||||
"executable": "timely_datasource_backend",
|
||||
"info": {
|
||||
"description": "Datasource for Timely",
|
||||
"description": "Open source time series database backed by Accumulo",
|
||||
"author": {
|
||||
"name": "National Security Agency"
|
||||
},
|
||||
"keywords": ["datasource"],
|
||||
"keywords": ["Simple"],
|
||||
"logos": {
|
||||
"small": "static/img/timely_square_small.png",
|
||||
"large": "static/img/timely_square_large.png"
|
||||
@@ -33,7 +32,9 @@
|
||||
"updated": "%TODAY%"
|
||||
},
|
||||
"dependencies": {
|
||||
"grafanaDependency": ">=10.0.0",
|
||||
"classnames": "2.2.6",
|
||||
"slate-plain-serializer": "0.7.10",
|
||||
"grafanaVersion": "6.5.x",
|
||||
"plugins": []
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@ div.timely input:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.timely-edior-row div.gf-form-inline {
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
div.timely input.form-control {
|
||||
border-color: rgb(44, 50, 53);
|
||||
border-top-color: rgb(44, 50, 53);
|
||||
@@ -52,10 +56,6 @@ div.timely.tag.addtag svg {
|
||||
color: #62a562;
|
||||
}
|
||||
|
||||
div.timely.tag.deletetag svg {
|
||||
color: #d9162d;
|
||||
}
|
||||
|
||||
button[title='Move query down'] div svg {
|
||||
color: #b3bfbd;
|
||||
}
|
||||
@@ -75,36 +75,3 @@ button[title='Disable/enable query'] div svg {
|
||||
button[title='Remove query'] div svg {
|
||||
color: #d9162d;
|
||||
}
|
||||
|
||||
.queryErrorFieldRow {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.queryErrorContainer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.queryErrorIconDiv {
|
||||
background-color: rgb(209, 14, 92);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.queryErrorIcon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
line-height: 0;
|
||||
vertical-align: middle;
|
||||
fill: rgb(255, 255, 255);
|
||||
overflow-clip-margin: content-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.queryErrorText {
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
font-size: 0.857143rem;
|
||||
font-family: "Roboto Mono", monospace;
|
||||
padding: 8px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,54 @@
|
||||
$box-shadow-dimensions: 0 0 0 0.2rem;
|
||||
$placeholder-color: #6c757d;
|
||||
|
||||
.rbt {
|
||||
&-input-multi {
|
||||
// Bootstrap 4 focus style
|
||||
&.focus {
|
||||
background-color: #fff;
|
||||
border-color: #80bdff;
|
||||
box-shadow: $box-shadow-dimensions rgba(0, 123, 255, 0.25);
|
||||
color: #495057;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&.is-invalid.focus {
|
||||
border-color: #dc3545;
|
||||
box-shadow: $box-shadow-dimensions rgba(220, 53, 69, 0.25);
|
||||
}
|
||||
|
||||
&.is-valid.focus {
|
||||
border-color: #28a745;
|
||||
box-shadow: $box-shadow-dimensions rgba(40, 167, 69, 0.25);
|
||||
}
|
||||
|
||||
input {
|
||||
// Firefox
|
||||
&::-moz-placeholder {
|
||||
color: $placeholder-color;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Internet Explorer 10+
|
||||
&:-ms-input-placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
|
||||
// Safari and Chrome
|
||||
&::-webkit-input-placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
// Override height in main CSS file :/
|
||||
& .rbt-input-main,
|
||||
&.form-control-lg .rbt-input-main,
|
||||
&.form-control-sm .rbt-input-main {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-token {
|
||||
margin: 1px 3px 2px 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
.rbt .rbt-input-main::-ms-clear {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu
|
||||
*/
|
||||
.rbt-menu {
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.rbt-menu > .dropdown-item {
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
.rbt-menu > .dropdown-item:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.rbt-menu-pagination-option {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-select Input
|
||||
*/
|
||||
.rbt-input-multi {
|
||||
cursor: text !important;
|
||||
overflow: hidden !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.focus {
|
||||
border-color: #80bdff !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
||||
color: #495057 !important;
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.form-control {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.form-control[disabled] {
|
||||
background-color: #e9ecef !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.is-invalid.focus {
|
||||
border-color: #dc3545 !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi.is-valid.focus {
|
||||
border-color: #28a745 !important;
|
||||
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi input::-moz-placeholder {
|
||||
color: #6c757d !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi input:-ms-input-placeholder {
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi input::-webkit-input-placeholder {
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi .rbt-input-wrapper {
|
||||
align-items: flex-start !important;
|
||||
display: flex !important;
|
||||
flex-wrap: wrap !important;
|
||||
margin-bottom: -4px !important;
|
||||
margin-top: -1px !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.rbt-input-multi .rbt-input-main {
|
||||
margin: 1px 0 4px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Button
|
||||
*/
|
||||
.rbt-close {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
|
||||
.rbt-close-lg {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token
|
||||
*/
|
||||
.rbt-token {
|
||||
background-color: #e7f4ff !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0.25rem !important;
|
||||
color: #007bff !important;
|
||||
display: inline-block !important;
|
||||
line-height: 1em !important;
|
||||
margin: 1px 3px 2px 0 !important;
|
||||
padding: 4px 7px !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.rbt-token-disabled {
|
||||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||||
color: #495057 !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.rbt-token-removeable {
|
||||
cursor: pointer !important;
|
||||
padding-right: 21px !important;
|
||||
}
|
||||
|
||||
.rbt-token-active {
|
||||
background-color: #007bff !important;
|
||||
color: #fff !important;
|
||||
outline: none !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.rbt-token .rbt-token-remove-button {
|
||||
bottom: 0 !important;
|
||||
color: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: normal !important;
|
||||
opacity: 1 !important;
|
||||
outline: none !important;
|
||||
padding: 3px 7px !important;
|
||||
position: absolute !important;
|
||||
right: 0 !important;
|
||||
text-shadow: none !important;
|
||||
top: -2px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loader + CloseButton container
|
||||
*/
|
||||
.rbt-aux {
|
||||
align-items: center !important;
|
||||
display: flex !important;
|
||||
bottom: 0 !important;
|
||||
justify-content: center !important;
|
||||
pointer-events: none !important;
|
||||
/* Don't block clicks on the input */
|
||||
position: absolute !important;
|
||||
right: 0 !important;
|
||||
top: 0 !important;
|
||||
width: 34px !important;
|
||||
}
|
||||
|
||||
.rbt-aux-lg {
|
||||
width: 46px !important;
|
||||
}
|
||||
|
||||
.rbt-aux .rbt-close {
|
||||
margin-top: -4px !important;
|
||||
pointer-events: auto !important;
|
||||
/* Override pointer-events: none; above */
|
||||
}
|
||||
|
||||
.has-aux .rbt-input {
|
||||
padding-right: 34px !important;
|
||||
}
|
||||
|
||||
.rbt-highlight-text {
|
||||
background-color: inherit !important;
|
||||
color: inherit !important;
|
||||
font-weight: bold !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input Groups
|
||||
*/
|
||||
.input-group > .rbt {
|
||||
flex: 1 !important;
|
||||
}
|
||||
|
||||
.input-group > .rbt .rbt-input-hint,
|
||||
.input-group > .rbt .rbt-aux {
|
||||
z-index: 5 !important;
|
||||
}
|
||||
|
||||
.input-group > .rbt:not(:first-child) .form-control {
|
||||
border-top-left-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
}
|
||||
|
||||
.input-group > .rbt:not(:last-child) .form-control {
|
||||
border-top-right-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||