summaryrefslogtreecommitdiff
path: root/src/com/nis/nmsclient/thread/alarm/AlarmThread.java
blob: 41d989aedff39893a73090202d23bafb67fe4cb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
package com.nis.nmsclient.thread.alarm;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.nis.nmsclient.common.Common;
import com.nis.nmsclient.common.Contants;
import com.nis.nmsclient.config.DetecConfOper;
import com.nis.nmsclient.util.DateUtil;
import com.nis.nmsclient.util.FileUtil;
import com.nis.nmsclient.util.ProcessUtil;
import com.nis.nmsclient.util.Utils;

/**
 * 主动报警线程:针对当前所有有效监测设置进行主动报警
 *    定时监测某设置是否正常生成数据,N次未取到数据后向Server报警,恢复正常后向Server发送提示信息
 * @date Mar 22, 2012
 * @author zhenzhen
 * @version
 */
public class AlarmThread implements Runnable{
	Logger logger = Logger.getLogger(AlarmThread.class);
	private String name;
	
	private Map<Long, AlarmStateMsg> alarmSmMap = new HashMap<Long, AlarmStateMsg>();
	
	public AlarmThread(String name) {
		super();
		this.name = name;
	}
	
	public void run() {
		Thread.currentThread().setName(name);
		
		logger.debug("主动预警检查开始 ~~~~~~~");
		try{
			Map<Long, AlarmPO> alarmPOs = new HashMap<Long, AlarmPO>(Common
					.getAlarmPOs());
			// 清除垃圾数据
			if (alarmSmMap.size() > alarmPOs.size()) {
				Iterator<Long> it = alarmSmMap.keySet().iterator();
				while (it.hasNext()) {
					Long key = it.next();
					if(!alarmPOs.containsKey(key)){
						//alarmSmMap.remove(key);
						it.remove();//update by jinsj for 2013-07-08 java.util.ConcurrentModificationException
					}
				}

			}
			Set<Map.Entry<Long, AlarmPO>> entrys = alarmPOs.entrySet();
			int alarmCnt = 0;
			StringBuffer alarmDescInfo = new StringBuffer();
			for (Map.Entry<Long, AlarmPO> entry : entrys) {
				// 如果监测进程未启动,则不进行告警检查
				if (entry.getValue().getControlStartTime() != null
						&& entry.getValue().getControlStartTime() > System
								.currentTimeMillis()) {
					continue;
				}
				// 对各监测设置告警状态信息进行赋初值
				Long key = entry.getValue().getId();
				if (alarmSmMap.get(key) == null) {
					alarmSmMap.put(key, new AlarmStateMsg(new Date(), 0,
							new StringBuffer(), false));
				}else if(alarmSmMap.get(key).getAlarmMsg().length() == 0){
					alarmSmMap.get(key).setStart(new Date());
				}

				boolean flag = alarm(entry.getValue());
				if(flag){
					alarmCnt += 1;
					alarmDescInfo.append("\tsetId: " + key + " >> " + entry.getValue().getType() + "_" + entry.getValue().getProcIden());
					alarmDescInfo.append("\n");
				}
			}
			logger.info("本次预警轮循检查监测设置总数:" + alarmPOs.size() + ",正常:"
					+ (alarmPOs.size() - alarmCnt) + ",不正常:" + alarmCnt);
			if(alarmCnt>0){
				logger.info("本次预警检查不正常的监测如下:\n" + alarmDescInfo.toString());
			}
		}catch (Exception e) {
			logger.error("Active early warning thread exception:" + Utils.printExceptionStack(e));
		}
		logger.debug("主动预警检查结束 ~~~~~~~");
	}
	
