Enterprises building mobile apps at scale want to know how people are using their app: Is it crashing? Where are users spending the most time? What requests is the app making to the backend? Observability tools can help you answer these answers.
One example is Embrace, a leading enterprise mobile observability platform and a VGV partner. With existing SDKs for Unity, React Native, iOS, and Android, today we are excited to announce the beta release of the Embrace Flutter SDK!
Embrace expands into Flutter
The Embrace product and engineering teams have no shortage of mobile, observability, and SDK expertise. As their customers, including mutual VGV and Embrace customer Slickdeals, increasingly asked for Flutter support, Embrace knew it was time to turn their attention to developing an SDK for Flutter. But they were looking for a partner with Flutter expertise to help build a solid SDK, so, they turned to our team at Very Good Ventures.
Building a beta in three weeks with our best practices
Embrace came to VGV with a Proof of Concept (POC) for the Flutter SDK that proved feasibility but, not surprisingly for a POC, lacked many of the best practices and standards that VGV recommends. Initially, we worked with the existing POC structure to make some initial improvements. Once we reached a stable point, we regenerated the plugin using very_good_cli and migrated to the new project structure.
As we’ve written about before, very_good_cli speeds up what would normally be the tedious project setup phase. We used the very_good_cli create command with the flutter_plugin template option to generate a solid foundation for this SDK.
The original Embrace POC had around 5% test coverage, as they were not initially focused on tests and were simply trying to demonstrate technical feasibility. Our very_good_coverage tool can be helpful when it comes to enforcing code coverage metrics over time. By default, the minimum coverage threshold is 100%, but you can customize that based on your team's needs. Once the team overcame the initial concerns and gained confidence that high test coverage was feasible, we switched gears and made sure that the codebase was well-tested. Now, the SDK has 100% test coverage — meaning that every single line of code is exercised at least once. While this doesn't guarantee the codebase is bug-free, it is one measure of quality and increases confidence in the functionality of the SDK.
Overall, we were able to release a beta in about three weeks due to:
- Embedded peer programming: Our teammates worked with engineers at Embrace on code reviews and architecture discussions to ensure that everyone was on the same page throughout the project. These pair programming sessions are a great way to get quick feedback and ensure everyone is aligned.
- Our open source tools: Using very_good_cli allowed us to generate a solid federated plugin with a single command, which greatly sped up the project timeline, compared to if we had started from scratch.
- Embrace's deep observability expertise: Because the Embrace team has existing SDKs in other ecosystems, they were able to bring their mobile observability knowledge to the project and ensure that the Flutter SDK we were creating would meet their users' needs.
Making the Embrace SDK _Fluttery _with familiar APIs
An important part of this project was ensuring that the SDK would feel familiar to Flutter developers.
One of these elements involved structuring APIs to be familiar to developers who are working with plugins. For example, do you set up a singleton with a bunch of static APIs? — e.g. EmbracePlatform.instance.logError — or instead do you implement top level functions such as logError? This is the type of question that we discussed early on in order to ensure the final result aligned with what Flutter developers expect. For this SDK, we aligned with approaches used in other Flutter plugins and went with the singleton and static API approach.
For decisions that impact developer experience, we referenced similar SDKs in the ecosystem to make sure that when a developer integrates this SDK into a Flutter codebase, it feels natural. The ultimate goal is for a developer to look at the Embrace SDK and say: "Oh yeah, I've done this before. I've seen or used other observability tools and the API makes sense.” Generally, when you're developing across multiple frameworks and languages, it is important to avoid tunnel vision: “We have this existing implementation and it works well, so let’s do the exact same thing in this other ecosystem." In our experience, this rarely produces the best results. There are many things that make sense to do in iOS, Android, or other contexts, but don't translate well when using Flutter due to conceptual differences.
One example in which we focused on designing APIs specifically for Flutter was tracking page views and moments. Knowing how many times a user saw or interacted with a page is important for many developers and product professionals trying to optimize their app's performance. While there are a variety of different mechanisms to accomplish these things across iOS, Android, and Flutter, the obvious choice for Flutter was using the NavigatorObserver API to track page view events by overriding didPush, didPop, and didReplace.
Federated plugin architecture
With Embrace, we implemented a federated plugin architecture. The benefits of this approach are numerous: flexibility, ease of adoption, ease of maintenance, facilitating community contribution, and an abstraction layer between the logic and the platform-specific implementations. This allows authors to define an interface, implement support for whatever platforms they want, and the community can gradually contribute support for new platforms without requiring changes to the plugin interface.
Currently, the Embrace SDK only supports Android and iOS. But with the federated plugin architecture, it will be easy to add support for other platforms in the future, without overhauling any of the existing plugin code.
Using integration tests with federated plugins
The federated plugin architecture also allows you to test, instrument, and set up automations for each of the platforms independently of the others. This helps with maintenance and the general CI/CD setup because everything can be tested and worked on independently. This can be particularly beneficial for larger companies that have different teams working on different platform implementations without stepping on each other's toes.
The very_good_cli plugin template also includes integration tests, which can come in handy when testing a plugin. These workflows make sure we're testing the platform-specific implementations on the respective platforms. For example, if a change is made to the iOS implementation of the plugin, these workflows would spin up an iOS environment and run integration tests to verify the plugin functions as expected on iOS. This gives us an extra boost of confidence that the SDK is performing as intended without the need to constantly perform manual tests.
Using the Embrace SDK for comprehensive observability metrics
When it comes to observability and crash reporting with Flutter apps, there historically have been only a couple of solutions. There are existing observability tools, but most tend to focus on one specific area, like crash reporting, logging, or user tracking. Flutter makes observability extra challenging because applications built with Flutter can be deployed to many platforms. As the ecosystem stands right now, you would need to research and integrate several different tools to get at the full spectrum of app performance the way Embrace does. In addition to crash reporting, the Embrace Flutter SDK currently offers network monitoring, logging, and custom user flows (moments). With the addition of the Embrace SDK to the Flutter ecosystem, developers now have another comprehensive observability solution.