Remove datarouter-node critical code smells
[dmaap/datarouter.git] / datarouter-node / src / main / java / org / onap / dmaap / datarouter / node / StatusLog.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 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  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24 package org.onap.dmaap.datarouter.node;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFManager;
28 import java.util.regex.*;
29 import java.util.*;
30 import java.io.*;
31 import java.nio.file.*;
32 import java.text.*;
33
34 /**
35  * Logging for data router delivery events (PUB/DEL/EXP)
36  */
37 public class StatusLog {
38     private static EELFLogger eelfLogger = EELFManager.getInstance().getLogger(StatusLog.class);
39     private static StatusLog instance = new StatusLog();
40     private HashSet<String> toship = new HashSet<String>();
41     private SimpleDateFormat filedate;
42     private String prefix = "logs/events";
43     private String suffix = ".log";
44     private String plainfile;
45     private String curfile;
46     private long nexttime;
47     private OutputStream os;
48     private long intvl;
49     private NodeConfigManager config = NodeConfigManager.getInstance();
50
51     {
52         try {
53             filedate = new SimpleDateFormat("-yyyyMMddHHmm");
54         } catch (Exception e) {
55             eelfLogger.error("Exception", e);
56         }
57     }
58
59     /**
60      * Parse an interval of the form xxhyymzzs and round it to the nearest whole fraction of 24 hours.If no units are specified, assume seconds.
61      */
62     public static long parseInterval(String interval, int def) {
63         try {
64             Matcher m = Pattern.compile("(?:(\\d+)[Hh])?(?:(\\d+)[Mm])?(?:(\\d+)[Ss]?)?").matcher(interval);
65             if (m.matches()) {
66                 int dur = 0;
67                 String x = m.group(1);
68                 if (x != null) {
69                     dur += 3600 * Integer.parseInt(x);
70                 }
71                 x = m.group(2);
72                 if (x != null) {
73                     dur += 60 * Integer.parseInt(x);
74                 }
75                 x = m.group(3);
76                 if (x != null) {
77                     dur += Integer.parseInt(x);
78                 }
79                 if (dur < 60) {
80                     dur = 60;
81                 }
82                 int best = 86400;
83                 int dist = best - dur;
84                 if (dur > best) {
85                     dist = dur - best;
86                 }
87                 int base = 1;
88                 for (int i = 0; i < 8; i++) {
89                     int base2 = base;
90                     base *= 2;
91                     for (int j = 0; j < 4; j++) {
92                         int base3 = base2;
93                         base2 *= 3;
94                         for (int k = 0; k < 3; k++) {
95                             int cur = base3;
96                             base3 *= 5;
97                             int ndist = cur - dur;
98                             if (dur > cur) {
99                                 ndist = dur - cur;
100                             }
101                             if (ndist < dist) {
102                                 best = cur;
103                                 dist = ndist;
104                             }
105                         }
106                     }
107                 }
108                 def = best * 1000;
109             }
110         } catch (Exception e) {
111             eelfLogger.error("Exception", e);
112         }
113         return (def);
114     }
115
116     private synchronized void checkRoll(long now) throws IOException {
117         if (now >= nexttime) {
118             if (os != null) {
119                 os.close();
120                 os = null;
121             }
122             intvl = parseInterval(config.getEventLogInterval(), 300000);
123             prefix = config.getEventLogPrefix();
124             suffix = config.getEventLogSuffix();
125             nexttime = now - now % intvl + intvl;
126             curfile = prefix + filedate.format(new Date(nexttime - intvl)) + suffix;
127             plainfile = prefix + suffix;
128             notify();
129         }
130     }
131
132     /**
133      * Get the name of the current log file
134      *
135      * @return The full path name of the current event log file
136      */
137     public static synchronized String getCurLogFile() {
138         try {
139             instance.checkRoll(System.currentTimeMillis());
140         } catch (Exception e) {
141             eelfLogger.error("Exception", e);
142         }
143         return (instance.curfile);
144     }
145
146     private synchronized void log(String s) {
147         try {
148             long now = System.currentTimeMillis();
149             checkRoll(now);
150             if (os == null) {
151                 os = new FileOutputStream(curfile, true);
152                 (new File(plainfile)).delete();
153                 Files.createLink(Paths.get(plainfile), Paths.get(curfile));
154             }
155             os.write((NodeUtils.logts(new Date(now)) + '|' + s + '\n').getBytes());
156             os.flush();
157         } catch (IOException ioe) {
158             eelfLogger.error("IOException", ioe);
159         }
160     }
161
162     /**
163      * Log a received publication attempt.
164      *
165      * @param pubid  The publish ID assigned by the node
166      * @param feedid The feed id given by the publisher
167      * @param requrl The URL of the received request
168      * @param method The method (DELETE or PUT) in the received request
169      * @param ctype  The content type (if method is PUT and clen > 0)
170      * @param clen   The content length (if method is PUT)
171      * @param srcip  The IP address of the publisher
172      * @param user   The identity of the publisher
173      * @param status The status returned to the publisher
174      */
175     public static void logPub(String pubid, String feedid, String requrl, String method, String ctype, long clen, String srcip, String user, int status) {
176         instance.log("PUB|" + pubid + "|" + feedid + "|" + requrl + "|" + method + "|" + ctype + "|" + clen + "|" + srcip + "|" + user + "|" + status);
177     }
178
179     /**
180      * Log a data transfer error receiving a publication attempt
181      *
182      * @param pubid  The publish ID assigned by the node
183      * @param feedid The feed id given by the publisher
184      * @param requrl The URL of the received request
185      * @param method The method (DELETE or PUT) in the received request
186      * @param ctype  The content type (if method is PUT and clen > 0)
187      * @param clen   The expected content length (if method is PUT)
188      * @param rcvd   The content length received
189      * @param srcip  The IP address of the publisher
190      * @param user   The identity of the publisher
191      * @param error  The error message from the IO exception
192      */
193     public static void logPubFail(String pubid, String feedid, String requrl, String method, String ctype, long clen, long rcvd, String srcip, String user, String error) {
194         instance.log("PBF|" + pubid + "|" + feedid + "|" + requrl + "|" + method + "|" + ctype + "|" + clen + "|" + rcvd + "|" + srcip + "|" + user + "|" + error);
195     }
196
197     /**
198      * Log a delivery attempt.
199      *
200      * @param pubid  The publish ID assigned by the node
201      * @param feedid The feed ID
202      * @param subid  The (space delimited list of) subscription ID
203      * @param requrl The URL used in the attempt
204      * @param method The method (DELETE or PUT) in the attempt
205      * @param ctype  The content type (if method is PUT, not metaonly, and clen > 0)
206      * @param clen   The content length (if PUT and not metaonly)
207      * @param user   The identity given to the subscriber
208      * @param status The status returned by the subscriber or -1 if an exeception occured trying to connect
209      * @param xpubid The publish ID returned by the subscriber
210      */
211     public static void logDel(String pubid, String feedid, String subid, String requrl, String method, String ctype, long clen, String user, int status, String xpubid) {
212         if (feedid == null) {
213             return;
214         }
215         instance.log("DEL|" + pubid + "|" + feedid + "|" + subid + "|" + requrl + "|" + method + "|" + ctype + "|" + clen + "|" + user + "|" + status + "|" + xpubid);
216     }
217
218     /**
219      * Log delivery attempts expired
220      *
221      * @param pubid    The publish ID assigned by the node
222      * @param feedid   The feed ID
223      * @param subid    The (space delimited list of) subscription ID
224      * @param requrl   The URL that would be delivered to
225      * @param method   The method (DELETE or PUT) in the request
226      * @param ctype    The content type (if method is PUT, not metaonly, and clen > 0)
227      * @param clen     The content length (if PUT and not metaonly)
228      * @param reason   The reason the attempts were discontinued
229      * @param attempts The number of attempts made
230      */
231     public static void logExp(String pubid, String feedid, String subid, String requrl, String method, String ctype, long clen, String reason, int attempts) {
232         if (feedid == null) {
233             return;
234         }
235         instance.log("EXP|" + pubid + "|" + feedid + "|" + subid + "|" + requrl + "|" + method + "|" + ctype + "|" + clen + "|" + reason + "|" + attempts);
236     }
237
238     /**
239      * Log extra statistics about unsuccessful delivery attempts.
240      *
241      * @param pubid  The publish ID assigned by the node
242      * @param feedid The feed ID
243      * @param subid  The (space delimited list of) subscription ID
244      * @param clen   The content length
245      * @param sent   The # of bytes sent or -1 if subscriber returned an error instead of 100 Continue, otherwise, the number of bytes sent before an error occurred.
246      */
247     public static void logDelExtra(String pubid, String feedid, String subid, long clen, long sent) {
248         if (feedid == null) {
249             return;
250         }
251         instance.log("DLX|" + pubid + "|" + feedid + "|" + subid + "|" + clen + "|" + sent);
252     }
253
254     private StatusLog() {
255     }
256 }