Skip to content

Commit dc883b2

Browse files
committed
initial
1 parent 8e04946 commit dc883b2

File tree

7 files changed

+491
-0
lines changed

7 files changed

+491
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@
1010

1111
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
1212
hs_err_pid*
13+
14+
*.iml

pom.xml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.github.scouter-project</groupId>
8+
<artifactId>scouter-plugin-server-alert-line</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13+
</properties>
14+
15+
<repositories>
16+
<repository>
17+
<id>scouter-repo</id>
18+
<name>scouter apm repository</name>
19+
<url>http://repository.scouterapm.com/artifactory/repository</url>
20+
</repository>
21+
</repositories>
22+
23+
<distributionManagement>
24+
<repository>
25+
<id>central</id>
26+
<name>scouter apm releases</name>
27+
<url>http://repository.scouterapm.com/artifactory/libs-release-local</url>
28+
</repository>
29+
30+
<snapshotRepository>
31+
<id>snapshots</id>
32+
<name>scouter apm snapshots</name>
33+
<url>http://repository.scouterapm.com/artifactory/libs-snapshot-local</url>
34+
</snapshotRepository>
35+
</distributionManagement>
36+
37+
<dependencies>
38+
<dependency>
39+
<groupId>com.github.scouter-project</groupId>
40+
<artifactId>scouter-server</artifactId>
41+
<version>1.1.1</version>
42+
</dependency>
43+
<dependency>
44+
<groupId>com.github.scouter-project</groupId>
45+
<artifactId>scouter-common</artifactId>
46+
<version>1.1.1</version>
47+
</dependency>
48+
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
49+
<dependency>
50+
<groupId>org.apache.httpcomponents</groupId>
51+
<artifactId>httpclient</artifactId>
52+
<version>4.5.2</version>
53+
</dependency>
54+
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
55+
<dependency>
56+
<groupId>org.apache.httpcomponents</groupId>
57+
<artifactId>httpcore</artifactId>
58+
<version>4.4.4</version>
59+
</dependency>
60+
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
61+
<dependency>
62+
<groupId>com.google.code.gson</groupId>
63+
<artifactId>gson</artifactId>
64+
<version>2.6.2</version>
65+
</dependency>
66+
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
67+
<dependency>
68+
<groupId>commons-logging</groupId>
69+
<artifactId>commons-logging</artifactId>
70+
<version>1.2</version>
71+
</dependency>
72+
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
73+
<dependency>
74+
<groupId>commons-codec</groupId>
75+
<artifactId>commons-codec</artifactId>
76+
<version>1.9</version>
77+
</dependency>
78+
<dependency>
79+
<groupId>junit</groupId>
80+
<artifactId>junit</artifactId>
81+
<version>4.12</version>
82+
<scope>test</scope>
83+
</dependency>
84+
<dependency>
85+
<groupId>org.assertj</groupId>
86+
<artifactId>assertj-core</artifactId>
87+
<version>2.3.0</version>
88+
<scope>test</scope>
89+
</dependency>
90+
<dependency>
91+
<groupId>org.mockito</groupId>
92+
<artifactId>mockito-all</artifactId>
93+
<version>1.10.8</version>
94+
<scope>test</scope>
95+
</dependency>
96+
</dependencies>
97+
98+
</project>
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
/*
2+
* Copyright 2016 Scouter Project.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* @author Sang-Cheon Park
17+
*/
18+
package scouter.plugin.server.alert.line;
19+
20+
import com.google.gson.Gson;
21+
import org.apache.http.HttpResponse;
22+
import org.apache.http.HttpStatus;
23+
import org.apache.http.client.methods.HttpPost;
24+
import org.apache.http.entity.StringEntity;
25+
import org.apache.http.impl.client.CloseableHttpClient;
26+
import org.apache.http.impl.client.HttpClientBuilder;
27+
import org.apache.http.util.EntityUtils;
28+
import scouter.lang.AlertLevel;
29+
import scouter.lang.TextTypes;
30+
import scouter.lang.TimeTypeEnum;
31+
import scouter.lang.counters.CounterConstants;
32+
import scouter.lang.pack.AlertPack;
33+
import scouter.lang.pack.ObjectPack;
34+
import scouter.lang.pack.PerfCounterPack;
35+
import scouter.lang.pack.XLogPack;
36+
import scouter.lang.plugin.PluginConstants;
37+
import scouter.lang.plugin.annotation.ServerPlugin;
38+
import scouter.server.Configure;
39+
import scouter.server.CounterManager;
40+
import scouter.server.Logger;
41+
import scouter.server.core.AgentManager;
42+
import scouter.server.db.TextRD;
43+
import scouter.util.DateUtil;
44+
import scouter.util.HashUtil;
45+
46+
import java.util.ArrayList;
47+
import java.util.List;
48+
49+
/**
50+
* Scouter server plugin to send alert via line
51+
*
52+
* @author Gun Lee ([email protected]) on 2016. 12. 20.
53+
* @author original Sang-Cheon Park([email protected])
54+
*/
55+
public class LinePlugin {
56+
57+
// Get singleton Configure instance from server
58+
Configure conf = Configure.getInstance();
59+
60+
private static List<Integer> javaeeObjHashList = new ArrayList<Integer>();
61+
62+
@ServerPlugin(PluginConstants.PLUGIN_SERVER_ALERT)
63+
public void alert(final AlertPack pack) {
64+
if (conf.getBoolean("ext_plugin_line_send_alert", false)) {
65+
66+
// Get log level (0 : INFO, 1 : WARN, 2 : ERROR, 3 : FATAL)
67+
int level = conf.getInt("ext_plugin_line_level", 0);
68+
69+
if (level <= pack.level) {
70+
new Thread() {
71+
public void run() {
72+
try {
73+
// Get server configurations for line
74+
String token = conf.getValue("ext_plugin_line_access_token");
75+
String chatId = conf.getValue("ext_plugin_line_group_id");
76+
77+
assert token != null;
78+
assert chatId != null;
79+
80+
// Make a request URL using telegram bot api
81+
String url = "https://api.line.me/v2/bot/message/push";
82+
83+
// Get the agent Name
84+
String name = AgentManager.getAgentName(pack.objHash) == null ? "N/A" : AgentManager.getAgentName(pack.objHash);
85+
86+
if (name.equals("N/A") && pack.message.endsWith("connected.")) {
87+
int idx = pack.message.indexOf("connected");
88+
if (pack.message.indexOf("reconnected") > -1) {
89+
name = pack.message.substring(0, idx - 6);
90+
} else {
91+
name = pack.message.substring(0, idx - 4);
92+
}
93+
}
94+
95+
String title = pack.title;
96+
String msg = pack.message;
97+
if (title.equals("INACTIVE_OBJECT")) {
98+
title = "An object has been inactivated.";
99+
msg = pack.message.substring(0, pack.message.indexOf("OBJECT") - 1);
100+
}
101+
102+
// Make message contents
103+
String contents = "[TYPE] : " + pack.objType.toUpperCase() + "\n" +
104+
"[NAME] : " + name + "\n" +
105+
"[LEVEL] : " + AlertLevel.getName(pack.level) + "\n" +
106+
"[TITLE] : " + title + "\n" +
107+
"[MESSAGE] : " + msg;
108+
109+
LinePushFormat pushFormat = new LinePushFormat();
110+
pushFormat.setTo(chatId);
111+
pushFormat.addMessage(new StringMessage(contents));
112+
113+
String body = new Gson().toJson(pushFormat);
114+
115+
HttpPost post = new HttpPost(url);
116+
post.addHeader("Content-Type","application/json");
117+
post.addHeader("Authorization", "Bearer {" + token + "}");
118+
post.setEntity(new StringEntity(body));
119+
120+
CloseableHttpClient client = HttpClientBuilder.create().build();
121+
122+
// send the post request
123+
HttpResponse response = client.execute(post);
124+
125+
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
126+
println("Line message sent to [" + chatId + "] successfully.");
127+
} else {
128+
println("Line message sent failed. Verify below information.");
129+
println("[URL] : " + url);
130+
println("[Message] : " + body);
131+
println("[Reason] : " + EntityUtils.toString(response.getEntity(), "UTF-8"));
132+
}
133+
} catch (Exception e) {
134+
println("[Error] : " + e.getMessage());
135+
136+
if(conf._trace) {
137+
e.printStackTrace();
138+
}
139+
}
140+
}
141+
}.start();
142+
}
143+
}
144+
}
145+
146+
@ServerPlugin(PluginConstants.PLUGIN_SERVER_OBJECT)
147+
public void object(ObjectPack pack) {
148+
if (pack.version != null && pack.version.length() > 0) {
149+
AlertPack ap = null;
150+
ObjectPack op = AgentManager.getAgent(pack.objHash);
151+
152+
if (op == null && pack.wakeup == 0L) {
153+
// in case of new agent connected
154+
ap = new AlertPack();
155+
ap.level = AlertLevel.INFO;
156+
ap.objHash = pack.objHash;
157+
ap.title = "An object has been activated.";
158+
ap.message = pack.objName + " is connected.";
159+
ap.time = System.currentTimeMillis();
160+
161+
if (AgentManager.getAgent(pack.objHash) != null) {
162+
ap.objType = AgentManager.getAgent(pack.objHash).objType;
163+
} else {
164+
ap.objType = "scouter";
165+
}
166+
167+
alert(ap);
168+
} else if (op.alive == false) {
169+
// in case of agent reconnected
170+
ap = new AlertPack();
171+
ap.level = AlertLevel.INFO;
172+
ap.objHash = pack.objHash;
173+
ap.title = "An object has been activated.";
174+
ap.message = pack.objName + " is reconnected.";
175+
ap.time = System.currentTimeMillis();
176+
ap.objType = AgentManager.getAgent(pack.objHash).objType;
177+
178+
alert(ap);
179+
}
180+
// inactive state can be handled in alert() method.
181+
}
182+
}
183+
184+
@ServerPlugin(PluginConstants.PLUGIN_SERVER_XLOG)
185+
public void xlog(XLogPack pack) {
186+
try {
187+
int elapsedThreshold = conf.getInt("ext_plugin_elapsed_time_threshold", 0);
188+
189+
if (elapsedThreshold != 0 && pack.elapsed > elapsedThreshold) {
190+
String serviceName = TextRD.getString(DateUtil.yyyymmdd(pack.endTime), TextTypes.SERVICE, pack.service);
191+
192+
AlertPack ap = new AlertPack();
193+
194+
ap.level = AlertLevel.WARN;
195+
ap.objHash = pack.objHash;
196+
ap.title = "Elapsed time exceed a threshold.";
197+
ap.message = "[" + AgentManager.getAgentName(pack.objHash) + "] "
198+
+ pack.service + "(" + serviceName + ") "
199+
+ "elapsed time(" + pack.elapsed + " ms) exceed a threshold.";
200+
ap.time = System.currentTimeMillis();
201+
ap.objType = AgentManager.getAgent(pack.objHash).objType;
202+
203+
alert(ap);
204+
}
205+
206+
} catch (Exception e) {
207+
Logger.printStackTrace(e);
208+
}
209+
}
210+
211+
@ServerPlugin(PluginConstants.PLUGIN_SERVER_COUNTER)
212+
public void counter(PerfCounterPack pack) {
213+
String objName = pack.objName;
214+
int objHash = HashUtil.hash(objName);
215+
String objType = null;
216+
String objFamily = null;
217+
218+
if (AgentManager.getAgent(objHash) != null) {
219+
objType = AgentManager.getAgent(objHash).objType;
220+
}
221+
222+
if (objType != null) {
223+
objFamily = CounterManager.getInstance().getCounterEngine().getObjectType(objType).getFamily().getName();
224+
}
225+
226+
try {
227+
// in case of objFamily is javaee
228+
if (CounterConstants.FAMILY_JAVAEE.equals(objFamily)) {
229+
// save javaee type's objHash
230+
if (!javaeeObjHashList.contains(objHash)) {
231+
javaeeObjHashList.add(objHash);
232+
}
233+
234+
if (pack.timetype == TimeTypeEnum.REALTIME) {
235+
long gcTimeThreshold = conf.getLong("ext_plugin_gc_time_threshold", 0);
236+
long gcTime = pack.data.getLong(CounterConstants.JAVA_GC_TIME);
237+
238+
if (gcTimeThreshold != 0 && gcTime > gcTimeThreshold) {
239+
AlertPack ap = new AlertPack();
240+
241+
ap.level = AlertLevel.WARN;
242+
ap.objHash = objHash;
243+
ap.title = "GC time exceed a threshold.";
244+
ap.message = objName + "'s GC time(" + gcTime + " ms) exceed a threshold.";
245+
ap.time = System.currentTimeMillis();
246+
ap.objType = objType;
247+
248+
alert(ap);
249+
}
250+
}
251+
}
252+
} catch (Exception e) {
253+
Logger.printStackTrace(e);
254+
}
255+
}
256+
257+
private void println(Object o) {
258+
if (conf.getBoolean("ext_plugin_line_debug", false)) {
259+
Logger.println(o);
260+
}
261+
}
262+
}

0 commit comments

Comments
 (0)