	/**
	 * 针对一个监测设置的主动预警具体逻辑实现
	 * @param alarm
	 * @return true 告警监测不正常 false 监测正常
	 * @throws Exception
	 */
	public boolean alarm(AlarmPO alarm) throws Exception{
		Long key = alarm.getId();
		String sonDirName = DetecConfOper.getFileName(alarm.getType(), alarm.getProcIden(), null);
		StringBuffer sbMsg = new StringBuffer();
		/**
		 * 1、检查是否存在数据: alarmLevel 0 -- 数据存在,非0 -- 数据不存在 
		 */
		int alarmLevel = checkDataIsExist(sonDirName, alarm.getCheckGap(), sbMsg);
		
		/**
		 * 2、判断进程是否存在:是进程且数据不存在才判断,不是进程如系统类型CPU,则不进行这些操作
		 */
		if(alarmLevel!=0 && alarm.isIsproc()){
			if("2".equals(alarm.getIsControlStart())) { // NC周期启动(脚本间断性执行且执行时间较短,通过判断Java定时任务确认进程)
				if(Common.containPluginDetecFuture(key)){ // 进程存在
					String temp = sbMsg.toString();
					sbMsg.delete(0, sbMsg.length());
//					sbMsg.append("进程存在,但" + temp);
					sbMsg.append("i18n_client.AlarmThread.processExists_n81i" + temp);
					alarmLevel = 2;
				} else { // 进程不存在
					sbMsg.delete(0, sbMsg.length());
//					sbMsg.append("定时任务“" + alarm.getType() + "”不存在");
					sbMsg.append("i18n_client.AlarmThread.loopMission1_n81i“" + alarm.getType() + "”i18n_client.AlarmThread.loopMission2_n81i");
					alarmLevel = 1;
				}
			} else {
				Object[] objArr = ProcessUtil.checkPidAndGetPid(alarm.getPidFileStr(), alarm.getProcessSearchKeyCode());
				int isExistFlag = Integer.parseInt(objArr[0].toString());
				String pidInfo = objArr[1].toString();
				
				if(isExistFlag==0){// 进程不存在(包括PID文件不存在,PID值不存在,搜索关键字也找不到进程)
					sbMsg.delete(0, sbMsg.length());
					sbMsg.append(pidInfo);
					alarmLevel = 1;
				} else {// 进程存在(一个进程或多个进程)
					String temp = sbMsg.toString();
					sbMsg.delete(0, sbMsg.length());
//					sbMsg.append("进程存在,但" + temp);
					sbMsg.append("i18n_client.AlarmThread.processExists_n81i" + temp);
					alarmLevel = 2;
				}
			}
		}
		
		/**
		 * 3、统计并发送报警信息
		 */
		AlarmStateMsg asMsg= alarmSmMap.get(key);
		int times = asMsg.getTimes();
		boolean flag = true;
		if (sbMsg.length()>0 && sbMsg.toString().equals(asMsg.getAlarmMsg().toString())) {
			times ++ ;
			
			if (times == Contants.noDataTimes) {// Contants.noDataTime次未取到数据,报警
				AlarmUtil.sendAlarmMsg(alarm, asMsg.getStart(), new Date(),
						alarmLevel, Contants.DETECTION_STATUS_ABNORMAL, asMsg
								.getAlarmMsg().toString()
//								+ ",此状态持续了" + times + "次");
								+ ",i18n_client.AlarmThread.state_n81i" + times + "i18n_client.AlarmThread.times_n81i");
				asMsg.setAlarmState(true);
			}
		} else if (sbMsg.length() > 0
				&& !sbMsg.toString().equals(asMsg.getAlarmMsg().toString())) {
			asMsg.getAlarmMsg().delete(0, asMsg.getAlarmMsg().length());
			asMsg.getAlarmMsg().append(sbMsg.toString());
			times = 1;
		} else {
			asMsg.getAlarmMsg().delete(0, asMsg.getAlarmMsg().length());
			times = 0;
			if(asMsg.isAlarmState()){
				/*AlarmUtil.sendAlarmMsg(alarm, asMsg.getStart(), new Date(),
						99, Contants.DETECTION_STATUS_NORMAL, "恢复正常");*/
				asMsg.setAlarmState(false);
			}
			flag = false;
		}
		asMsg.setTimes(times);
		alarmSmMap.put(key, asMsg);
		
		return flag;
	}
	
