We use a combination of Java and C# microservices on AWS. We started off with CloudWatch but found it severely lacking - even for basic logging functionality; mostly because the way it sets up log groups is not very useful for distributed applications. It gets hard to find the right logs for the right instance; the interface is rather lacking, etc.
We looked into several alternatives. Our final decision fell upon: - Datadog, bundled with every docker image during the CI/CD build process. Datadog has agents easily hook into our existing processes. No real code had to be changed other than the build script and the Dockerfile (https://docs.datadoghq.com/tracing/setup_overview/setup/java/?tab=containers). Datadog has been very good at providing insights on many different levels (performance, errors, infrastructure load) and can be set up to send automated alerts when unexpected behavior happens. - Kibana, to centralize our logging into a more easily searchable and filterable configuration.
I would also recommend considering Dynatrace. I believe it comes at a higher price, but I fondly look back to my time working with the tool in the past. Dynatrace is remarkably deep and smart; it ended up being very good at helping us find tricky issues like memory leaks, it helped us monitor performance, trace user paths throughout our apps and so much more. I understand they've evolved quite a bit since I last used them, investing heavily into AI components to improve the experience. Worth the consideration.
Via acquisitions and internal product developments over the last year+, Splunk provides really differentiated APM and monitoring for microservices and AWS. I'd recommend giving it a peak if you haven't yet! For some validation, a recent Cloud Observability vendor report by GigaOm came out and ranked Splunk as the "top performer" in the space. Hope this helps in your search