1 /* 2 * Copyright (C) 2017 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.util.hostmetric; 17 18 import com.android.tradefed.config.Option; 19 import com.android.tradefed.config.Option.Importance; 20 import com.android.tradefed.config.OptionClass; 21 import com.android.tradefed.log.LogUtil.CLog; 22 import com.android.tradefed.util.Email; 23 import com.android.tradefed.util.IEmail; 24 import com.android.tradefed.util.IEmail.Message; 25 26 import org.json.JSONException; 27 import org.json.JSONObject; 28 29 import java.io.IOException; 30 import java.net.InetAddress; 31 import java.net.UnknownHostException; 32 import java.util.Collection; 33 import java.util.HashSet; 34 import java.util.Iterator; 35 import java.util.LinkedList; 36 import java.util.List; 37 import java.util.Map; 38 39 /** A {@link IHostHealthAgent} implementation to send email from Host monitor reports */ 40 @OptionClass(alias = "host_metric_agent_email", global_namespace = false) 41 public class EmailHostHealthAgent implements IHostHealthAgent { 42 43 @Option( 44 name = "sender", 45 description = "The envelope-sender address to use for the messages.", 46 importance = Importance.IF_UNSET 47 ) 48 private String mSender = null; 49 50 @Option( 51 name = "destination", 52 description = "The destination email addresses. Can be repeated.", 53 importance = Importance.IF_UNSET 54 ) 55 private Collection<String> mDestinations = new HashSet<String>(); 56 57 private List<HostMetric> mMetrics = new LinkedList<>(); 58 59 /** {@inheritDoc} */ 60 @Override 61 public void emitValue(String name, long value, Map<String, String> data) { 62 mMetrics.add(new HostMetric(name, System.currentTimeMillis(), value, data)); 63 } 64 65 /** {@inheritDoc} */ 66 @Override 67 public void flush() { 68 if (mMetrics.isEmpty()) { 69 CLog.i("No metric to send, skipping HostMetricAgentEmail."); 70 return; 71 } 72 if (mDestinations.isEmpty()) { 73 CLog.w("No email sent because no destination addresses were set."); 74 return; 75 } 76 if (mSender == null) { 77 CLog.w("No email sent because no sender addresse was set."); 78 return; 79 } 80 IEmail mMailer = new Email(); 81 Message msg = new Message(); 82 msg.setSender(mSender); 83 msg.setSubject(generateEmailSubject()); 84 msg.setBody(generateEmailBody()); 85 msg.setHtml(false); 86 Iterator<String> toAddress = mDestinations.iterator(); 87 while (toAddress.hasNext()) { 88 msg.addTo(toAddress.next()); 89 } 90 91 try { 92 CLog.d(msg.getSubject()); 93 CLog.d(msg.getBody()); 94 mMailer.send(msg); 95 } catch (IllegalArgumentException e) { 96 CLog.e("Failed to send email"); 97 CLog.e(e); 98 } catch (IOException e) { 99 CLog.e("Failed to send email"); 100 CLog.e(e); 101 } 102 } 103 104 private String generateEmailSubject() { 105 final StringBuilder subj = new StringBuilder("Tradefed host: "); 106 try { 107 subj.append(InetAddress.getLocalHost().getHostName()); 108 } catch (UnknownHostException e) { 109 subj.append("UNKNOWN"); 110 } 111 subj.append(" - Health Report"); 112 return subj.toString(); 113 } 114 115 private String generateEmailBody() { 116 StringBuilder bodyBuilder = new StringBuilder(); 117 bodyBuilder.append("Reporting Event from Host Health Monitor:\n\n"); 118 119 while (!mMetrics.isEmpty()) { 120 HostMetric tmp = mMetrics.remove(0); 121 try { 122 JSONObject metric = tmp.toJson(); 123 Iterator<?> i = metric.keys(); 124 while (i.hasNext()) { 125 String key = (String) i.next(); 126 bodyBuilder.append(key).append(": ").append(metric.get(key)).append("\n"); 127 } 128 } catch (JSONException e) { 129 CLog.e(e); 130 } 131 } 132 return bodyBuilder.toString(); 133 } 134 } 135