1 /*
2  * Copyright (C) 2010 The Android Open Source 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 package com.android.tradefed.log;
17 
18 import com.android.tradefed.config.Option;
19 import com.android.tradefed.config.OptionClass;
20 import com.android.tradefed.config.OptionCopier;
21 import com.android.tradefed.result.ByteArrayInputStreamSource;
22 import com.android.tradefed.result.InputStreamSource;
23 import com.android.tradefed.result.SnapshotInputStreamSource;
24 import com.android.tradefed.util.SizeLimitedOutputStream;
25 import com.android.tradefed.util.StreamUtil;
26 
27 import com.google.common.annotations.VisibleForTesting;
28 
29 import java.io.IOException;
30 import java.io.InputStream;
31 
32 /** A {@link ILeveledLogOutput} that directs log messages to a file and to stdout. */
33 @OptionClass(alias = "file")
34 public class FileLogger extends BaseStreamLogger<SizeLimitedOutputStream> {
35     private static final String TEMP_FILE_PREFIX = "tradefed_log_";
36     private static final String TEMP_FILE_SUFFIX = ".txt";
37 
38     @Option(name = "max-log-size", description = "maximum allowable size of tmp log data in mB.")
39     private long mMaxLogSizeMbytes = 20;
40 
41     @Override
init()42     public void init() throws IOException {
43         init(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
44     }
45 
46     /**
47      * Alternative to {@link #init()} where we can specify the file name and suffix.
48      *
49      * @param logPrefix the file name where to log without extension.
50      * @param fileSuffix the extension of the file where to log.
51      */
init(String logPrefix, String fileSuffix)52     protected void init(String logPrefix, String fileSuffix) {
53         mOutputStream =
54                 new SizeLimitedOutputStream(mMaxLogSizeMbytes * 1024 * 1024, logPrefix, fileSuffix);
55     }
56 
57     /**
58      * Creates a new {@link FileLogger} with the same log level settings as the current object.
59      * <p/>
60      * Does not copy underlying log file content (ie the clone's log data will be written to a new
61      * file.)
62      */
63     @Override
clone()64     public ILeveledLogOutput clone()  {
65         FileLogger logger = new FileLogger();
66         OptionCopier.copyOptionsNoThrow(this, logger);
67         return logger;
68     }
69 
70     /** Returns the max log size of the log in MBytes. */
getMaxLogSizeMbytes()71     public long getMaxLogSizeMbytes() {
72         return mMaxLogSizeMbytes;
73     }
74 
75     @Override
getLog()76     public InputStreamSource getLog() {
77         if (mOutputStream != null) {
78             try {
79                 // create a InputStream from log file
80                 mOutputStream.flush();
81                 return new SnapshotInputStreamSource("FileLogger", mOutputStream.getData());
82             } catch (IOException e) {
83                 System.err.println("Failed to get log");
84                 e.printStackTrace();
85             }
86         }
87         return new ByteArrayInputStreamSource(new byte[0]);
88     }
89 
90     @Override
closeLog()91     public void closeLog() {
92         doCloseLog();
93     }
94 
95     /** Flushes stream and closes log file. */
96     @VisibleForTesting
doCloseLog()97     void doCloseLog() {
98         SizeLimitedOutputStream stream = mOutputStream;
99         mOutputStream = null;
100         StreamUtil.flushAndCloseStream(stream);
101         if (stream != null) {
102             stream.delete();
103         }
104     }
105 
106     /**
107      * Dump the contents of the input stream to this log
108      *
109      * @param inputStream input stream to dump
110      * @throws IOException if an I/O error occurs
111      */
dumpToLog(InputStream inputStream)112     void dumpToLog(InputStream inputStream) throws IOException {
113         if (mOutputStream != null) {
114             StreamUtil.copyStreams(inputStream, mOutputStream);
115         }
116     }
117 }
118