Skip to content

Add model name to Rollbar; change API_URL to API_HOST (UPLOAD-1661, UPLOAD-421)#1754

Open
gniezen wants to merge 8 commits into
developfrom
add-model-rollbar
Open

Add model name to Rollbar; change API_URL to API_HOST (UPLOAD-1661, UPLOAD-421)#1754
gniezen wants to merge 8 commits into
developfrom
add-model-rollbar

Conversation

@gniezen

@gniezen gniezen commented Jun 18, 2026

Copy link
Copy Markdown
Member

Addresses UPLOAD-1661 and UPLOAD-421.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves upload error observability in Rollbar (better grouping + more device context) and renames the uploader’s API endpoint configuration from API_URL to API_HOST across runtime config, docker/dev tooling, and tests.

Changes:

  • Add deviceModel (“model”) into Rollbar custom payload and adjust Rollbar fingerprinting to group by error code.
  • Preserve deviceModel through driverManager waterfall errors so it remains available for error reporting/cleanup paths.
  • Rename configuration/env usage from API_URLAPI_HOST across app initialization, CLI tools, docker artifacts, and tests.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/app/actions/async.test.js Updates async action tests to use API_HOST config key.
server.js Updates CSP connectSrc to allow the configured API host via API_HOST.
package.json Bumps version to a prerelease tag for this change set.
lib/drivers/onetouch/cli/otverio.js Uses cfg.API_HOST when creating API client.
lib/drivers/medtronic600/cli/blob_loader.js Uses cfg.API_HOST when creating API client.
lib/drivers/medtronic/cli/blob_loader.js Uses config.API_HOST when creating API client.
lib/drivers/insulet/cli/ibf_loader.js Uses cfg.API_HOST when creating API client.
lib/drivers/abbott/cli/fslibre.js Uses cfg.API_HOST when creating API client.
lib/drivers/abbott/cli/csv_loader.js Uses cfg.API_HOST when creating API client.
lib/driverManager.js Tracks lastData so deviceModel can be preserved on waterfall error paths.
lib/core/api.js Updates setHosts to look for API_HOST when setting Tidepool API host.
Dockerfile Renames build args/env from API_URL to API_HOST.
docker-compose.yaml Renames compose environment variable from API_URL to API_HOST.
config/local.sh Renames local env export from API_URL to API_HOST.
config/local.example.js Renames example env values from API_URL to API_HOST.
app/utils/rollbar.js Sets Rollbar fingerprint by error code to improve grouping.
app/store/configureStore.production.js Uses config.API_HOST for API client creation.
app/store/configureStore.development.js Uses config.API_HOST for API client creation.
app/package.json Keeps app version aligned with root package prerelease tag.
app/containers/App.js Renames environment menu/server definitions to use API_HOST.
app/actions/utils.js Adds model to Rollbar custom payload for upload errors.
app/actions/async.js Uses API_HOST when initializing API hosts during app init.
.config.js Renames exported config key and env lookup to API_HOST.
Comments suppressed due to low confidence (1)

Dockerfile:64

  • Same issue as the build stage: the production image now only exports API_HOST, but other parts of the repo/tooling still reference API_URL. Exporting both variables (and accepting both ARGs) avoids breakage for existing deploy tooling during the rename.
