惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
S
Schneier on Security
P
Privacy & Cybersecurity Law Blog
S
Security @ Cisco Blogs
W
WeLiveSecurity
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
NISL@THU
NISL@THU
T
Troy Hunt's Blog
L
LangChain Blog
L
LINUX DO - 最新话题
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
N
News and Events Feed by Topic
A
About on SuperTechFans
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
H
Heimdal Security Blog
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
SecWiki News
SecWiki News
Microsoft Security Blog
Microsoft Security Blog
T
Tenable Blog
P
Proofpoint News Feed
H
Hacker News: Front Page
G
GRAHAM CLULEY
I
Intezer
V
V2EX
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
Latest news
Latest news
Recent Announcements
Recent Announcements
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园_首页
Webroot Blog
Webroot Blog
博客园 - 三生石上(FineUI控件)
AI
AI
N
News | PayPal Newsroom
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
B
Blog RSS Feed
美团技术团队

Dropbox Tech Blog

How we used DSPy to turn AI evaluations into better responses in Dash chat How Dropbox uses MCP and Dash to close the design-to-code security gap Beyond code generation: rethinking engineering productivity in the age of AI agents Introducing Nova, our internal platform for coding agents Improving storage efficiency in Magic Pocket, our immutable blob store Reducing our monorepo size to improve developer velocity How we optimized Dash's relevance judge with DSPy Using LLMs to amplify human labeling and improve Dash search relevance How low-bit inference enables efficient AI Insights from our executive roundtable on AI and engineering productivity Engineering VP Josh Clemm on how we use knowledge graphs, MCP, and DSPy in Dash Inside the feature store powering real-time AI in Dropbox Dash Building the future: highlights from Dropbox’s 2025 summer intern class Fighting the forces of clock skew when syncing password payloads Introducing Focus, a new open source Gradle plugin Making camera uploads for Android faster and more reliable How Dropbox Replay keeps everyone in sync Why we built a custom Rust library for Capture Detecting memory leaks in Android applications How we sped up Dropbox Android app startup by 30% Why we chose Apache Superset as our data exploration platform Revamping the Android testing pipeline at Dropbox Our counterintuitive fix for Android path normalization JQuery to React: How we rewrote the HelloSign Editor Engineering Dropbox Transfer: Making simple even simpler Speeding up a Git monorepo at Dropbox with <200 lines of code Building for reliability at HelloSign Store grand re-opening: loading Android data with coroutines Modernizing our Android build system: Part I, the planning Modernizing our Android build system: Part II, the execution Our journey to type checking 4 million lines of Python The (not so) hidden cost of sharing code between iOS and Android Redux with Code-Splitting and Type Checking The Programmer Mindset: Main Debug Loop On working with designers Incrementally migrating over one million lines of code from Python 2 to Python 3 Crash reporting in desktop Python applications What we learned at our first JS Guild Summit How we rolled out one of the largest Python 3 migrations ever Dropbox Paper: Emojis and Exformation Creating a culture of accessibility Adding IPv6 connectivity support to the Dropbox desktop client Accelerating Iteration Velocity on Dropbox’s Desktop Client, Part 2 Accelerating Iteration Velocity on Dropbox’s Desktop Client, Part 1 DropboxMacUpdate: Making automatic updates on macOS safer and more reliable Annotations on Document Previews Open Sourcing Pytest Tools Open Sourcing Zulip – a Dropbox Hack Week Project Building Carousel, Part III: Drawing Images on Screen The Tech Behind Dropbox’s New User Experience on Mobile (Part 2) Building Dropbox’s New User Experience for Mobile, Part 1 Building Carousel, Part II: Speeding Up the Data Model Building Carousel, Part I: How we made our networked mobile app feel fast and local Scaling MongoDB at Mailbox Welcome Guido! Dropbox dives into CoffeeScript Some love for JavaScript applications Plop: Low-overhead profiling for Python Using the Dropbox API from Haskell A Python Optimization Anecdote Translating Dropbox
How we ensure credible analytics on Dropbox mobile apps
Marianna Budnikova · 2020-07-16 · via Dropbox Tech Blog

