Containerization feature of SO
[so.git] / common / src / main / java / org / onap / so / logger / MsoAlarmLogger.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.logger;
22
23
24 import java.io.File;
25
26 import javax.servlet.ServletContextEvent;
27 import javax.servlet.ServletContextListener;
28
29 import org.slf4j.LoggerFactory;
30
31 import ch.qos.logback.classic.Level;
32 import ch.qos.logback.classic.Logger;
33 import ch.qos.logback.classic.LoggerContext;
34 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
35 import ch.qos.logback.classic.spi.ILoggingEvent;
36 import ch.qos.logback.core.rolling.RollingFileAppender;
37 import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
38
39 /**
40  * Wrapper around log4j and Nagios NRDP passive alarming for MSO.
41  *
42  * For local alarm logging, this class will look for an alarm log file name
43  * in the servlet context parameter "mso.alarms.file". If none is found,
44  * it will look for an MsoProperty of the same name. As a last resort,
45  * it will use the default path "/var/log/ecomp/MSO/alarms/alarm.log".
46  * It is expected that all alarms within an application will use the same
47  * alarm file, so there is no way to dynamically add other alarm files.
48  *
49  * Alarms are logged as a simple pipe-delimited string of the format:
50  * <dateTime>|<alarmType>|<state>|<detailMessage>
51  *
52  * This class also supports real-time Nagios NRDP alarming. If enabled via
53  * MsoProperties, all alarms generated and logged to the local alarm file will
54  * also be transmitted to a Nagios NRDP instance. NRDP requires 4 parameters
55  * in service alarm events (all Mso Alarms will be Service Alarms):
56  * hostname, servicename, state, detail
57  *
58  * The log file format is also intended to be compatible with Nagios NRDP for
59  * non-real-time reporting. The command-line tool for sending alarms is
60  * is "send_nrdp.php", which takes the same 4 parameters as input.
61  * It will be easy enough to translate entries from an alarm.log file to
62  * NRDP if real-time NRDP alarming is not enabled.
63  *
64  * For Nagios integration, the alarmTypes should all match "service names"
65  * configured in the receiving Nagios server. Also, the alarm state will
66  * be limited to the 4 values defined by Nagios:
67  * 0 = OK, 1 = Warning, 2 = Critical, 3 = Unknown
68  *
69  *
70  */
71 public class MsoAlarmLogger implements ServletContextListener {
72
73         private Logger alarmLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(MSO_ALARM_CONTEXT);
74     private static RollingFileAppender<ILoggingEvent> fileAppender = null;
75     public static final String DEFAULT_MSO_ALARM_FILE = "/var/log/ecomp/MSO/alarms/alarm.log";
76     public static final String MSO_ALARM_CONTEXT = "mso.alarms";
77     
78     public static final int OK = 0;
79     public static final int WARNING = 1;
80     public static final int CRITICAL = 2;
81     public static final int UNKNOWN = 3;
82
83     /**
84      * Get the default MSO Alarm Logger
85      */
86     public MsoAlarmLogger () {
87                 
88         initializeAlarmLogger(null);
89
90     }
91
92     public MsoAlarmLogger (String alarmFile) {
93         initializeAlarmLogger(alarmFile);
94
95     }
96
97      /**
98      * Method to record an alarm.
99      *
100      * @param alarm - the alarm identifier (Nagios "service")
101      * @param state - the alarm state/severity, based on Nagios service
102      *        state values: 0 = OK, 1 = Warning, 2 = Critical, 3 = Unknown
103      * @param detail - detail message (may contain additional internal
104      *        structure per alarm type)
105      */
106     public void sendAlarm (String alarm, int state, String detail) {
107         // Write the alarm to Log file
108         if (alarmLogger != null) {
109             String output = alarm + "|" + state + "|" + detail;
110             alarmLogger.info (output);
111         }
112
113     }
114
115     @Override
116     public void contextDestroyed (ServletContextEvent event) {
117         // Nothing to do...
118     }
119
120     @Override
121     public void contextInitialized (ServletContextEvent event) {
122         String msoAlarmFile = event.getServletContext ().getInitParameter ("mso.alarm.file");
123         if (msoAlarmFile == null) {
124             msoAlarmFile = DEFAULT_MSO_ALARM_FILE;
125         }
126
127         initializeAlarmLogger (msoAlarmFile);
128     }
129
130     private void initializeAlarmLogger (String alarmFile) {
131         synchronized (MsoAlarmLogger.class) {
132             if (fileAppender == null) {
133                 if (alarmFile != null) {
134                         fileAppender = MsoAlarmLogger.getAppender (alarmFile);
135                 } else {
136                         fileAppender = MsoAlarmLogger.getAppender (DEFAULT_MSO_ALARM_FILE);
137                 }
138             }
139         }
140         // The alarmLogger was static originally.
141         // The initialization of the alarmLogger was fine, but not sure why, it lost its appender info later
142         // Due to that issue, the alarmLogger is not static any more.
143         // Instead static attribute fileAppender is added and will be assigned to the alarmLogger every time new MsoAlarmLogger is created.
144         alarmLogger.setLevel (Level.INFO);
145         alarmLogger.addAppender (fileAppender);
146         alarmLogger.setAdditive (false);
147     }
148
149     public void resetAppender() {
150         synchronized (MsoAlarmLogger.class) {
151                 fileAppender = null;
152         }
153     }
154
155     private static RollingFileAppender<ILoggingEvent> getAppender (String msoAlarmFile) {
156         // Create a Logger for alarms. Just use a default Pattern that outputs
157         // a message. MsoAlarmLogger will handle the formatting.
158         File alarmFile = new File (msoAlarmFile);
159         File alarmDir = alarmFile.getParentFile ();
160         if (!alarmDir.exists ()) {
161             alarmDir.mkdirs ();
162         }
163
164         String logPattern = "%d{yyyy-MM-dd HH:mm:ss}|%m%n";
165
166         LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
167         PatternLayoutEncoder encoder=new PatternLayoutEncoder();
168         encoder.setPattern(logPattern);
169         encoder.setContext(context);
170         encoder.start();
171         RollingFileAppender<ILoggingEvent> fileAppender= new RollingFileAppender<>();
172         TimeBasedRollingPolicy<ILoggingEvent> rollingPolicy= new TimeBasedRollingPolicy<>();
173         rollingPolicy.setContext(context);
174         rollingPolicy.setFileNamePattern(msoAlarmFile + ".%d");
175         rollingPolicy.setParent(fileAppender);
176         rollingPolicy.start();
177         fileAppender.setFile(msoAlarmFile);
178         fileAppender.setAppend(true);
179         fileAppender.setEncoder(encoder);
180         fileAppender.setRollingPolicy(rollingPolicy);
181         fileAppender.setContext(context);
182         fileAppender.start();
183
184         return fileAppender;
185     }
186
187 }