Browse code

BM-14990 Feat: db metrics

Thomas Fricker authored on 01/07/2019 13:47:34
Showing 6 changed files
... ...
@@ -64,6 +64,10 @@ public class JdbcActivator implements BundleActivator {
64 64
 		return dataSource;
65 65
 	}
66 66
 
67
+	public Map<String, DataSource> getMailboxDataSource() {
68
+		return mailboxDataSource;
69
+	}
70
+
67 71
 	public void setDataSource(DataSource dataSource) {
68 72
 		this.dataSource = dataSource;
69 73
 		ServerSideServiceProvider.defaultDataSource = dataSource;
... ...
@@ -24,7 +24,10 @@ Require-Bundle: org.eclipse.core.runtime,
24 24
  io.netty,
25 25
  com.ning.async-http-client,
26 26
  net.bluemind.network.utils,
27
- net.bluemind.network.topology
27
+ net.bluemind.network.topology,
28
+ net.bluemind.core.jdbc;bundle-version="4.1.0",
29
+ com.netflix.spectator.api,
30
+ net.bluemind.metrics.registry
28 31
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
29 32
 Automatic-Module-Name: net.bluemind.metrics.core
30 33
 Bundle-ActivationPolicy: lazy
... ...
@@ -149,6 +149,9 @@
149 149
          <tick_template_provider
150 150
                impl="net.bluemind.metrics.core.tick.scripts.MailspoolWorstResponseTime">
151 151
          </tick_template_provider>
152
+         <tick_template_provider
153
+               impl="net.bluemind.metrics.core.tick.scripts.DbConnections">
154
+         </tick_template_provider>
152 155
    </extension>
153 156
    <extension
154 157
          point="net.bluemind.metrics.core.tickDashboardProvider">
... ...
@@ -200,4 +203,11 @@
200 203
       </verticle>
201 204
    </extension>
202 205
    
206
+   <extension
207
+         point="net.bluemind.lib.vertx.verticles">
208
+      <verticle
209
+            impl="net.bluemind.metrics.core.db.DbCheck$Factory">
210
+      </verticle>
211
+   </extension>
212
+   
203 213
 </plugin>
204 214
new file mode 100644
... ...
@@ -0,0 +1,105 @@
1
+/* BEGIN LICENSE
2
+ * Copyright © Blue Mind SAS, 2012-2018
3
+ *
4
+ * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+ * solution.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of either the GNU Affero General Public License as
9
+ * published by the Free Software Foundation (version 3 of the License).
10
+ *
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
+ *
16
+ * See LICENSE.txt
17
+ * END LICENSE
18
+ */
19
+package net.bluemind.metrics.core.db;
20
+
21
+import java.sql.Connection;
22
+
23
+import javax.sql.DataSource;
24
+
25
+import org.osgi.framework.BundleActivator;
26
+import org.osgi.framework.BundleContext;
27
+import org.slf4j.Logger;
28
+import org.slf4j.LoggerFactory;
29
+import org.vertx.java.platform.Verticle;
30
+
31
+import com.netflix.spectator.api.Registry;
32
+
33
+import net.bluemind.core.jdbc.JdbcActivator;
34
+import net.bluemind.lib.vertx.IUniqueVerticleFactory;
35
+import net.bluemind.lib.vertx.IVerticleFactory;
36
+import net.bluemind.metrics.registry.IdFactory;
37
+import net.bluemind.metrics.registry.MetricsRegistry;
38
+import net.bluemind.network.topology.Topology;
39
+
40
+public class DbCheck extends Verticle implements BundleActivator {
41
+
42
+	private Registry metricRegistry;
43
+	private IdFactory idFactory;
44
+
45
+	Logger logger = LoggerFactory.getLogger(DbCheck.class);
46
+
47
+	@Override
48
+	public void start() {
49
+		super.start();
50
+
51
+		metricRegistry = MetricsRegistry.get();
52
+		idFactory = new IdFactory("jdbc", metricRegistry, DbCheck.class);
53
+
54
+		super.vertx.setPeriodic(1000 * 10, (id) -> {
55
+			String coreuid = Topology.get().core().uid;
56
+			check(JdbcActivator.getInstance().getDataSource(), coreuid, "directory");
57
+			JdbcActivator.getInstance().getMailboxDataSource().entrySet().forEach(e -> {
58
+				check(e.getValue(), e.getKey(), "mailbox");
59
+			});
60
+		});
61
+	}
62
+
63
+	private void check(DataSource ds, String dataLocation, String kind) {
64
+		boolean isValid = false;
65
+		try (Connection con = ds.getConnection()) {
66
+			isValid = con.isValid(3);
67
+		} catch (Exception e) {
68
+			logger.warn("DBCheck failed on db {}", dataLocation, e);
69
+		}
70
+
71
+		if (!isValid) {
72
+			logger.warn("DB-check failed on {}, {}", dataLocation, kind);
73
+		}
74
+
75
+		metricRegistry.gauge(idFactory.name("db-connections", "targetdatalocation", dataLocation, "dbkind", kind))
76
+				.set(isValid ? 1 : 0);
77
+	}
78
+
79
+	public static class Factory implements IVerticleFactory, IUniqueVerticleFactory {
80
+
81
+		@Override
82
+		public boolean isWorker() {
83
+			return true;
84
+		}
85
+
86
+		@Override
87
+		public Verticle newInstance() {
88
+			return new DbCheck();
89
+		}
90
+
91
+	}
92
+
93
+	@Override
94
+	public void start(BundleContext context) throws Exception {
95
+		// TODO Auto-generated method stub
96
+
97
+	}
98
+
99
+	@Override
100
+	public void stop(BundleContext context) throws Exception {
101
+		// TODO Auto-generated method stub
102
+
103
+	}
104
+
105
+}
0 106
new file mode 100644
... ...
@@ -0,0 +1,83 @@
1
+/* BEGIN LICENSE
2
+ * Copyright © Blue Mind SAS, 2012-2018
3
+ *
4
+ * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+ * solution.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of either the GNU Affero General Public License as
9
+ * published by the Free Software Foundation (version 3 of the License).
10
+ *
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
+ *
16
+ * See LICENSE.txt
17
+ * END LICENSE
18
+ */
19
+package net.bluemind.metrics.core.tick.scripts;
20
+
21
+import java.io.InputStream;
22
+import java.util.ArrayList;
23
+import java.util.EnumSet;
24
+import java.util.List;
25
+import java.util.Set;
26
+
27
+import org.slf4j.Logger;
28
+import org.slf4j.LoggerFactory;
29
+import org.vertx.java.core.json.JsonObject;
30
+
31
+import net.bluemind.core.container.model.ItemValue;
32
+import net.bluemind.core.rest.BmContext;
33
+import net.bluemind.metrics.core.Product;
34
+import net.bluemind.metrics.core.tick.ITickTemplateProvider;
35
+import net.bluemind.metrics.core.tick.TickTemplateDefBuilder;
36
+import net.bluemind.metrics.core.tick.TickTemplateHelper;
37
+import net.bluemind.network.topology.Topology;
38
+import net.bluemind.server.api.Server;
39
+
40
+public class DbConnections implements ITickTemplateProvider {
41
+	private static final Logger logger = LoggerFactory.getLogger(ITickTemplateProvider.class);
42
+
43
+	@Override
44
+	public String templateId() {
45
+		return "db-connections";
46
+	}
47
+
48
+	@Override
49
+	public InputStream content() {
50
+		return DbConnections.class.getClassLoader().getResourceAsStream("tickconfig/db-connections.tick");
51
+	}
52
+
53
+	@Override
54
+	public List<TemplateDefinition> createDefinitions(BmContext ctx, String endPointUrl, ItemValue<Server> server) {
55
+		Set<Product> srvProducts = EnumSet.noneOf(Product.class);
56
+		server.value.tags.forEach(tag -> srvProducts.addAll(Product.byTag(tag)));
57
+
58
+		List<TemplateDefinition> defs = new ArrayList<>();
59
+
60
+		if (srvProducts.contains(Product.POSTGRESQL)) {
61
+			if (Topology.get().core().uid.equals(server.uid)) {
62
+				defs.add(addDefinition(endPointUrl, server,
63
+						TickTemplateHelper.newId(Product.POSTGRESQL, templateId() + ".bj", server), "directory"));
64
+			}
65
+			defs.add(addDefinition(endPointUrl, server,
66
+					TickTemplateHelper.newId(Product.POSTGRESQL, templateId() + ".bj-data", server), "mailbox"));
67
+		}
68
+		return defs;
69
+	}
70
+
71
+	private TemplateDefinition addDefinition(String endPointUrl, ItemValue<Server> server, String alertId,
72
+			String kind) {
73
+		TemplateDefinition def = new TickTemplateDefBuilder(alertId).withDatalocation(server.uid)
74
+				.withEndPoint(endPointUrl).withProduct(Product.POSTGRESQL).build();
75
+
76
+		def.variables.putObject("targetdatalocation",
77
+				new JsonObject().putString("type", "string").putString("value", server.uid));
78
+		def.variables.putObject("dbkind", new JsonObject().putString("type", "string").putString("value", kind));
79
+
80
+		return def;
81
+	}
82
+
83
+}
0 84
new file mode 100644
... ...
@@ -0,0 +1,81 @@
1
+var targetdatalocation string
2
+
3
+var dbkind string
4
+
5
+var datalocation string
6
+
7
+var bmProduct string
8
+
9
+var alertsEndPoint string
10
+
11
+var db = 'telegraf'
12
+
13
+var rp = 'autogen'
14
+
15
+var measurement = 'bm-core.jdbc.db-connections'
16
+
17
+var groupBy = []
18
+
19
+var whereFilter = lambda: ("targetdatalocation" == targetdatalocation) AND ("dbkind" == dbkind)
20
+
21
+var name string
22
+
23
+var idVar = name
24
+
25
+var message = ''
26
+
27
+var idTag = 'alertID'
28
+
29
+var levelTag = 'level'
30
+
31
+var messageField = 'message'
32
+
33
+var durationField = 'duration'
34
+
35
+var outputDB = 'chronograf'
36
+
37
+var outputRP = 'autogen'
38
+
39
+var outputMeasurement = 'alerts'
40
+
41
+var triggerType = 'threshold'
42
+
43
+var crit = 1
44
+
45
+var data = stream
46
+    |from()
47
+        .database(db)
48
+        .retentionPolicy(rp)
49
+        .measurement(measurement)
50
+        .groupBy(groupBy)
51
+        .where(whereFilter)
52
+    |eval(lambda: "value")
53
+        .as('value')
54
+
55
+var trigger = data
56
+    |alert()
57
+        .crit(lambda: "value" < crit)
58
+        .stateChangesOnly()
59
+        .message(message)
60
+        .id(idVar)
61
+        .idTag(idTag)
62
+        .levelTag(levelTag)
63
+        .messageField(messageField)
64
+        .durationField(durationField)
65
+        .stateChangesOnly()
66
+        .post(alertsEndPoint)
67
+
68
+trigger
69
+    |eval(lambda: float("value"))
70
+        .as('value')
71
+        .keep()
72
+    |influxDBOut()
73
+        .create()
74
+        .database(outputDB)
75
+        .retentionPolicy(outputRP)
76
+        .measurement(outputMeasurement)
77
+        .tag('alertName', name)
78
+        .tag('triggerType', triggerType)
79
+
80
+trigger
81
+    |httpOut('output')