Adding user analytics to a feature may seem like a straightforward task: add events to all the appropriate call sites, pass the event names to product analysts who will use the events for their investigations, and voilà—you have analytics for your feature! 

In reality, the user analytics story is a lot more complicated. When creating new features, engineers rarely think about analytics and how they will measure the success of the new feature. Feature analytics are often added at the last minute by request of the business stakeholders. Exact details of what analytics are needed and what type of insights the data should be used for are often not specified. As a last-minute addition, the analytics code tends to be poorly-designed and not well-tested. After the initial launch of the feature, analytics often become forgotten and unobserved, and with continued development of new features without the sufficient code coverage, the old analytics becomes untrustworthy. It would almost be better to not have any analytics at all than make decisions on faulty data! 

My team at Dropbox recently invested in ensuring the integrity of our analytics. We wanted to share what we learned and what we would have done differently.

Our approach

Together with product analysts and product managers, we came up with three pillars of credible and useful analytics:

  1. Intentional: analytics should answer real business questions that measure feature success important to stakeholders
  2. Credible: analytics should be well-tested to prevent degradation
  3. Discoverable: analytics should be easy to find, understand, and use by business stakeholders

Intentional data: Data as a feature success indicator

Oftentimes as engineers we do not meaningfully engage with product managers and product analysts to understand the questions they are trying to answer. We simply turn their request to “add analytics here” into a JIRA ticket, then into a pull request, then finally wash our hands of the entire process. This leads to messy analytics code being put in last minute and without much thought. What is worse, without a clear structure and guidance on how to intentionally add analytics, we may end up accidentally measuring the wrong things. To ensure the events that we log are intentional, engineers must play a more active role in how analytics get added to our codebases. We should ask ourselves, why are we adding feature analytics in the first place? The answer is, to measure the success of the feature, of course! So how do we measure success? We ask our product analysts and product managers to come up with business questions they want to answer. 

As an example, these are some of the questions we use to measure photo upload feature success on mobile apps:

  • How long does it take to upload a photo?
  • What is the upload completion rate?
  • How many of our mobile users are uploading photos? 
  • What is the week-over-week retention rate for photo uploads?

We then can design and instrument analytics directly to answer these questions. We also significantly speed up the implementation and testing of analytics.

Credible data: data as code

Product analysts are interested in answering questions involving complex user scenarios spanning multiple screens and user interactions. As developers, we write tests to validate that our code behaves as expected. However, since unit tests are designed to test the smallest unit of code, they cannot be used to ensure analytics are being captured properly as a user moves throughout the app. To test user flows throughout the app, we employ our instrumented UI test infrastructure. In a UI test, we simulate users going through complex workflows in our mobile app and capture the analytics events for those workflows. These analytics events are then serialized into JSON format and compared against an expected output.

Comparing complex outputs saved to a text file is called snapshot testing, or textual snapshot testing. The main idea behind textual snapshot testing is that the expected output gets stored in a text file and when the test runs, a new output is generated. The new output is then compared against the expected one. If the outputs match, the test passes, otherwise the test fails with an error showing the difference between the two outputs. Snapshot testing is not a new concept and has been widely applied in web development. React’s Jest framework leverages snapshot testing to test UI component structure without actually rendering any UI.

Let’s look at a snapshot test example. Here is an instrumented test that tests the photo upload scenario in our Android app:

@get:Rule
val snapshotTestRule = SnapshotRule.Creator().create()

@Test
@ExpectedSnapshot(R.raw.test_upload_image)
fun testUploadImage() {
    uploadPhotoButton.click()
    uploadPhoto("test_photo.jpg")
    waitUntilSuccessfulUpload()

    snapshotTestRule.verifySnapshot()
}