	/**
	 * 检查是否存在数据
	 * @param sonDirName
	 * @param checkGap
	 * @return
	 */
	private int checkDataIsExist(String sonDirName, long checkGap, StringBuffer sbMsg){
		int alarmLevel = 0;
		// ------- 1、先查看当前正在写入的数据文件夹
		File curDir = new File(Contants.localDataFilePath + File.separator + sonDirName);
		if(!curDir.exists()){
//			sbMsg.append("数据文件目录“" + curDir.getAbsolutePath() + "”不存在");
			sbMsg.append("i18n_client.AlarmThread.dataFileNotExists1_n81i“" + curDir.getAbsolutePath() + "”i18n_client.AlarmThread.dataFileNotExists2_n81i");
			alarmLevel = 1;
			return alarmLevel;
		}
		long timeMillis = System.currentTimeMillis() - Contants.noDataTimes * checkGap * 60 * 1000; 
		File[] rightFiles = FileUtil.getFilesAfterMillis(curDir, timeMillis);
		if(rightFiles!=null && rightFiles.length>0){// 找到数据,正常
			alarmLevel = 0;
			return alarmLevel;
		}
		
		// -------- 2、如果当前正在写入的数据文件夹没有找到符合条件的数据,则查找上传成功后备份到的相应目录
		// 2013-3-28 修改内容:原本只检查当天日期目录是否存在数据,针对监测时间间隔超过一天的存在问题,所以当间隔时间大于等于一天时,改为检查当天日期之前的目录
		String dateDirName = DateUtil.getCurrentDate(DateUtil.YYYYMMDD);
		File doneDir = new File(Contants.localDataDonePath + File.separator + sonDirName);
		if(doneDir.exists()){
			if(checkGap >= 1440){// --- 检查当天日期及之前的目录
				// 找到指定的日期目录及之前的日期目录,将其降序排列,是为了最先查找当天日期
				File[] dateDirs = FileUtil.sortDescByFileName(FileUtil.getDirsBeforeDateName(doneDir, dateDirName));
				// 在找到的日期目录下检查文件是否存在
				for(File dateDir : dateDirs){
					rightFiles = FileUtil.getFilesAfterMillis(dateDir, timeMillis);
					if(rightFiles!=null && rightFiles.length>0){// 在任一目录找到则不再继续查找其他目录
						break;
					}
				}
			}else {// --- 只检查当天日期
				File dateDir = new File(doneDir.getAbsolutePath() + File.separator + dateDirName);
				if(dateDir.exists()){
					rightFiles = FileUtil.getFilesAfterMillis(dateDir, timeMillis);
				}
			}
		}
		if(rightFiles!=null && rightFiles.length>0){// 找到数据,正常
			alarmLevel = 0;
			return alarmLevel;
		}
		
		// -------- 3、查找不完整数据即0大小文件备份到的相应目录
		File[] errorFiles = null;
		File errorDir = new File(Contants.localDataErrorPath + File.separator + sonDirName);
		if(errorDir.exists()){
			if(checkGap >= 1440){// --- 检查当天日期及之前的目录
				// 找到指定的日期目录及之前的日期目录,将其降序排列,是为了最先查找当天日期
				File[] dateDirs = FileUtil.sortDescByFileName(FileUtil.getDirsBeforeDateName(errorDir, dateDirName));
				// 在找到的日期目录下检查文件是否存在
				for(File dateDir : dateDirs){
					errorFiles = FileUtil.getFilesAfterMillis(dateDir, timeMillis);
					if(errorFiles!=null && errorFiles.length>0){// 在任一目录找到则不再继续查找其他目录
						break;
					}
				}
			}else {// --- 只检查当天日期
				File dateDir = new File(doneDir.getAbsolutePath() + File.separator + dateDirName);
				if(dateDir.exists()){
					errorFiles = FileUtil.getFilesAfterMillis(errorDir, timeMillis);
				}
			}
			
		}
		if(errorFiles!=null && errorFiles.length>0){
//			sbMsg.append("监测数据文件大小为0");
			sbMsg.append("i18n_client.AlarmThread.dataSize_n81i");
			alarmLevel = 1;
		}else{
//			sbMsg.append("未取到监测数据");
			sbMsg.append("i18n_client.AlarmThread.noDetecateData_n81i");
			alarmLevel = 1;
		}
		
		return alarmLevel;
	}
	
	/**
	 * 告警检查过程中针对每个监测设置的过程变量状态的封装类
	 * @date Mar 22, 2012
	 * @author zhenzhen
	 * @version
	 */
	class AlarmStateMsg {
		private Date start;//告警检查不正常情况的开始时间
		private Integer times;//连续告警次数
		private StringBuffer alarmMsg;//告警信息
		private boolean alarmState;//是否向Server发送了主动告警请求
		
		public AlarmStateMsg(Date start, Integer times, StringBuffer alarmMsg,
				boolean alarmState) {
			super();
			this.start = start;
			this.times = times;
			this.alarmMsg = alarmMsg;
			this.alarmState = alarmState;
		}
		
		public Date getStart() {
			return start;
		}
		public void setStart(Date start) {
			this.start = start;
		}
		public Integer getTimes() {
			return times;
		}
		public void setTimes(Integer times) {
			this.times = times;
		}
		public StringBuffer getAlarmMsg() {
			return alarmMsg;
		}
		public void setAlarmMsg(StringBuffer alarmMsg) {
			this.alarmMsg = alarmMsg;
		}
		public boolean isAlarmState() {
			return alarmState;
		}
		public void setAlarmState(boolean alarmState) {
			this.alarmState = alarmState;
		}
	}
	
}