• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 
17 package com.android.tradefed.result;
18 
19 import com.android.ddmlib.Log.LogLevel;
20 import com.android.tradefed.config.IConfiguration;
21 import com.android.tradefed.invoker.IInvocationContext;
22 import com.android.tradefed.invoker.TestInvocation;
23 import com.android.tradefed.invoker.logger.InvocationMetricLogger;
24 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
25 import com.android.tradefed.log.LogRegistry;
26 import com.android.tradefed.log.LogUtil.CLog;
27 import com.android.tradefed.log.StdoutLogger;
28 import com.android.tradefed.util.StreamUtil;
29 import com.android.tradefed.util.SystemUtil;
30 
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.List;
34 
35 /** A {@link ResultForwarder} for saving logs with the global file saver. */
36 public class LogSaverResultForwarder extends ResultForwarder implements ILogSaverListener {
37 
38     ILogSaver mLogSaver;
39     IConfiguration mConfig;
40 
LogSaverResultForwarder( ILogSaver logSaver, List<ITestInvocationListener> listeners, IConfiguration config)41     public LogSaverResultForwarder(
42             ILogSaver logSaver, List<ITestInvocationListener> listeners, IConfiguration config) {
43         this(logSaver, listeners, config, true);
44     }
45 
LogSaverResultForwarder( ILogSaver logSaver, List<ITestInvocationListener> listeners, IConfiguration config, boolean setLogSaver)46     public LogSaverResultForwarder(
47             ILogSaver logSaver,
48             List<ITestInvocationListener> listeners,
49             IConfiguration config,
50             boolean setLogSaver) {
51         super(listeners);
52         mLogSaver = logSaver;
53         mConfig = config;
54         if (setLogSaver) {
55             for (ITestInvocationListener listener : listeners) {
56                 if (listener instanceof ILogSaverListener) {
57                     ((ILogSaverListener) listener).setLogSaver(mLogSaver);
58                 }
59             }
60         }
61     }
62 
63     /**
64      * {@inheritDoc}
65      */
66     @Override
invocationStarted(IInvocationContext context)67     public void invocationStarted(IInvocationContext context) {
68         // Intentionally call invocationStarted for the log saver first.
69         try {
70             mLogSaver.invocationStarted(context);
71         } catch (RuntimeException e) {
72             CLog.e("Caught runtime exception from log saver: %s", mLogSaver.getClass().getName());
73             CLog.e(e);
74         }
75         InvocationSummaryHelper.reportInvocationStarted(getListeners(), context);
76     }
77 
78     /**
79      * {@inheritDoc}
80      */
81     @Override
invocationEnded(long elapsedTime)82     public void invocationEnded(long elapsedTime) {
83         InvocationSummaryHelper.reportInvocationEnded(getListeners(), elapsedTime);
84         // Intentionally call invocationEnded for the log saver last.
85         try {
86             mLogSaver.invocationEnded(elapsedTime);
87         } catch (RuntimeException e) {
88             CLog.e("Caught runtime exception from log saver: %s", mLogSaver.getClass().getName());
89             CLog.e(e);
90         }
91         String endHostLogName = TestInvocation.TRADEFED_END_HOST_LOG;
92         if (mConfig.getCommandOptions().getHostLogSuffix() != null) {
93             endHostLogName += mConfig.getCommandOptions().getHostLogSuffix();
94         }
95         reportEndHostLog(getListeners(), mLogSaver, endHostLogName);
96     }
97 
98     /** Log a final file before completion */
logFile( List<ITestInvocationListener> listeners, ILogSaver saver, InputStreamSource source, String name, LogDataType type)99     public static void logFile(
100             List<ITestInvocationListener> listeners,
101             ILogSaver saver,
102             InputStreamSource source,
103             String name,
104             LogDataType type) {
105         try (InputStream stream = source.createInputStream()) {
106             LogFile logFile = saver.saveLogData(name, type, stream);
107 
108             for (ITestInvocationListener listener : listeners) {
109                 try {
110                     if (listener instanceof ILogSaverListener) {
111                         ((ILogSaverListener) listener).testLogSaved(name, type, source, logFile);
112                         ((ILogSaverListener) listener).logAssociation(name, logFile);
113                     }
114                 } catch (Exception e) {
115                     CLog.logAndDisplay(LogLevel.ERROR, e.getMessage());
116                     CLog.e(e);
117                 }
118             }
119         } catch (IOException e) {
120             CLog.e(e);
121         }
122     }
123 
124     /** Reports host_log from session in progress. */
reportEndHostLog( List<ITestInvocationListener> listeners, ILogSaver saver, String name)125     public static void reportEndHostLog(
126             List<ITestInvocationListener> listeners, ILogSaver saver, String name) {
127         LogRegistry registry = (LogRegistry) LogRegistry.getLogRegistry();
128         try (InputStreamSource source = registry.getLogger().getLog()) {
129             if (source == null) {
130                 if (!(registry.getLogger() instanceof StdoutLogger)) {
131                     CLog.e("%s stream was null, skip saving it.", name);
132                 }
133                 return;
134             }
135             logFile(listeners, saver, source, name, LogDataType.HOST_LOG);
136             if (SystemUtil.isRemoteEnvironment()) {
137                 try (InputStream stream = source.createInputStream()) {
138                     // In remote environment, dump to the stdout so we can get the logs in the
139                     // console.
140                     System.out.println(
141                             String.format(
142                                     "===== Result Reporters =====\n%s",
143                                     StreamUtil.getStringFromStream(stream)));
144                 }
145             }
146         } catch (IOException e) {
147             CLog.e(e);
148         }
149     }
150 
151     /**
152      * {@inheritDoc}
153      * <p/>
154      * Also, save the log file with the global {@link ILogSaver} and call
155      * {@link ILogSaverListener#testLogSaved(String, LogDataType, InputStreamSource, LogFile)}
156      * for those listeners implementing the {@link ILogSaverListener} interface.
157      */
158     @Override
testLog(String dataName, LogDataType dataType, InputStreamSource dataStream)159     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
160         testLogForward(dataName, dataType, dataStream);
161         try {
162             if (dataStream == null) {
163                 CLog.w("Skip forwarding of '%s', data stream is null.", dataName);
164                 return;
165             }
166             long startTime = System.currentTimeMillis();
167             LogFile logFile = null;
168             try {
169                 // If it's a file, copy it directly as it's faster
170                 if (dataStream instanceof FileInputStreamSource) {
171                     logFile =
172                             mLogSaver.saveLogFile(
173                                     dataName,
174                                     dataType,
175                                     ((FileInputStreamSource) dataStream).getFile());
176                 } else {
177                     logFile =
178                             mLogSaver.saveLogData(
179                                     dataName, dataType, dataStream.createInputStream());
180                 }
181             } finally {
182                 InvocationMetricLogger.addInvocationMetrics(
183                         InvocationMetricKey.LOG_SAVING_TIME,
184                         System.currentTimeMillis() - startTime);
185                 InvocationMetricLogger.addInvocationMetrics(
186                         InvocationMetricKey.LOG_SAVING_COUNT, 1);
187             }
188             for (ITestInvocationListener listener : getListeners()) {
189                 if (listener instanceof ILogSaverListener) {
190                     ((ILogSaverListener) listener).testLogSaved(dataName, dataType,
191                             dataStream, logFile);
192                     ((ILogSaverListener) listener).logAssociation(dataName, logFile);
193                 }
194             }
195         } catch (RuntimeException | IOException e) {
196             CLog.e("Failed to save log data: %s", dataName);
197             CLog.e(e);
198         }
199     }
200 
201     /** Only forward the testLog instead of saving the log first. */
testLogForward( String dataName, LogDataType dataType, InputStreamSource dataStream)202     public void testLogForward(
203             String dataName, LogDataType dataType, InputStreamSource dataStream) {
204         super.testLog(dataName, dataType, dataStream);
205     }
206 
207     /**
208      * {@inheritDoc}
209      *
210      * <p>If {@link LogSaverResultForwarder} is wrap in another one, ensure we forward the
211      * testLogSaved callback to the listeners under it.
212      */
213     @Override
testLogSaved( String dataName, LogDataType dataType, InputStreamSource dataStream, LogFile logFile)214     public void testLogSaved(
215             String dataName, LogDataType dataType, InputStreamSource dataStream, LogFile logFile) {
216         try {
217             for (ITestInvocationListener listener : getListeners()) {
218                 if (listener instanceof ILogSaverListener) {
219                     ((ILogSaverListener) listener)
220                             .testLogSaved(dataName, dataType, dataStream, logFile);
221                 }
222             }
223         } catch (RuntimeException e) {
224             CLog.e("Failed to save log data for %s", dataName);
225             CLog.e(e);
226         }
227     }
228 
229     /** {@inheritDoc} */
230     @Override
logAssociation(String dataName, LogFile logFile)231     public void logAssociation(String dataName, LogFile logFile) {
232         for (ITestInvocationListener listener : getListeners()) {
233             try {
234                 // Forward the logAssociation call
235                 if (listener instanceof ILogSaverListener) {
236                     ((ILogSaverListener) listener).logAssociation(dataName, logFile);
237                 }
238             } catch (RuntimeException e) {
239                 CLog.e("Failed to provide the log association");
240                 CLog.e(e);
241             }
242         }
243     }
244 }
245