I've been trying to integrate Cloud Watch Logging in my Android app that Logs directly without using any other API calls. I went over the AWS Amplify but there is no Logging for Android
It's easy to just create an API using API Gateway and connect it to Lambda that logs the sent data but I'm not looking into that kind of solution.
I was able to implement the solution using AWS SDK in the app with Amplify providing temporary credentials.
UPDATE: This is how I implemented it in Android
Client Provided using Hilt:
@ViewModelScoped
@Provides
fun provideAmazonCloudWatchLogsClient(@ApplicationContext context: Context): AmazonCloudWatchLogsClient {
val credentialsProvider = CognitoCachingCredentialsProvider(
context,
"<Identity-Pool-id-from-cognito>",
Regions.US_WEST_2
)
val region: Region = Region.getRegion(Regions.US_WEST_2)
val client = AmazonCloudWatchLogsClient(credentialsProvider)
client.setRegion(region)
return client
}
Logging from a Usecase:
fun cloudWatchLog(eventType: EventType, appLog: AppLog, level: LogLevel = LogLevel.INFO) =
flow {
try {
emit(Resource.Loading())
val isUserSignedIn = authUser.getUserId().let { id -> !(id.isEmpty() || id == "null") }
val logEvent = PutLogEventsRequest().apply {
logGroupName = LogStream.ANDROID_LOG.stream
logStreamName = authUser.getUserId()
.let { id -> if (id.isEmpty() || id == "null") preferences.getLogsUserId()
else id
}
}
val currentTime = System.currentTimeMillis()
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val currentDate = simpleDateFormat.format(Date(currentTime))
val event = InputLogEvent().apply {
timestamp = currentTime
message =
"[$currentDate] ${level.level} [${if(isUserSignedIn) "LOGGED ✅" else "TEMP ❌"}] ${eventType.type} " +
when (eventType) {
EventType.CODE -> appLog.toCodeString()
EventType.CUSTOM, EventType.QR -> appLog.toMessageString()
else -> appLog
}
}
val list = ArrayList<InputLogEvent>().apply { add(event) }
logEvent.setLogEvents(list)
if (internetUseCase()) {
val describeRequest = DescribeLogStreamsRequest()
.withLogGroupName(logEvent.logGroupName)
.withLogStreamNamePrefix(logEvent.logStreamName)
describeRequest.limit = 1
val describeResult = logs.describeLogStreams(describeRequest);
if (describeResult.logStreams.isEmpty()) {
val createRequest = CreateLogStreamRequest()
.withLogGroupName(logEvent.logGroupName)
.withLogStreamName(logEvent.logStreamName);
LogAndToast.log("AppLogUploadUseCase", "Log Stream does not exist")
logs.createLogStream(createRequest)
logs.putLogEvents(logEvent)
} else {
LogAndToast.log("AppLogUploadUseCase", "Log Stream does exists")
logs.putLogEvents(logEvent)
}
emit(Resource.Success(data = "Success!"))
return@flow
} else {
emit(Resource.Error(message = "Failed App Logs - No Internet"))
}
} catch (e: Exception) {
LogAndToast.log("AppLogUploadUseCase", "Error = ${e.message}")
emit(Resource.Error(message = e.message ?: "An unknown error"))
}
}