1 /* 2 * Copyright 2022 Google LLC 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.google.android.libraries.mobiledatadownload.internal.logging; 17 18 import com.google.errorprone.annotations.CheckReturnValue; 19 import com.google.mobiledatadownload.LogEnumsProto.MddClientEvent; 20 import com.google.mobiledatadownload.LogProto.DataDownloadFileGroupStats; 21 import com.google.mobiledatadownload.LogProto.MddDownloadLatency; 22 import com.google.mobiledatadownload.internal.MetadataProto.DataFileGroupBookkeeping; 23 import com.google.mobiledatadownload.internal.MetadataProto.DataFileGroupInternal; 24 25 /** Helper logger to log the events associated with an MDD Download or Import operation. */ 26 @CheckReturnValue 27 public final class DownloadStateLogger { 28 private static final String TAG = "FileGroupStatusLogger"; 29 30 /** The type of operation for which the logger will log events. */ 31 public enum Operation { 32 DOWNLOAD, 33 IMPORT, 34 }; 35 36 private final EventLogger eventLogger; 37 private final Operation operation; 38 DownloadStateLogger(EventLogger eventLogger, Operation operation)39 private DownloadStateLogger(EventLogger eventLogger, Operation operation) { 40 this.eventLogger = eventLogger; 41 this.operation = operation; 42 } 43 forDownload(EventLogger eventLogger)44 public static DownloadStateLogger forDownload(EventLogger eventLogger) { 45 return new DownloadStateLogger(eventLogger, Operation.DOWNLOAD); 46 } 47 forImport(EventLogger eventLogger)48 public static DownloadStateLogger forImport(EventLogger eventLogger) { 49 return new DownloadStateLogger(eventLogger, Operation.IMPORT); 50 } 51 52 /** Gets the operation associated with this logger. */ getOperation()53 public Operation getOperation() { 54 return operation; 55 } 56 logStarted(DataFileGroupInternal fileGroup)57 public void logStarted(DataFileGroupInternal fileGroup) { 58 switch (operation) { 59 case DOWNLOAD: 60 logEventWithDataFileGroup(MddClientEvent.Code.DATA_DOWNLOAD_STARTED, fileGroup); 61 break; 62 case IMPORT: 63 logEventWithDataFileGroup(MddClientEvent.Code.EVENT_CODE_UNSPECIFIED, fileGroup); 64 break; 65 } 66 } 67 logPending(DataFileGroupInternal fileGroup)68 public void logPending(DataFileGroupInternal fileGroup) { 69 switch (operation) { 70 case DOWNLOAD: 71 logEventWithDataFileGroup(MddClientEvent.Code.EVENT_CODE_UNSPECIFIED, fileGroup); 72 break; 73 case IMPORT: 74 logEventWithDataFileGroup(MddClientEvent.Code.EVENT_CODE_UNSPECIFIED, fileGroup); 75 break; 76 } 77 } 78 logFailed(DataFileGroupInternal fileGroup)79 public void logFailed(DataFileGroupInternal fileGroup) { 80 switch (operation) { 81 case DOWNLOAD: 82 logEventWithDataFileGroup(MddClientEvent.Code.EVENT_CODE_UNSPECIFIED, fileGroup); 83 break; 84 case IMPORT: 85 logEventWithDataFileGroup(MddClientEvent.Code.EVENT_CODE_UNSPECIFIED, fileGroup); 86 break; 87 } 88 } 89 logComplete(DataFileGroupInternal fileGroup)90 public void logComplete(DataFileGroupInternal fileGroup) { 91 switch (operation) { 92 case DOWNLOAD: 93 logEventWithDataFileGroup(MddClientEvent.Code.DATA_DOWNLOAD_COMPLETE, fileGroup); 94 logDownloadLatency(fileGroup); 95 break; 96 case IMPORT: 97 logEventWithDataFileGroup(MddClientEvent.Code.EVENT_CODE_UNSPECIFIED, fileGroup); 98 break; 99 } 100 } 101 logDownloadLatency(DataFileGroupInternal fileGroup)102 private void logDownloadLatency(DataFileGroupInternal fileGroup) { 103 // This operation only makes sense for download operation, exit early if it's not the download 104 // operation. 105 if (operation != Operation.DOWNLOAD) { 106 return; 107 } 108 109 DataDownloadFileGroupStats fileGroupDetails = 110 DataDownloadFileGroupStats.newBuilder() 111 .setOwnerPackage(fileGroup.getOwnerPackage()) 112 .setFileGroupName(fileGroup.getGroupName()) 113 .setFileGroupVersionNumber(fileGroup.getFileGroupVersionNumber()) 114 .setFileCount(fileGroup.getFileCount()) 115 .setBuildId(fileGroup.getBuildId()) 116 .setVariantId(fileGroup.getVariantId()) 117 .build(); 118 119 DataFileGroupBookkeeping bookkeeping = fileGroup.getBookkeeping(); 120 long newFilesReceivedTimestamp = bookkeeping.getGroupNewFilesReceivedTimestamp(); 121 long downloadStartedTimestamp = bookkeeping.getGroupDownloadStartedTimestampInMillis(); 122 long downloadCompleteTimestamp = bookkeeping.getGroupDownloadedTimestampInMillis(); 123 124 MddDownloadLatency downloadLatency = 125 MddDownloadLatency.newBuilder() 126 .setDownloadAttemptCount(bookkeeping.getDownloadStartedCount()) 127 .setDownloadLatencyMs(downloadCompleteTimestamp - downloadStartedTimestamp) 128 .setTotalLatencyMs(downloadCompleteTimestamp - newFilesReceivedTimestamp) 129 .build(); 130 131 eventLogger.logMddDownloadLatency(fileGroupDetails, downloadLatency); 132 } 133 logEventWithDataFileGroup( MddClientEvent.Code code, DataFileGroupInternal fileGroup)134 private void logEventWithDataFileGroup( 135 MddClientEvent.Code code, DataFileGroupInternal fileGroup) { 136 eventLogger.logEventSampled( 137 code, 138 fileGroup.getGroupName(), 139 fileGroup.getFileGroupVersionNumber(), 140 fileGroup.getBuildId(), 141 fileGroup.getVariantId()); 142 } 143 } 144