From fed0a152e3cd46a871fbe45260af06e3af36cb6c Mon Sep 17 00:00:00 2001 From: regeter <2320305+regeter@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:02:59 +0800 Subject: [PATCH 1/2] fix: Refresh Readme --- README.md | 159 ++++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 60adac7..1fbaae4 100644 --- a/README.md +++ b/README.md @@ -1,137 +1,132 @@ # Fleet Debugger Tool -A visualization and debugging tool for Google Maps Platform's Mobility Solutions, supporting [Scheduled tasks](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/tasks-intro) and [On-demand trips](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/trip-intro). +Fleet Debugger is an open-source web tool designed to help you visualize and analyze logs from Google Maps Platform's Mobility solutions, supporting both [Scheduled tasks](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/tasks-intro) and [On-demand trips](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/trip-intro). It provides an interactive map and timeline to analyze vehicle and task or trip data, running entirely in your browser. - + -## Using the Demo Site(s) +## Key Features -The fastest way to get started is using our GitHub hosted site: \ -[googlemaps.github.io/fleet-debugger/demos/multiple-trips](https://googlemaps.github.io/fleet-debugger/demos/multiple-trips) +Fleet Debugger helps you understand complex journey and vehicle behaviors by offering: -We also have demo data for: -- [Scheduled task](https://googlemaps.github.io/fleet-debugger/demos/lmfs/) +* **Interactive map and timeline replay:** Observe vehicle movement in real time or at an accelerated time-lapse. +* **Synchronization:** Events are linked across the map, data table, and timeline. Click an event in one place, and it's highlighted everywhere. +* **Detailed log entry inspection:** Deep dive into API requests and responses. +* **Filter & inspect log messages:** Use customizable table views to easily find and analyze specific log entries. +* **File Import:** Load logs from JSON or ZIP files. +* **Direct Cloud Logging Connection:** Securely fetch logs directly from your Google Cloud project. +* **Flexible Filtering:** Easily narrow down data by time range, entity IDs, and more. +* **View status changes:** Track changes in vehicle, trip, task, and navigation status. +* **Visualize multiple trips:** View all trips or tasks for a single vehicle. +* **Analyze GPS data:** Examine location, accuracy, and heading information. + * **GPS accuracy, speed, and heading analysis:** Detailed analysis tools for these metrics ([GPS accuracy](docs/GPSAccuracy.md), [speed](docs/Speed.md), [heading](docs/Heading.md)). +* **Analyze dwell times:** Measure time spent at specific locations ([dwell times](docs/DwellTimes.md)). +* **View planned navigation routes:** See the routes with traffic conditions as experienced by drivers (requires [Restricted Use Logs](#restricted-use-logs)). +* **See requested vs. actual pickup and dropoff points:** (requires [Restricted Use Logs](#restricted-use-logs)). +* **Map and Timeslider Interaction:** Click directly on the map or the timeslider to select the nearest log event. +* **Tracking (Chevron):** Use the tracking button to keep the map centered on the current event during replay. +* **Exporting Logs:** Export loaded dataset to a local file for easy collaboration. -### Loading Your Data +## Using the Demo Site -Click on any empy Dataset buttons `Load Dataset` to get the `Fleet Engine Logs Loading` UI. +The fastest way to get started is using our GitHub hosted site. - +This site includes demo data for: -#### Direct Cloud Logging Connection (Recommended) +* [On-demand trips](https://googlemaps.github.io/fleet-debugger/demos/multiple-trips) +* [Scheduled tasks](https://googlemaps.github.io/fleet-debugger/demos/lmfs/) -1. **Configure Parameters:** Configure the Cloud Logging query parameters directly within UI. +## Loading Your Data -2. **Connect to Cloud Logging:** The Fleet Debugger can connect directly to your Google Cloud project's Cloud Logging. Click the `Sign in and Fetch Logs` button and follow the prompts to authenticate and grant access. You'll need appropriate IAM permissions (`roles/logging.viewer` which is also granted via `roles/viewer`) for the Fleet Debugger to read logs. +Click on any empty "Load Dataset" button to open the data loading interface. -#### Log Files in JSON Format + -1. Export your Fleet Engine logs from Cloud Logging using one of the following filters (customize as needed): +### 1. Direct Cloud Logging Connection (Recommended) -```sql --- On-demand trips -resource.type="fleetengine.googleapis.com/Fleet" -AND (labels.vehicle_id="YOUR_VEHICLE_ID" OR - labels.trip_id=~"(TRIP_ID_1|TRIP_ID_2)") -AND timestamp >= "START_TIME" -- ISO 8601 format (YYYY-MM-DDTHH:MM:SS) -AND timestamp <= "END_TIME" -- ISO 8601 format (YYYY-MM-DDTHH:MM:SS) -AND ( - logName:"logs/fleetengine.googleapis.com%2Fcreate_vehicle" OR - logName:"logs/fleetengine.googleapis.com%2Fupdate_vehicle" OR - logName:"logs/fleetengine.googleapis.com%2Fcreate_trip" OR - logName:"logs/fleetengine.googleapis.com%2Fupdate_trip" -) -``` +1. **Configure Parameters:** Input your Project ID, Vehicle ID(s) or Trip/Task ID(s), and the selected time range within the UI. +2. **Connect to Cloud Logging:** Click the "Sign in and Fetch Logs" button and follow the prompts to authenticate with your Google Account and grant access. You'll need appropriate IAM permissions (e.g., `roles/logging.viewer`) to read logs. -```sql --- Scheduled tasks -resource.type="fleetengine.googleapis.com/DeliveryFleet" -AND (labels.delivery_vehicle_id="YOUR_VEHICLE_ID" OR - labels.task_id=~"(TASK_ID_1|TASK_ID_2)") -AND timestamp >= "START_TIME" -- ISO 8601 format (YYYY-MM-DDTHH:MM:SS) -AND timestamp <= "END_TIME" -- ISO 8601 format (YYYY-MM-DDTHH:MM:SS) -AND ( - logName:"logs/fleetengine.googleapis.com%2Fcreate_delivery_vehicle" OR - logName:"logs/fleetengine.googleapis.com%2Fupdate_delivery_vehicle" OR - logName:"logs/fleetengine.googleapis.com%2Fcreate_task" OR - logName:"logs/fleetengine.googleapis.com%2Fupdate_task" -) -``` +**Note:** The direct Cloud Logging import feature is fully supported for `On-demand trips`. `Scheduled tasks` support is limited ([tracking issue](https://github.com/googlemaps/fleet-debugger/issues/278)). + +### 2. Import from Log Files -2. Download the logs in JSON format and optionally zip them -3. Import the JSON/ZIP file to Fleet Debugger, using the `Load JSON or ZIP file instead` button. +You can load log data from JSON or ZIP files using the "Load JSON or ZIP file instead" button. This is useful for: -> **Note**: All data processing happens client-side. Your logs remain in your browser's Local Storage and are not uploaded to Google/GitHub. +* Analyzing logs shared with you. +* Loading previously exported datasets. -### Key Features +You can export logs from the Google Cloud Console's Logs Explorer. -- **Filter & inspect log messages:** Use customizable table views to easily find and analyze specific log entries. -- **View planned navigation routes:** See the routes with traffic conditions as experienced by drivers (requires [Restricted Use Logs](#restricted-use-logs)). -- **Replay vehicle movement:** Observe vehicle movement in real time or at an accelerated time-lapse. -- **See requested vs. actual pickup and dropoff points:** (requires [Restricted Use Logs](#restricted-use-logs)). -- **View status changes:** Track changes in vehicle, trip, and navigation status. -- **Analyze GPS data:** Examine location, accuracy, and heading information. -- **Visualize multiple trips:** View all trips for a single vehicle. -- **Analyze GPS accuracy, speed, and heading:** Detailed analysis tools for these metrics ([GPS accuracy](docs/GPSAccuracy.md), [speed](docs/Speed.md), [heading](docs/Heading.md)). -- **Analyze dwell times:** Measure time spent at specific locations ([dwell times](docs/DwellTimes.md)). -- **Map and Timeslider Interaction:** Click directly on the map or the timeslider to select the nearest log event. -- **Tracking (Chevron):** Use the tracking button to keep the map centered on the current event during replay. -- **Exporting Logs:** Export loaded dataset to a local file for easy collaboration. +> **Note**: All data processing happens client-side. Your logs or API keys are not uploaded to any server. Data is stored in your browser's Local Storage. -### Restricted Use Logs +## Restricted Use Logs -Planned navigation routes and requested Pickup/Dropoff points require enablement of [Restricted Use Logs](https://developers.google.com/maps/documentation/mobility/operations/cloud-logging/setup#enable_restricted_use_logs). +To see features like the driver's planned navigation route, traffic, and original requested stop locations, you need to enable +[Restricted Use Logs](https://developers.google.com/maps/documentation/mobility/operations/cloud-logging/setup#enable_restricted_use_logs) in your Google Cloud project. This is not required for the tool to function but highly recommended for a richer analysis. -### Managing Datasets +## Managing Datasets -Each dataset (loaded from a file or Cloud Logging) has a dropdown menu: +Each dataset has a dropdown menu: -- **Save (Export):** Save the current dataset as a JSON file. -- **Delete:** Remove the dataset from the Fleet Debugger. This clears the data from your browser's local storage. +- **Export:** Save the current dataset as a JSON file to your local system. +- **Delete:** Remove the dataset from the Fleet Debugger and your browser's local storage. ### Restoring Demo Data To reload the original demo data: -1. Select "Delete" from `Dataset 1` dropdown menu. -2. Refresh the page. The demo data will be automatically reloaded into Dataset 1. +1. Select "Delete" from the `Dataset 1` dropdown menu. +2. Refresh the page. The demo data will be automatically reloaded. ## Running Your Own Server ### Development Setup -1. Install dependencies: - - [Node.js](https://nodejs.org/en/download) - -2. Install node modules: -```bash -npm install -``` +1. Install dependencies: + * [Node.js](https://nodejs.org/en/download) +2. Clone the repository: + ```bash + git clone https://github.com/googlemaps/fleet-debugger.git + cd fleet-debugger + ``` +3. Install node modules: + ```bash + npm install + ``` ### Start development server ```bash npm start ``` +This will open the app in your default browser, usually at `http://localhost:3000`. ### Building and Deploying ```bash # Generate static build npm run build +``` +The static files will be in the `build` folder. You can deploy this folder to any static site hosting service. For Firebase Hosting: -# Deploy to firebase +```bash +# Optional: Install Firebase CLI globally npm install -g firebase-tools + +# Deploy to Firebase Hosting firebase deploy --only hosting ``` +(Requires Firebase project setup and `firebase login`) -## Privacy Policy - -This project is 100% client-side and does not collect or store any user data on servers. Please see our [Privacy Policy](docs/PRIVACY.md) for full details. +## Privacy -## Disclaimer +This project is 100% client-side. Please see our [Privacy Policy](docs/PRIVACY.md) for full details. -This is not an officially supported Google product. +## Support & Contributing -## Additional Resources +This Fleet Debugger tool is offered under an open source license. It is not an officially supported Google product. -- [Reporting Issues](docs/reporting-issues.md) +* To report bugs or request features, file an issue on + [GitHub](https://github.com/googlemaps/fleet-debugger/issues). +* For technical questions and discussions, use the + [Google Maps Platform developer community channels](https://developers.google.com/maps/developer-community). +* To contribute, check the [CONTRIBUTING.md](CONTRIBUTING.md) guide. From 417b2014f6294e9bb72eab144450b668b416f61e Mon Sep 17 00:00:00 2001 From: regeter <2320305+regeter@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:21:10 -0800 Subject: [PATCH 2/2] feat: support for scheduled task via Cloud Logging --- README.md | 3 +-- src/CloudLogging.js | 52 +++++++++++++++++++++++++++++++++------- src/CloudLogging.test.js | 18 ++++++++------ src/DatasetLoading.js | 4 ++-- src/Task.js | 8 ++++++- 5 files changed, 64 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1fbaae4..a75a760 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,6 @@ Click on any empty "Load Dataset" button to open the data loading interface. 1. **Configure Parameters:** Input your Project ID, Vehicle ID(s) or Trip/Task ID(s), and the selected time range within the UI. 2. **Connect to Cloud Logging:** Click the "Sign in and Fetch Logs" button and follow the prompts to authenticate with your Google Account and grant access. You'll need appropriate IAM permissions (e.g., `roles/logging.viewer`) to read logs. -**Note:** The direct Cloud Logging import feature is fully supported for `On-demand trips`. `Scheduled tasks` support is limited ([tracking issue](https://github.com/googlemaps/fleet-debugger/issues/278)). - ### 2. Import from Log Files You can load log data from JSON or ZIP files using the "Load JSON or ZIP file instead" button. This is useful for: @@ -92,6 +90,7 @@ To reload the original demo data: ```bash npm install ``` +4. Add Maps Javascript API Key to src/constants.js ### Start development server diff --git a/src/CloudLogging.js b/src/CloudLogging.js index c096e2a..85d7581 100644 --- a/src/CloudLogging.js +++ b/src/CloudLogging.js @@ -22,24 +22,53 @@ export function buildQueryFilter(params) { const startDate = params.startTime || new Date(0).toISOString(); const endDate = params.endTime || new Date(Date.now() + 86400000).toISOString(); - // Build vehicle/trip filter part - let entityFilter = ""; + /* + * Query for both On-demand Trips (Fleet) AND Scheduled Tasks (DeliveryFleet) + * + * We use "resource.type" OR logic because a single log entry has only one resource type. + * + * Structure: + * ( + * (On-demand Trips (ODRD) Conditions) OR (Scheduled Tasks (LMFS) Conditions) + * ) + * AND timestamp... + * AND logName... + */ + + let vehicleFilter = ""; if (params.vehicleId?.trim()) { - entityFilter += `labels.vehicle_id="${params.vehicleId.trim()}"`; + const vId = params.vehicleId.trim(); + vehicleFilter = `(labels.vehicle_id="${vId}" OR labels.delivery_vehicle_id="${vId}")`; } + + let tripTaskFilter = ""; if (params.tripIds?.trim()) { - const trips = params.tripIds + const ids = params.tripIds .split(",") .map((t) => t.trim()) .filter(Boolean); - if (trips.length > 0) { - const tripFilter = trips.length === 1 ? `labels.trip_id="${trips[0]}"` : `labels.trip_id=~"(${trips.join("|")})"`; - entityFilter = entityFilter ? `(${entityFilter} OR ${tripFilter})` : tripFilter; + + if (ids.length > 0) { + if (ids.length === 1) { + const id = ids[0]; + tripTaskFilter = `(labels.trip_id="${id}" OR labels.task_id="${id}")`; + } else { + const joined = ids.join("|"); + tripTaskFilter = `(labels.trip_id=~"(${joined})" OR labels.task_id=~"(${joined})")`; + } } } + // If both present: (vehicleFilter OR tripTaskFilter) + let entityFilter = ""; + if (vehicleFilter && tripTaskFilter) { + entityFilter = `(${vehicleFilter} OR ${tripTaskFilter})`; + } else { + entityFilter = vehicleFilter || tripTaskFilter; + } + const filter = ` - resource.type="fleetengine.googleapis.com/Fleet" + (resource.type="fleetengine.googleapis.com/Fleet" OR resource.type="fleetengine.googleapis.com/DeliveryFleet") AND ${entityFilter} AND timestamp >= "${startDate}" AND timestamp <= "${endDate}" @@ -48,7 +77,12 @@ export function buildQueryFilter(params) { logName:"logs/fleetengine.googleapis.com%2Fupdate_vehicle" OR logName:"logs/fleetengine.googleapis.com%2Fcreate_trip" OR logName:"logs/fleetengine.googleapis.com%2Fupdate_trip" OR - logName:"logs/fleetengine.googleapis.com%2Fget_trip" + logName:"logs/fleetengine.googleapis.com%2Fget_trip" OR + logName:"logs/fleetengine.googleapis.com%2Fcreate_delivery_vehicle" OR + logName:"logs/fleetengine.googleapis.com%2Fupdate_delivery_vehicle" OR + logName:"logs/fleetengine.googleapis.com%2Fcreate_task" OR + logName:"logs/fleetengine.googleapis.com%2Fupdate_task" OR + logName:"logs/fleetengine.googleapis.com%2Fget_task" ) `; diff --git a/src/CloudLogging.test.js b/src/CloudLogging.test.js index 71bd049..b0f3a4a 100644 --- a/src/CloudLogging.test.js +++ b/src/CloudLogging.test.js @@ -14,8 +14,10 @@ describe("buildQueryFilter", () => { const filter = buildQueryFilter(params); // Check for key components in the filter - expect(filter).toContain('resource.type="fleetengine.googleapis.com/Fleet"'); - expect(filter).toContain('labels.vehicle_id="vehicle1"'); + expect(filter).toContain( + '(resource.type="fleetengine.googleapis.com/Fleet" OR resource.type="fleetengine.googleapis.com/DeliveryFleet")' + ); + expect(filter).toContain('(labels.vehicle_id="vehicle1" OR labels.delivery_vehicle_id="vehicle1")'); expect(filter).toContain("2023-01-01T01:00:00"); expect(filter).toContain("2023-01-02T02:00:00"); }); @@ -31,8 +33,8 @@ describe("buildQueryFilter", () => { const filter = buildQueryFilter(params); - // Should include regex for multiple trip IDs - expect(filter).toContain('labels.trip_id=~"(trip1|trip2)"'); + // Should include regex for multiple trip IDs and verify task_id is included + expect(filter).toContain('(labels.trip_id=~"(trip1|trip2)" OR labels.task_id=~"(trip1|trip2)")'); }); test("builds filter with single trip ID", () => { @@ -46,8 +48,8 @@ describe("buildQueryFilter", () => { const filter = buildQueryFilter(params); - // Should use exact match for single trip ID - expect(filter).toContain('labels.trip_id="trip1"'); + // Should use exact match for single trip ID and verify task_id is included + expect(filter).toContain('(labels.trip_id="trip1" OR labels.task_id="trip1")'); }); test("builds filter with both vehicle and trip IDs", () => { @@ -62,7 +64,9 @@ describe("buildQueryFilter", () => { const filter = buildQueryFilter(params); // Should combine vehicle and trip filters with OR - expect(filter).toContain('(labels.vehicle_id="vehicle1" OR labels.trip_id=~"(trip1|trip2)")'); + expect(filter).toContain( + '((labels.vehicle_id="vehicle1" OR labels.delivery_vehicle_id="vehicle1") OR (labels.trip_id=~"(trip1|trip2)" OR labels.task_id=~"(trip1|trip2)"))' + ); }); test("throws error for missing project ID", () => { diff --git a/src/DatasetLoading.js b/src/DatasetLoading.js index 7878efb..d882b48 100644 --- a/src/DatasetLoading.js +++ b/src/DatasetLoading.js @@ -101,14 +101,14 @@ const CloudLoggingFormComponent = ({ onLogsReceived, onFileUpload }) => {