blob: b8f5b11dc9327b6731b39d1168ab899c3aabb071 [file] [log] [blame]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package browserdevicedb
import (
"context"
"entgo.io/ent/dialect/sql/sqljson"
"go.chromium.org/luci/common/errors"
"go.chromium.org/infra/fleetconsole/api/fleetconsolerpc"
"go.chromium.org/infra/fleetconsole/internal/database"
"go.chromium.org/infra/fleetconsole/internal/database/queryutils"
"go.chromium.org/infra/fleetconsole/internal/ent/entx"
ent "go.chromium.org/infra/fleetconsole/internal/ent/generated"
"go.chromium.org/infra/fleetconsole/internal/ent/generated/browserdevice"
"go.chromium.org/infra/fleetconsole/internal/ent/generated/migrate"
"go.chromium.org/infra/fleetconsole/internal/swarmingclient"
)
type DeviceCounts struct {
Total int32 `sql:"total"`
Alive int32 `sql:"alive"`
Dead int32 `sql:"dead"`
Quarantined int32 `sql:"quarantined"`
Maintenance int32 `sql:"maintenance"`
}
// CountDevices calculates browser devices related metrics.
func CountDevices(ctx context.Context, filter string, realms []string) (*fleetconsolerpc.CountBrowserDevicesResponse, error) {
var rows []DeviceCounts
p, err := queryutils.ToEntPredicate(filter, migrate.BrowserDevicesTable)
if err != nil {
return nil, errors.Fmt("failed to parse filter: %w", err)
}
jsonPath := sqljson.Path("state")
database.GetEntClient(ctx).BrowserDevice.
Query().
Where(p).
Where(entx.RealmFilter(browserdevice.FieldRealm, realms)).
Aggregate(
ent.As(ent.Count(), "total"),
ent.As(entx.CountIf(sqljson.ValueContains(browserdevice.FieldSwarmingLabels, string(swarmingclient.Alive), jsonPath)), string(swarmingclient.Alive)),
ent.As(entx.CountIf(sqljson.ValueContains(browserdevice.FieldSwarmingLabels, string(swarmingclient.Dead), jsonPath)), string(swarmingclient.Dead)),
ent.As(entx.CountIf(sqljson.ValueContains(browserdevice.FieldSwarmingLabels, string(swarmingclient.Quarantined), jsonPath)), string(swarmingclient.Quarantined)),
ent.As(entx.CountIf(sqljson.ValueContains(browserdevice.FieldSwarmingLabels, string(swarmingclient.Maintenance), jsonPath)), string(swarmingclient.Maintenance))).
Scan(ctx, &rows)
if err != nil {
return nil, err
}
if len(rows) == 0 {
return &fleetconsolerpc.CountBrowserDevicesResponse{}, nil
}
result := rows[0]
return &fleetconsolerpc.CountBrowserDevicesResponse{
Total: result.Total,
SwarmingState: &fleetconsolerpc.SwarmingStateCounts{
Alive: result.Alive,
Dead: result.Dead,
Quarantined: result.Quarantined,
Maintenance: result.Maintenance,
},
}, nil
}