cf3b29a55c6e8b10dec3cb99598717a525c7e6c3
[dmaap/datarouter.git] / datarouter-node / src / main / java / org / onap / dmaap / datarouter / node / LogManager.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.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileReader;
31 import java.io.FileWriter;
32 import java.io.Writer;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.util.Arrays;
36 import java.util.TimerTask;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
39 import org.jetbrains.annotations.NotNull;
40
41 /**
42  * Cleanup of old log files.
43  *
44  * <p>Periodically scan the log directory for log files that are older than the log file retention interval, and delete
45  * them.  In a future release, This class will also be responsible for uploading events logs to the log server to
46  * support the log query APIs.
47  */
48
49 public class LogManager extends TimerTask {
50
51     private static final String EXCEPTION = "Exception";
52     private EELFLogger logger = EELFManager.getInstance().getLogger(LogManager.class);
53     private NodeConfigManager config;
54     private Matcher isnodelog;
55     private Matcher iseventlog;
56     private Uploader worker;
57     private String uploaddir;
58     private String logdir;
59
60     /**
61      * Construct a log manager
62      *
63      * <p>The log manager will check for expired log files every 5 minutes at 20 seconds after the 5 minute boundary.
64      * (Actually, the interval is the event log rollover interval, which defaults to 5 minutes).
65      */
66     public LogManager(NodeConfigManager config) {
67         this.config = config;
68         try {
69             isnodelog = Pattern.compile("node\\.log\\.\\d{8}").matcher("");
70             iseventlog = Pattern.compile("events-\\d{12}\\.log").matcher("");
71         } catch (Exception e) {
72             logger.error(EXCEPTION, e);
73         }
74         logdir = config.getLogDir();
75         uploaddir = logdir + "/.spool";
76         (new File(uploaddir)).mkdirs();
77         long now = System.currentTimeMillis();
78         long intvl = StatusLog.parseInterval(config.getEventLogInterval(), 30000);
79         long when = now - now % intvl + intvl + 20000L;
80         config.getTimer().scheduleAtFixedRate(this, when - now, intvl);
81         worker = new Uploader();
82     }
83
84     /**
85      * Trigger check for expired log files and log files to upload.
86      */
87     public void run() {
88         worker.poke();
89     }
90
91     public Uploader getWorker() {
92         return worker;
93     }
94
95     class Uploader extends Thread implements DeliveryQueueHelper {
96
97         private static final String META = "/.meta";
98         private EELFLogger logger = EELFManager.getInstance().getLogger(Uploader.class);
99         private DeliveryQueue dq;
100
101         Uploader() {
102             dq = new DeliveryQueue(this,
103                     new DestInfoBuilder().setName("LogUpload").setSpool(uploaddir).setSubid(null).setLogdata(null)
104                             .setUrl(null).setAuthuser(config.getMyName()).setAuthentication(config.getMyAuth())
105                             .setMetaonly(false).setUse100(false).setPrivilegedSubscriber(false)
106                             .setFollowRedirects(false)
107                             .setDecompress(false).createDestInfo());
108             setDaemon(true);
109             setName("Log Uploader");
110             start();
111         }
112
113         public long getInitFailureTimer() {
114             return (10000L);
115         }
116
117         public long getWaitForFileProcessFailureTimer() {
118             return (600000L);
119         }
120
121         public double getFailureBackoff() {
122             return (2.0);
123         }
124
125         public long getMaxFailureTimer() {
126             return (150000L);
127         }
128
129         public long getExpirationTimer() {
130             return (604800000L);
131         }
132
133         public int getFairFileLimit() {
134             return (10000);
135         }
136
137         public long getFairTimeLimit() {
138             return (86400000);
139         }
140
141         public String getDestURL(DestInfo destinationInfo, String fileid) {
142             return (config.getEventLogUrl());
143         }
144
145         public void handleUnreachable(DestInfo destinationInfo) {
146             throw new UnsupportedOperationException();
147         }
148
149         public boolean handleRedirection(DestInfo destinationInfo, String location, String fileid) {
150             return (false);
151         }
152
153         public boolean isFollowRedirects() {
154             return (false);
155         }
156
157         public String getFeedId(String subid) {
158             return (null);
159         }
160
161         private synchronized void snooze() {
162             try {
163                 wait(10000);
164             } catch (Exception e) {
165                 logger.error(EXCEPTION, e);
166             }
167         }
168
169         private synchronized void poke() {
170             notify();
171         }
172
173         @Override
174         public void run() {
175             while (true) {
176                 scan();
177                 dq.run();
178                 snooze();
179             }
180         }
181
182         private void scan() {
183             long threshold = System.currentTimeMillis() - config.getLogRetention();
184             File dir = new File(logdir);
185             String[] fns = dir.list();
186             Arrays.sort(fns);
187             String lastqueued = "events-000000000000.log";
188             String curlog = StatusLog.getCurLogFile();
189             curlog = curlog.substring(curlog.lastIndexOf('/') + 1);
190             try {
191                 Writer writer = new FileWriter(uploaddir + META);
192                 writer.write("POST\tlogdata\nContent-Type\ttext/plain\n");
193                 writer.close();
194                 BufferedReader br = new BufferedReader(new FileReader(uploaddir + "/.lastqueued"));
195                 lastqueued = br.readLine();
196                 br.close();
197             } catch (Exception e) {
198                 logger.error(EXCEPTION, e);
199             }
200             for (String fn : fns) {
201                 if (!isnodelog.reset(fn).matches()) {
202                     if (!iseventlog.reset(fn).matches()) {
203                         continue;
204                     }
205                     lastqueued = setLastQueued(lastqueued, curlog, fn);
206                 }
207                 File file = new File(dir, fn);
208                 if (file.lastModified() < threshold) {
209                     file.delete();
210                 }
211             }
212             try (Writer w = new FileWriter(uploaddir + "/.lastqueued")) {
213                 (new File(uploaddir + META)).delete();
214                 w.write(lastqueued + "\n");
215             } catch (Exception e) {
216                 logger.error(EXCEPTION, e);
217             }
218         }
219
220         @NotNull
221         private String setLastQueued(String lastqueued, String curlog, String fn) {
222             if (lastqueued.compareTo(fn) < 0 && curlog.compareTo(fn) > 0) {
223                 lastqueued = fn;
224                 try {
225                     String pid = config.getPublishId();
226                     Files.createLink(Paths.get(uploaddir + "/" + pid), Paths.get(logdir + "/" + fn));
227                     Files.createLink(Paths.get(uploaddir + "/" + pid + ".M"), Paths.get(uploaddir + META));
228                 } catch (Exception e) {
229                     logger.error(EXCEPTION, e);
230                 }
231             }
232             return lastqueued;
233         }
234     }
235 }