ARG API_HOST
ARG UPLOAD_URL
ARG DATA_URL
ARG BLIP_URL
ARG REALM_HOST

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .config.js
DEBUG: stringToBoolean(process.env.DEBUG, true),
// the defaults for these need to be pointing to prod
API_URL: process.env.API_URL || serverEnvironments[selectedServerEnv].API_URL,
API_HOST: process.env.API_HOST || serverEnvironments[selectedServerEnv].API_HOST,
Comment thread lib/core/api.js
Comment on lines +87 to 89
if (hosts.API_HOST) {
tidepool.setApiHost(hosts.API_HOST);
}
Comment thread server.js
frameSrc: ['https://docs.google.com', 'https://app.pendo.io', '*.tidepool.org', 'localhost:*', 'tidepooluploader://*'],
connectSrc: [].concat([
process.env.API_URL || 'localhost:*',
process.env.API_HOST || 'localhost:*',
Comment thread Dockerfile
Comment on lines 6 to 8
ARG VERSION_SHA
ARG API_URL
ARG API_HOST
ARG UPLOAD_URL
Comment thread lib/driverManager.js
Comment on lines 246 to +249
result = result || {};
if (result.deviceModel == null && lastData.deviceModel != null) {
result.deviceModel = lastData.deviceModel;
}
@krystophv

Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • API connection settings now use a host-based configuration across the app and deployment setup, making environment setup more consistent.
  • Bug Fixes

    • Improved error reporting for uploads by including device model details when available.
    • Updated error grouping so similar failures are easier to track and separate.
    • Adjusted connection rules to recognize the new API host setting for outbound requests.

Walkthrough

This PR renames the API_URL configuration key to API_HOST across build configs, Docker files, server CSP settings, app initialization, store setup, core API client, and CLI driver login flows. It also adds device model tracking through the upload pipeline, backfilling deviceModel on cleanup, includes it in upload error payloads, and adjusts Rollbar error fingerprinting to use error codes. Version numbers were bumped in package.json files.

Changes

API_URL to API_HOST rename

Layer / File(s) Summary
Root and build configuration
.config.js, Dockerfile, docker-compose.yaml, config/local.example.js, config/local.sh
Renames the API_URL config/environment key to API_HOST across server environment definitions, Docker build args and ENV mappings, and local config files.
App init, store, and server wiring
app/containers/App.js, app/actions/async.js, app/store/configureStore.development.js, app/store/configureStore.production.js, lib/core/api.js, server.js, test/app/actions/async.test.js
Updates serverdata, doAppInit, store creation, api.setHosts, and CSP connect-src to read/pass API_HOST instead of API_URL, with matching test updates.
CLI driver login flows
lib/drivers/abbott/cli/*, lib/drivers/insulet/cli/ibf_loader.js, lib/drivers/medtronic/cli/blob_loader.js, lib/drivers/medtronic600/cli/blob_loader.js, lib/drivers/onetouch/cli/otverio.js
Updates login functions to use cfg.API_HOST/config.API_HOST when calling api.create for apiUrl, and updates related log statements.

Device model tracking and error fingerprinting

Layer / File(s) Summary
Device model backfill and error reporting
lib/driverManager.js, app/actions/utils.js, app/utils/rollbar.js
Tracks the latest pipeline data to backfill result.deviceModel on cleanup, adds a model field to upload error payloads, and fingerprints Rollbar errors using payload.custom.code when present.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DriverManager as lib/driverManager.js
  participant Driver as Device Driver
  participant Cleanup as drvr.cleanup

  DriverManager->>Driver: connect/fetchData/processData/uploadData(data)
  Driver-->>DriverManager: returns data, stores as lastData
  DriverManager->>DriverManager: check result.deviceModel missing
  DriverManager->>DriverManager: backfill result.deviceModel from lastData.deviceModel
  DriverManager->>Cleanup: cleanup(result)
Loading

Related PRs: None identified.

Suggested labels: configuration, breaking-change

Suggested reviewers: None identified.

Poem:
A rabbit hopped through config trees,
Swapped URL for HOST with ease,
Drivers logged in, one by one,
Rollbar fingerprints errors done,
And deviceModel, once astray,
Now backfilled to save the day! 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main changes: adding model data to Rollbar and renaming API_URL to API_HOST.
Description check ✅ Passed The description is related to the changeset and references the linked issues addressed by this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-model-rollbar
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch add-model-rollbar

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.44.1)
test/app/actions/async.test.js

ast-grep timed out on this file


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/utils/rollbar.js (1)

36-48: 🧹 Nitpick | 🔵 Trivial

Fingerprint-by-code grouping is reasonable; matches existing payload access pattern in this file.

Direct payload.custom/payload.fingerprint access is consistent with the existing direct payload.body.trace usage above (Line 27), so no structural mismatch. One tradeoff worth being aware of: grouping strictly by custom.code will collapse all occurrences sharing a generic code (e.g. E_SERVER_ERR) into a single Rollbar item regardless of device/model/message differences, which may hide distinct root causes behind one item. This appears intentional per the added comments, so no action needed unless that granularity loss becomes a problem in practice.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/utils/rollbar.js` around lines 36 - 48, No code change is needed here:
the direct payload.custom and payload.fingerprint access in rollbar.js is
already consistent with the existing payload.body.trace handling, and the new
fingerprint-by-code logic is intentional. If you later decide the grouping is
too coarse, update the fingerprinting in the same rollbar payload path to
include additional discriminators beyond payload.custom.code so distinct failure
causes do not collapse into one Rollbar item.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/containers/App.js`:
- Line 176: The persisted server config upgrade path in App.js is missing a
legacy fallback for selectedEnv values saved with API_URL, so upgraded installs
can load the wrong API host while still reusing the other saved hosts. Update
the startup/config loading logic around api.setHosts and the selectedEnv
deserialization in App to treat API_URL as a fallback for API_HOST, and apply
the same fallback consistently in both places so old persisted configs map to
the intended host fields.

In `@lib/driverManager.js`:
- Around line 109-113: The debug-mode waterfall in driverManager.js bypasses the
local wrapper functions, so lastData is not updated for
connect/getConfigInfo/fetchData/processData/uploadData/disconnect and
result.deviceModel can’t be backfilled on error. Update the debug path to call
the same wrapper helpers (or otherwise assign lastData consistently) used in the
non-debug path, while keeping uploadBlob tracked too, so the final error handler
can reliably read the latest pipeline data.

---

Nitpick comments:
In `@app/utils/rollbar.js`:
- Around line 36-48: No code change is needed here: the direct payload.custom
and payload.fingerprint access in rollbar.js is already consistent with the
existing payload.body.trace handling, and the new fingerprint-by-code logic is
intentional. If you later decide the grouping is too coarse, update the
fingerprinting in the same rollbar payload path to include additional
discriminators beyond payload.custom.code so distinct failure causes do not
collapse into one Rollbar item.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: abf1f7e2-bba6-43ae-aa98-61f668f09b1e

📥 Commits

Reviewing files that changed from the base of the PR and between 4f1a1b2 and 3b05857.

📒 Files selected for processing (23)
  • .config.js
  • Dockerfile
  • app/actions/async.js
  • app/actions/utils.js
  • app/containers/App.js
  • app/package.json
  • app/store/configureStore.development.js
  • app/store/configureStore.production.js
  • app/utils/rollbar.js
  • config/local.example.js
  • config/local.sh
  • docker-compose.yaml
  • lib/core/api.js
  • lib/driverManager.js
  • lib/drivers/abbott/cli/csv_loader.js
  • lib/drivers/abbott/cli/fslibre.js
  • lib/drivers/insulet/cli/ibf_loader.js
  • lib/drivers/medtronic/cli/blob_loader.js
  • lib/drivers/medtronic600/cli/blob_loader.js
  • lib/drivers/onetouch/cli/otverio.js
  • package.json
  • server.js
  • test/app/actions/async.test.js

Comment thread app/containers/App.js
const url = `${protocol}${server.name}:${server.port}`;
serverdata[server.name] = {
API_URL: url,
API_HOST: url,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Files ==\n'
git ls-files 'app/containers/App.js' 'lib/core/api.js' | sed 's#^`#-` #'

printf '\n== Search selectedEnv / API_URL / API_HOST ==\n'
rg -n --hidden --no-ignore-vcs -S 'selectedEnv|API_URL|API_HOST' app lib | sed -n '1,240p'

printf '\n== App.js relevant slice ==\n'
sed -n '1,240p' app/containers/App.js

printf '\n== api.js relevant slice ==\n'
sed -n '1,220p' lib/core/api.js

Repository: tidepool-org/uploader

Length of output: 16296


Handle legacy API_URL in persisted server config.

selectedEnv saved before this rename can still deserialize with API_URL, but api.setHosts() only reads API_HOST. That leaves upgraded Electron installs on the default API host while reusing the old upload/data/blip hosts from storage. Mirror the same fallback in both startup reads.

Suggested fallback
       let parsedEnv = JSON.parse(selectedEnv);
+      if (!parsedEnv.API_HOST && parsedEnv.API_URL) {
+        parsedEnv.API_HOST = parsedEnv.API_URL;
+      }
       console.log('setting initial server from localstore:', parsedEnv.environment);
       api.setHosts(parsedEnv);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/containers/App.js` at line 176, The persisted server config upgrade path
in App.js is missing a legacy fallback for selectedEnv values saved with
API_URL, so upgraded installs can load the wrong API host while still reusing
the other saved hosts. Update the startup/config loading logic around
api.setHosts and the selectedEnv deserialization in App to treat API_URL as a
fallback for API_HOST, and apply the same fallback consistently in both places
so old persisted configs map to the intended host fields.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gniezen do you think that it's worth addressing loading old stored data here?

Comment thread lib/driverManager.js
Comment on lines +109 to +113
// async.waterfall only passes the data object to the final callback on
// success; on error it's dropped. We keep a reference to the latest data
// flowing through the pipeline so the device model and other metadata
// is still available to report on error.
var lastData = {};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

lastData backfill doesn't work in debug mode for most pipeline stages.

The debug-mode waterfall (Lines 237-244) binds drvr.connect, drvr.getConfigInfo, drvr.fetchData, drvr.processData, drvr.uploadData, drvr.disconnect directly, bypassing the local wrapper functions (connect, getConfigInfo, fetchData, processData, uploadData, disconnect) that set lastData. Only the shared uploadBlob step updates lastData in this path. As a result, if an error occurs in any stage other than uploadBlob while configs.debug === true, lastData still holds its initial {} (or a stale value from before uploadBlob ran), and the backfill at Lines 247-249 can't populate result.deviceModel. This defeats the stated purpose of the change ("we keep a reference to the latest data flowing through the pipeline ... available to report on error") for the debug path.

🔧 Proposed fix: wrap debug-mode steps to also track lastData without adding try/catch
+      function withLastData(fn) {
+        return function(data, next) {
+          lastData = data;
+          fn(data, next);
+        };
+      }
+
       if (configs.debug === true) {
         debug('DriverManager set up in debug mode: all non-device comms errors will throw in console.');
         console.time('total time elapsed');
         async.waterfall([
           drvr.setup.bind(drvr, deviceInfo, stat.progressForStep(0)),
-          drvr.connect.bind(drvr, stat.progressForStep(1)),
-          drvr.getConfigInfo.bind(drvr, stat.progressForStep(2)),
-          drvr.fetchData.bind(drvr, stat.progressForStep(3)),
+          withLastData(drvr.connect.bind(drvr, stat.progressForStep(1))),
+          withLastData(drvr.getConfigInfo.bind(drvr, stat.progressForStep(2))),
+          withLastData(drvr.fetchData.bind(drvr, stat.progressForStep(3))),
           uploadBlob,
-          drvr.processData.bind(drvr, stat.progressForStep(4)),
-          drvr.uploadData.bind(drvr, stat.progressForStep(5)),
-          drvr.disconnect.bind(drvr, stat.progressForStep(6))
+          withLastData(drvr.processData.bind(drvr, stat.progressForStep(4))),
+          withLastData(drvr.uploadData.bind(drvr, stat.progressForStep(5))),
+          withLastData(drvr.disconnect.bind(drvr, stat.progressForStep(6)))
         ], function(err, result) {

Also applies to: 236-283

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/driverManager.js` around lines 109 - 113, The debug-mode waterfall in
driverManager.js bypasses the local wrapper functions, so lastData is not
updated for connect/getConfigInfo/fetchData/processData/uploadData/disconnect
and result.deviceModel can’t be backfilled on error. Update the debug path to
call the same wrapper helpers (or otherwise assign lastData consistently) used
in the non-debug path, while keeping uploadBlob tracked too, so the final error
handler can reliably read the latest pipeline data.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gniezen This seems like an actual concern for the context/bind behavior that would need to be adjusted to make sure the reference is correct for the debug cases.

@krystophv

Copy link
Copy Markdown
Member

@gniezen as the AI code reviews mention in a couple places, there are still API_URL references in the webpack.config.X files that probably need to be handled for completeness. Also there seems to be a reference in the tandem driver that will need an update as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants