Skip to content

Commit 417b201

Browse files
committed
feat: support for scheduled task via Cloud Logging
1 parent fed0a15 commit 417b201

5 files changed

Lines changed: 64 additions & 21 deletions

File tree

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ Click on any empty "Load Dataset" button to open the data loading interface.
4646
1. **Configure Parameters:** Input your Project ID, Vehicle ID(s) or Trip/Task ID(s), and the selected time range within the UI.
4747
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.
4848

49-
**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)).
50-
5149
### 2. Import from Log Files
5250

5351
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:
9290
```bash
9391
npm install
9492
```
93+
4. Add Maps Javascript API Key to src/constants.js
9594

9695
### Start development server
9796

src/CloudLogging.js

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,53 @@ export function buildQueryFilter(params) {
2222
const startDate = params.startTime || new Date(0).toISOString();
2323
const endDate = params.endTime || new Date(Date.now() + 86400000).toISOString();
2424

25-
// Build vehicle/trip filter part
26-
let entityFilter = "";
25+
/*
26+
* Query for both On-demand Trips (Fleet) AND Scheduled Tasks (DeliveryFleet)
27+
*
28+
* We use "resource.type" OR logic because a single log entry has only one resource type.
29+
*
30+
* Structure:
31+
* (
32+
* (On-demand Trips (ODRD) Conditions) OR (Scheduled Tasks (LMFS) Conditions)
33+
* )
34+
* AND timestamp...
35+
* AND logName...
36+
*/
37+
38+
let vehicleFilter = "";
2739
if (params.vehicleId?.trim()) {
28-
entityFilter += `labels.vehicle_id="${params.vehicleId.trim()}"`;
40+
const vId = params.vehicleId.trim();
41+
vehicleFilter = `(labels.vehicle_id="${vId}" OR labels.delivery_vehicle_id="${vId}")`;
2942
}
43+
44+
let tripTaskFilter = "";
3045
if (params.tripIds?.trim()) {
31-
const trips = params.tripIds
46+
const ids = params.tripIds
3247
.split(",")
3348
.map((t) => t.trim())
3449
.filter(Boolean);
35-
if (trips.length > 0) {
36-
const tripFilter = trips.length === 1 ? `labels.trip_id="${trips[0]}"` : `labels.trip_id=~"(${trips.join("|")})"`;
37-
entityFilter = entityFilter ? `(${entityFilter} OR ${tripFilter})` : tripFilter;
50+
51+
if (ids.length > 0) {
52+
if (ids.length === 1) {
53+
const id = ids[0];
54+
tripTaskFilter = `(labels.trip_id="${id}" OR labels.task_id="${id}")`;
55+
} else {
56+
const joined = ids.join("|");
57+
tripTaskFilter = `(labels.trip_id=~"(${joined})" OR labels.task_id=~"(${joined})")`;
58+
}
3859
}
3960
}
4061

62+
// If both present: (vehicleFilter OR tripTaskFilter)
63+
let entityFilter = "";
64+
if (vehicleFilter && tripTaskFilter) {
65+
entityFilter = `(${vehicleFilter} OR ${tripTaskFilter})`;
66+
} else {
67+
entityFilter = vehicleFilter || tripTaskFilter;
68+
}
69+
4170
const filter = `
42-
resource.type="fleetengine.googleapis.com/Fleet"
71+
(resource.type="fleetengine.googleapis.com/Fleet" OR resource.type="fleetengine.googleapis.com/DeliveryFleet")
4372
AND ${entityFilter}
4473
AND timestamp >= "${startDate}"
4574
AND timestamp <= "${endDate}"
@@ -48,7 +77,12 @@ export function buildQueryFilter(params) {
4877
logName:"logs/fleetengine.googleapis.com%2Fupdate_vehicle" OR
4978
logName:"logs/fleetengine.googleapis.com%2Fcreate_trip" OR
5079
logName:"logs/fleetengine.googleapis.com%2Fupdate_trip" OR
51-
logName:"logs/fleetengine.googleapis.com%2Fget_trip"
80+
logName:"logs/fleetengine.googleapis.com%2Fget_trip" OR
81+
logName:"logs/fleetengine.googleapis.com%2Fcreate_delivery_vehicle" OR
82+
logName:"logs/fleetengine.googleapis.com%2Fupdate_delivery_vehicle" OR
83+
logName:"logs/fleetengine.googleapis.com%2Fcreate_task" OR
84+
logName:"logs/fleetengine.googleapis.com%2Fupdate_task" OR
85+
logName:"logs/fleetengine.googleapis.com%2Fget_task"
5286
)
5387
`;
5488

src/CloudLogging.test.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ describe("buildQueryFilter", () => {
1414
const filter = buildQueryFilter(params);
1515

1616
// Check for key components in the filter
17-
expect(filter).toContain('resource.type="fleetengine.googleapis.com/Fleet"');
18-
expect(filter).toContain('labels.vehicle_id="vehicle1"');
17+
expect(filter).toContain(
18+
'(resource.type="fleetengine.googleapis.com/Fleet" OR resource.type="fleetengine.googleapis.com/DeliveryFleet")'
19+
);
20+
expect(filter).toContain('(labels.vehicle_id="vehicle1" OR labels.delivery_vehicle_id="vehicle1")');
1921
expect(filter).toContain("2023-01-01T01:00:00");
2022
expect(filter).toContain("2023-01-02T02:00:00");
2123
});
@@ -31,8 +33,8 @@ describe("buildQueryFilter", () => {
3133

3234
const filter = buildQueryFilter(params);
3335

34-
// Should include regex for multiple trip IDs
35-
expect(filter).toContain('labels.trip_id=~"(trip1|trip2)"');
36+
// Should include regex for multiple trip IDs and verify task_id is included
37+
expect(filter).toContain('(labels.trip_id=~"(trip1|trip2)" OR labels.task_id=~"(trip1|trip2)")');
3638
});
3739

3840
test("builds filter with single trip ID", () => {
@@ -46,8 +48,8 @@ describe("buildQueryFilter", () => {
4648

4749
const filter = buildQueryFilter(params);
4850

49-
// Should use exact match for single trip ID
50-
expect(filter).toContain('labels.trip_id="trip1"');
51+
// Should use exact match for single trip ID and verify task_id is included
52+
expect(filter).toContain('(labels.trip_id="trip1" OR labels.task_id="trip1")');
5153
});
5254

5355
test("builds filter with both vehicle and trip IDs", () => {
@@ -62,7 +64,9 @@ describe("buildQueryFilter", () => {
6264
const filter = buildQueryFilter(params);
6365

6466
// Should combine vehicle and trip filters with OR
65-
expect(filter).toContain('(labels.vehicle_id="vehicle1" OR labels.trip_id=~"(trip1|trip2)")');
67+
expect(filter).toContain(
68+
'((labels.vehicle_id="vehicle1" OR labels.delivery_vehicle_id="vehicle1") OR (labels.trip_id=~"(trip1|trip2)" OR labels.task_id=~"(trip1|trip2)"))'
69+
);
6670
});
6771

6872
test("throws error for missing project ID", () => {

src/DatasetLoading.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,14 @@ const CloudLoggingFormComponent = ({ onLogsReceived, onFileUpload }) => {
101101
</div>
102102
<div className="form-field">
103103
<label className="form-label">
104-
Trip IDs (comma-separated):
104+
Trip/Task IDs (comma-separated):
105105
<input
106106
type="text"
107107
name="tripIds"
108108
value={queryParams.tripIds}
109109
onChange={(e) => setQueryParams({ ...queryParams, tripIds: e.target.value })}
110110
className="form-input"
111-
placeholder="TRIP_ID_1,TRIP_ID_2"
111+
placeholder="TRIP_ID, TASK_ID"
112112
autoComplete="on"
113113
/>
114114
</label>

src/Task.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ class Task {
4040
taskInfo.taskoutcomelocation = lastUpdate.taskResp.taskoutcomelocation;
4141
taskInfo.taskoutcometime = lastUpdate.taskResp.taskoutcometime;
4242
taskInfo.trackingid = lastUpdate.taskResp.trackingid || lastUpdate.taskReq.task.trackingid;
43-
if (taskInfo.taskoutcomelocationsource && taskInfo.plannedlocation && taskInfo.taskoutcomelocation) {
43+
if (
44+
taskInfo.taskoutcomelocationsource &&
45+
taskInfo.plannedlocation &&
46+
taskInfo.plannedlocation.point &&
47+
taskInfo.taskoutcomelocation &&
48+
taskInfo.taskoutcomelocation.point
49+
) {
4450
taskInfo.plannedVsActualDeltaMeters = window.google.maps.geometry.spherical.computeDistanceBetween(
4551
{
4652
lat: taskInfo.plannedlocation.point.latitude,

0 commit comments

Comments
 (0)