1 /* 2 * Copyright (C) 2024 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.federatedcompute.services.common; 18 19 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_COMPLETED; 20 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_ERROR_EXAMPLE_ITERATOR; 21 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_ERROR_INVALID_ARGUMENT; 22 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_ERROR_TENSORFLOW; 23 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_ERROR_INVALID_PAYLOAD; 24 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_PLAN_RECEIVED; 25 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_PLAN_URI_RECEIVED; 26 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_STARTED; 27 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_TURNED_AWAY; 28 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_FAILURE_UPLOADED; 29 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_FAILURE_UPLOAD_STARTED; 30 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_INITIATE_REPORT_RESULT_AUTH_SUCCEEDED; 31 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_KEY_ATTESTATION_SUCCEEDED; 32 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_NOT_STARTED; 33 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_REPORT_RESULT_UNAUTHORIZED; 34 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_RESULT_UPLOADED; 35 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_RESULT_UPLOAD_SERVER_ABORTED; 36 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_RESULT_UPLOAD_STARTED; 37 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_TASK_ASSIGNMENT_AUTH_SUCCEEDED; 38 import static com.android.federatedcompute.services.stats.FederatedComputeStatsLog.FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_TASK_ASSIGNMENT_UNAUTHORIZED; 39 40 import com.android.federatedcompute.internal.util.LogUtil; 41 import com.android.federatedcompute.services.statsd.FederatedComputeStatsdLogger; 42 import com.android.federatedcompute.services.statsd.TrainingEventReported; 43 44 /** The helper function to log {@link TrainingEventReported} in statsd. */ 45 public class TrainingEventLogger { 46 private static final String TAG = TrainingEventLogger.class.getSimpleName(); 47 private long mTaskId = 0; 48 private long mVersion = 0; 49 private long mPopulationId = 0; 50 private String mSdkPackageName = ""; 51 setTaskId(long taskId)52 public void setTaskId(long taskId) { 53 this.mTaskId = taskId; 54 } 55 setClientVersion(long version)56 public void setClientVersion(long version) { 57 this.mVersion = version; 58 } 59 setPopulationName(String populationName)60 public void setPopulationName(String populationName) { 61 this.mPopulationId = populationName.hashCode(); 62 } 63 setSdkPackageName(String sdkPackageName)64 public void setSdkPackageName(String sdkPackageName) { 65 this.mSdkPackageName = sdkPackageName; 66 } 67 68 /** Logs when device doesn't start federated task like not meet training constraints. */ logTaskNotStarted()69 public void logTaskNotStarted() { 70 TrainingEventReported.Builder event = 71 new TrainingEventReported.Builder() 72 .setEventKind( 73 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_NOT_STARTED); 74 logEvent(event); 75 } 76 77 /** Logs when device checks in starts. */ logCheckinStarted()78 public void logCheckinStarted() { 79 TrainingEventReported.Builder event = 80 new TrainingEventReported.Builder() 81 .setEventKind( 82 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_STARTED); 83 logEvent(event); 84 } 85 86 /** Logs when device is turned away from federated training. */ logCheckinRejected(NetworkStats networkStats)87 public void logCheckinRejected(NetworkStats networkStats) { 88 logNetworkEvent( 89 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_TURNED_AWAY, 90 networkStats); 91 } 92 93 /** 94 * Logs when device checks in, gets task assignment, download plan model and plan is invalid. 95 */ logCheckinInvalidPayload(NetworkStats networkStats)96 public void logCheckinInvalidPayload(NetworkStats networkStats) { 97 logNetworkEvent( 98 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_ERROR_INVALID_PAYLOAD, 99 networkStats); 100 } 101 102 /** 103 * Logs when device checks in, gets task assignment and receive plan uri but not download yet. 104 */ logCheckinPlanUriReceived(NetworkStats networkStats)105 public void logCheckinPlanUriReceived(NetworkStats networkStats) { 106 logNetworkEvent( 107 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_PLAN_URI_RECEIVED, 108 networkStats); 109 } 110 111 /** Logs when device checks in, gets task assignment, download plan model and plan is valid. */ logCheckinFinished(NetworkStats networkStats)112 public void logCheckinFinished(NetworkStats networkStats) { 113 logNetworkEvent( 114 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_DOWNLOAD_PLAN_RECEIVED, 115 networkStats); 116 } 117 118 /** Logs when federated computation job fails with invalid argument reason. */ logComputationInvalidArgument(ExampleStats exampleStats)119 public void logComputationInvalidArgument(ExampleStats exampleStats) { 120 logEventWithExampleStats( 121 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_ERROR_INVALID_ARGUMENT, 122 exampleStats); 123 } 124 125 /** Logs when federated computation job fails due to example iterator. */ logComputationExampleIteratorError(ExampleStats exampleStats)126 public void logComputationExampleIteratorError(ExampleStats exampleStats) { 127 logEventWithExampleStats( 128 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_ERROR_EXAMPLE_ITERATOR, 129 exampleStats); 130 } 131 132 /** 133 * Logs when federated computation job fails due to tensorflow issue like unsupported 134 * operations, kernels. 135 */ logComputationTensorflowError(ExampleStats exampleStats)136 public void logComputationTensorflowError(ExampleStats exampleStats) { 137 logEventWithExampleStats( 138 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_ERROR_TENSORFLOW, 139 exampleStats); 140 } 141 142 /** Logs when federated computation job complete. */ logComputationCompleted(ExampleStats exampleStats, long durationInMs)143 public void logComputationCompleted(ExampleStats exampleStats, long durationInMs) { 144 TrainingEventReported.Builder event = 145 new TrainingEventReported.Builder() 146 .setEventKind( 147 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_COMPUTATION_COMPLETED) 148 .setExampleCount(exampleStats.mExampleCount.get()) 149 .setExampleSize(exampleStats.mExampleSizeBytes.get()) 150 .setExampleStoreBindLatencyNanos( 151 exampleStats.mBindToExampleStoreLatencyNanos.get()) 152 .setExampleStoreStartQueryLatencyNanos( 153 exampleStats.mStartQueryLatencyNanos.get()) 154 .setDurationInMillis(durationInMs); 155 logEvent(event); 156 } 157 158 /** Log training event kind with duration. */ logEventWithDuration(int eventKind, long durationInMs)159 public void logEventWithDuration(int eventKind, long durationInMs) { 160 TrainingEventReported.Builder event = 161 new TrainingEventReported.Builder() 162 .setEventKind(eventKind) 163 .setDurationInMillis(durationInMs); 164 logEvent(event); 165 } 166 167 /** Logs training event kind with {@link ExampleStats}. */ logEventWithExampleStats(int eventKind, ExampleStats exampleStats)168 public void logEventWithExampleStats(int eventKind, ExampleStats exampleStats) { 169 TrainingEventReported.Builder event = 170 new TrainingEventReported.Builder() 171 .setEventKind(eventKind) 172 .setExampleCount(exampleStats.mExampleCount.get()) 173 .setExampleSize(exampleStats.mExampleSizeBytes.get()) 174 .setExampleStoreBindLatencyNanos( 175 exampleStats.mBindToExampleStoreLatencyNanos.get()) 176 .setExampleStoreStartQueryLatencyNanos( 177 exampleStats.mStartQueryLatencyNanos.get()); 178 179 logEvent(event); 180 } 181 182 /** Logs training event kind. */ logEventKind(int eventKind)183 public void logEventKind(int eventKind) { 184 TrainingEventReported.Builder event = 185 new TrainingEventReported.Builder().setEventKind(eventKind); 186 logEvent(event); 187 } 188 189 /** Logs when device starts to upload computation result. */ logResultUploadStarted()190 public void logResultUploadStarted() { 191 TrainingEventReported.Builder event = 192 new TrainingEventReported.Builder() 193 .setEventKind( 194 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_RESULT_UPLOAD_STARTED); 195 logEvent(event); 196 } 197 198 /** Logs when device uploads computation result but rejected by federated server. */ logResultUploadRejected(NetworkStats networkStats)199 public void logResultUploadRejected(NetworkStats networkStats) { 200 logNetworkEvent( 201 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_RESULT_UPLOAD_SERVER_ABORTED, 202 networkStats); 203 } 204 205 /** Logs when device uploads computation result completed. */ logResultUploadCompleted(NetworkStats networkStats)206 public void logResultUploadCompleted(NetworkStats networkStats) { 207 logNetworkEvent( 208 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_RESULT_UPLOADED, 209 networkStats); 210 } 211 212 /** Logs when device starts to upload failure computation result. */ logFailureResultUploadStarted()213 public void logFailureResultUploadStarted() { 214 TrainingEventReported.Builder event = 215 new TrainingEventReported.Builder() 216 .setEventKind( 217 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_FAILURE_UPLOAD_STARTED); 218 logEvent(event); 219 } 220 221 /** Logs when device finishes uploading failure computation result. */ logFailureResultUploadCompleted(NetworkStats networkStats)222 public void logFailureResultUploadCompleted(NetworkStats networkStats) { 223 logNetworkEvent( 224 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_FAILURE_UPLOADED, 225 networkStats); 226 } 227 logNetworkEvent(int eventKind, NetworkStats networkStats)228 private void logNetworkEvent(int eventKind, NetworkStats networkStats) { 229 TrainingEventReported.Builder event = 230 new TrainingEventReported.Builder() 231 .setEventKind(eventKind) 232 .setDataTransferDurationMillis( 233 networkStats.getDataTransferDurationInMillis()) 234 .setBytesUploaded(networkStats.getTotalBytesUploaded()) 235 .setBytesDownloaded(networkStats.getTotalBytesDownloaded()); 236 logEvent(event); 237 } 238 239 /** Logs when devices are unauthorized to create task assignment. */ logTaskAssignmentUnauthorized()240 public void logTaskAssignmentUnauthorized() { 241 logKeyAttestationEvent( 242 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_TASK_ASSIGNMENT_UNAUTHORIZED); 243 } 244 245 /** Logs when devices are successfully authenticated to create task assignment. */ logTaskAssignmentAuthSucceeded()246 public void logTaskAssignmentAuthSucceeded() { 247 logKeyAttestationEvent( 248 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_TASK_ASSIGNMENT_AUTH_SUCCEEDED); 249 } 250 251 /** Logs when devices are not authorized to report result. */ logReportResultUnauthorized()252 public void logReportResultUnauthorized() { 253 logKeyAttestationEvent( 254 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_REPORT_RESULT_UNAUTHORIZED); 255 } 256 257 /** Logs when devices are successfully authenticated to report result. */ logReportResultAuthSucceeded()258 public void logReportResultAuthSucceeded() { 259 logKeyAttestationEvent( 260 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_INITIATE_REPORT_RESULT_AUTH_SUCCEEDED); 261 } 262 263 /** Logs the latency of calling key attestation on device */ logKeyAttestationLatencyEvent(long latencyMillis)264 public void logKeyAttestationLatencyEvent(long latencyMillis) { 265 TrainingEventReported.Builder event = 266 new TrainingEventReported.Builder() 267 .setKeyAttestationLatencyMillis(latencyMillis) 268 .setEventKind( 269 FEDERATED_COMPUTE_TRAINING_EVENT_REPORTED__KIND__TRAIN_KEY_ATTESTATION_SUCCEEDED); 270 logEvent(event); 271 } 272 logKeyAttestationEvent(int eventKind)273 private void logKeyAttestationEvent(int eventKind) { 274 TrainingEventReported.Builder event = 275 new TrainingEventReported.Builder().setEventKind(eventKind); 276 logEvent(event); 277 } 278 logEvent(TrainingEventReported.Builder event)279 private void logEvent(TrainingEventReported.Builder event) { 280 if (mTaskId != 0) { 281 event.setTaskId(mTaskId); 282 } 283 if (mVersion != 0) { 284 event.setClientVersion(mVersion); 285 } 286 if (mPopulationId != 0) { 287 event.setPopulationId(mPopulationId); 288 } 289 if (mSdkPackageName != null && !mSdkPackageName.isBlank()) { 290 event.setSdkPackageName(mSdkPackageName); 291 } 292 TrainingEventReported trainingEvent = event.build(); 293 LogUtil.d( 294 TAG, 295 "Log population id %d event kind %d, calling sdk package name: %s," 296 + " network upload %d download %d data transfer time %d" 297 + " example stats %d key attestation stats %d" 298 + " example store bind latency: %d" 299 + " start query latency: %d", 300 trainingEvent.getPopulationId(), 301 trainingEvent.getEventKind(), 302 trainingEvent.getSdkPackageName(), 303 trainingEvent.getBytesUploaded(), 304 trainingEvent.getBytesDownloaded(), 305 trainingEvent.getDataTransferDurationMillis(), 306 trainingEvent.getExampleCount(), 307 trainingEvent.getKeyAttestationLatencyMillis(), 308 trainingEvent.getExampleStoreBindLatencyNanos(), 309 trainingEvent.getExampleStoreStartQueryLatencyNanos()); 310 FederatedComputeStatsdLogger.getInstance().logTrainingEventReported(trainingEvent); 311 } 312 313 /** Generate task id for logging purpose because we can't log string field in WW. */ getTaskIdForLogging(String populationName, String taskId)314 public static long getTaskIdForLogging(String populationName, String taskId) { 315 String taskName = populationName + "/" + taskId; 316 return taskName.hashCode(); 317 } 318 } 319