blob: e634130b0d19b965a081002caea1be54b2c003d4 [file] [log] [blame]
Di Qian38c02a72019-11-18 19:14:07 -08001/*
2 * Copyright (C) 2019 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 */
16package com.android.tradefed.cluster;
17
18import com.android.tradefed.log.LogUtil.CLog;
19
20import org.json.JSONArray;
21import org.json.JSONException;
22import org.json.JSONObject;
23
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Map;
27import java.util.Set;
28
29/** A class to encapsulate cluster command events to be uploaded. */
30public class ClusterCommandEvent implements IClusterEvent {
31
32 public static final String DATA_KEY_ERROR = "error";
33 public static final String DATA_KEY_SUMMARY = "summary";
34 public static final String DATA_KEY_SETUP_TIME_MILLIS = "setup_time_millis";
35 public static final String DATA_KEY_FETCH_BUILD_TIME_MILLIS = "fetch_build_time_millis";
36 public static final String DATA_KEY_TOTAL_TEST_COUNT = "total_test_count";
37 public static final String DATA_KEY_FAILED_TEST_COUNT = "failed_test_count";
Daniel Peykov0cb492a2019-12-13 10:49:35 -080038 public static final String DATA_KEY_PASSED_TEST_COUNT = "passed_test_count";
Di Qian38c02a72019-11-18 19:14:07 -080039 public static final String DATA_KEY_FAILED_TEST_RUN_COUNT = "failed_test_run_count";
Di Qian38c02a72019-11-18 19:14:07 -080040
41 // Maximum size of an individual data string value.
42 public static final int MAX_DATA_STRING_SIZE = 4095;
43
44 public enum Type {
45 AllocationFailed,
46 ConfigurationError,
47 FetchFailed,
48 ExecuteFailed,
49 InvocationInitiated,
50 InvocationStarted,
51 InvocationFailed,
52 InvocationEnded,
53 InvocationCompleted,
54 TestRunInProgress,
55 TestEnded
56 }
57
58 private long mTimestamp;
59 private Type mType;
60 private String mCommandTaskId;
61 private String mAttemptId;
62 private String mHostName;
63 private InvocationStatus mInvocationStatus;
64 private Map<String, Object> mData = new HashMap<>();
65 private Set<String> mDeviceSerials;
66
67 private ClusterCommandEvent() {}
68
69 public String getHostName() {
70 return mHostName;
71 }
72
73 public long getTimestamp() {
74 return mTimestamp;
75 }
76
77 public Type getType() {
78 return mType;
79 }
80
81 public String getCommandTaskId() {
82 return mCommandTaskId;
83 }
84
85 public String getAttemptId() {
86 return mAttemptId;
87 }
88
89 public InvocationStatus getInvocationStatus() {
90 return mInvocationStatus;
91 }
92
93 public Map<String, Object> getData() {
94 return mData;
95 }
96
97 public Set<String> getDeviceSerials() {
98 return mDeviceSerials;
99 }
100
101 public static class Builder {
102
103 private long mTimestamp = System.currentTimeMillis();
104 private Type mType;
105 private String mCommandTaskId;
106 private String mAttemptId;
107 private String mHostName;
108 private InvocationStatus mInvocationStatus;
109 private Map<String, Object> mData = new HashMap<>();
110 private Set<String> mDeviceSerials = new HashSet<>();
111
112 public Builder() {}
113
114 public Builder setTimestamp(final long timestamp) {
115 mTimestamp = timestamp;
116 return this;
117 }
118
119 public Builder setType(final Type type) {
120 mType = type;
121 return this;
122 }
123
124 public Builder setCommandTaskId(final String commandTaskId) {
125 mCommandTaskId = commandTaskId;
126 return this;
127 }
128
129 public Builder setAttemptId(final String attemptId) {
130 mAttemptId = attemptId;
131 return this;
132 }
133
134 public Builder setHostName(final String hostName) {
135 mHostName = hostName;
136 return this;
137 }
138
139 public Builder setInvocationStatus(final InvocationStatus invocationStatus) {
140 mInvocationStatus = invocationStatus;
141 return this;
142 }
143
144 public Builder setData(final String name, final Object value) {
145 if (value instanceof String && ((String) value).length() > MAX_DATA_STRING_SIZE) {
146 CLog.w(
147 String.format(
148 "Data for '%s' exceeds %d characters, and has been truncated.",
149 name, MAX_DATA_STRING_SIZE));
150 mData.put(name, ((String) value).substring(0, MAX_DATA_STRING_SIZE));
151 } else {
152 mData.put(name, value);
153 }
154 return this;
155 }
156
157 public Builder setDeviceSerials(final Set<String> deviceSerials) {
158 mDeviceSerials = deviceSerials;
159 return this;
160 }
161
162 public Builder addDeviceSerial(final String deviceSerial) {
163 mDeviceSerials.add(deviceSerial);
164 return this;
165 }
166
167 public ClusterCommandEvent build() {
168 final ClusterCommandEvent obj = new ClusterCommandEvent();
169 obj.mTimestamp = mTimestamp;
170 obj.mType = mType;
171 obj.mCommandTaskId = mCommandTaskId;
172 obj.mAttemptId = mAttemptId;
173 obj.mHostName = mHostName;
174 obj.mInvocationStatus = mInvocationStatus;
175 obj.mData = new HashMap<>(mData);
176 obj.mDeviceSerials = mDeviceSerials;
177 return obj;
178 }
179 }
180
181 /**
182 * Creates a base {@link Builder}.
183 *
184 * @return a {@link Builder}.
185 */
186 public static Builder createEventBuilder() {
187 return createEventBuilder(null);
188 }
189
190 /**
191 * Creates a base {@link Builder} for the given {@link ClusterCommand}.
192 *
193 * @return a {@link Builder}.
194 */
195 public static Builder createEventBuilder(final ClusterCommand command) {
196 final ClusterCommandEvent.Builder builder = new ClusterCommandEvent.Builder();
197 if (command != null) {
198 builder.setCommandTaskId(command.getTaskId());
199 builder.setAttemptId(command.getAttemptId());
200 }
201 return builder;
202 }
203
204 /** {@inheritDoc} */
205 @Override
206 public JSONObject toJSON() throws JSONException {
207 final JSONObject json = new JSONObject();
208 json.put("type", this.getType().toString());
209 // event time should be in POSIX timestamp.
210 json.put("time", this.getTimestamp() / 1000);
211 json.put("task_id", this.getCommandTaskId());
212 json.put("attempt_id", this.getAttemptId());
213 json.put("hostname", this.getHostName());
214 // TODO(b/79583735): deprecated.
215 if (!this.getDeviceSerials().isEmpty()) {
216 json.put("device_serial", this.getDeviceSerials().iterator().next());
217 }
218 json.put("device_serials", new JSONArray(this.getDeviceSerials()));
219 if (mInvocationStatus != null) {
220 json.put("invocation_status", mInvocationStatus.toJSON());
221 }
222 json.put("data", new JSONObject(this.getData()));
223 return json;
224 }
225
226 @Override
227 public String toString() {
228 String str = null;
229 try {
230 str = toJSON().toString();
231 } catch (final JSONException e) {
232 // ignore
233 }
234 return str;
235 }
236}