In this test, we instrument a user scenario where a user clicks on an upload button, chooses a file to upload, and waits until the upload finishes successfully. While the test is running, it collects analytics events of interest as defined in our test rule. 

@get:Rule
val snapshotTestRule = SnapshotRule.Creator()
    .metricsToVerify(
        "upload_button.clicked"
        "upload.success",
        "upload.start"
    )
    .attributesToVerify(
        "extension"
    )
    .create()

After the last user scenario instrumentation call, we run verifySnapshot. This verifies that the recorded events match the expected textual snapshot. The expected snapshot is a raw resource that we refer to in the test header. Below is what the contents of the test_upload_image snapshot file look like:

    [
      {
        "event": "upload_button.clicked"
      },
      {
        "event": "upload.start",
        "extension": "jpg"
      },
      {
        "event": "upload.success",
        "extension": "jpg",
        "total_time_ms": "EXCLUDED_FOR_SNAPSHOT_TEST"
      }
    ]

In the example above, note the presence of the EXCLUDED_FOR_SNAPSHOT_TEST value. Some of the fields we record for analytics events are not idempotent and will be different each time the code is run since we are not mocking the majority of the systems in the UI test. For non-idempotent fields, we chose to not test the recorded value and instead ensure the presence of the field. This way, if field tagging for the event is changed or removed in the future, the snapshot test will catch it. 

Discoverable data: anyone can gain insight from data

With user analytics added, verified, and put under test, the next step is to make the insights gathered from analytics accessible to the team and stakeholders. On the Mobile team, we have dashboards dedicated to each core Dropbox feature with graphs answering questions about the feature use (e.g. How long does it take for the Home screen to load?). The data would be useless if it does not get used and monitored consistently. At Dropbox Mobile, we have a combination of monitoring for data anomalies as well as manual dashboard reviews by analysts and oncall engineers. The specifics of how and what tools to use when sharing data will be different for each company. The important thing to remember here is that after defining a bunch of questions to answer with our data we can now finally get answers and monitor insights over time! 

Results

The process of making analytics intentional, credible, and discoverable can be applied to analytics for completely new features and existing features. Here are a couple of examples how this work helped ensure credible analytics for our mobile apps: 

  • We discovered that some of our existing analytics were double logged. For example, when the user clicked on some of the navigation buttons, we noticed that the logging event was being fired twice. We fixed the issues, and by creating snapshot tests for navigating through the app, made sure that the core navigation analytics stay credible.
  • We learned that some of the analytics we thought we were recording correctly turned out to be unusable by our stakeholders. For example, when the app sign in failed, we logged the localized error message shown to the user in a dialog. Since Dropbox is translated into 22 languages and there are many possible sign in failures, it is very difficult to visualize the breakdown of sign in error reasons without a lot of work mapping the translated error messages to unified error types. To fix the logging, we used an enum representing various error states (for example,  GOOGLE_AUTH_FAIL). By changing the logging to consistent enums, we can now easily visualize the sign in error breakdown, and enable focusing on most impactful user sign in errors.
  • As we invest in rearchitecting some of our code, for example, deprecating some of the legacy C++ into native code, snapshot tests will ensure that the feature analytics do not degrade during the migration. 

Overall we are incredibly satisfied with the impact of our investment to ensure integrity of Dropbox mobile analytics. 

We perform biweekly releases for our Mobile apps at Dropbox, so getting the data right on the first go is crucial. If we make a mistake in logging the data, we have to wait for two weeks to fix it. By engaging early and often with our product and analyst counterparts, we can more fully understand the value of our analytics. By knowing the questions we are trying to answer we can more meaningfully and thoughtfully add analytics code to our codebases. Lastly, by snapshot testing the events and fields for our analytics we can ensure the accuracy of our data. 

Thanks to Alison Wyllie, Amanda Adams, Angella Derington, Anthony Kosner, Mike Nakhimovich, and Sarah Tappon for comments and review.  And thanks to Zhaoze Zhou and Angella Derington for helping make mobile analytics healthy and happy.