Update gam print crostelemetry

This commit is contained in:
Ross Scroggs
2026-05-29 18:32:49 -07:00
parent b3acdf5955
commit 22d70ca2c3
3 changed files with 68 additions and 16 deletions

View File

@@ -2725,25 +2725,30 @@ gam <CrOSTypeEntity> get devicefile [select <DeviceFileEntity>] [targetfolder <F
Print telemetry data for specified CrOS devices. Print telemetry data for specified CrOS devices.
<CrOSTelemetryFieldName> ::= <CrOSTelemetryFieldName> ::=
appreport|
audiostatusreport| audiostatusreport|
batteryinfo| batteryinfo|
batterystatusreport| batterystatusreport|
bootPerformancereport| bootperformancereport|
cpuinfo| cpuinfo|
cpustatusreport| cpustatusreport|
customer| customer|
deviceid| deviceid|
graphicsinfo| graphicsinfo|
graphicsstatusreport| graphicsstatusreport|
heartbeatstatusreport|
kioskappstatusreport|
memoryinfo| memoryinfo|
memorystatusreport| memorystatusreport|
name| name|
networkbandwidthreport|
networkdiagnosticsreport| networkdiagnosticsreport|
networkinfo| networkinfo|
networkstatusreport| networkstatusreport|
orgunitid| orgunitid|
osupdatestatus| osupdatestatus|
peripheralsreport| peripheralsreport|
runtimecountersreport|
serialnumber| serialnumber|
storageinfo| storageinfo|
storagestatusreport| storagestatusreport|
@@ -2751,20 +2756,22 @@ Print telemetry data for specified CrOS devices.
<CrOSTelemetryFieldNameList> ::= "<CrOSTelemetryFieldName>(,<CrOSTelemetryFieldName>)*" <CrOSTelemetryFieldNameList> ::= "<CrOSTelemetryFieldName>(,<CrOSTelemetryFieldName>)*"
<CrOSTelemetryListFieldName> ::= <CrOSTelemetryListFieldName> ::=
appreport|
audiostatusreport| audiostatusreport|
batteryinfo|
batterystatusreport| batterystatusreport|
bootperformancereport| bootperformancereport|
cpuinfo|
cpustatusreport| cpustatusreport|
graphicsstatusreport| graphicsstatusreport|
heartbeatstatusreport|
kioskappstatusreport|
memorystatusreport| memorystatusreport|
networkbandwidthreport|
networkdiagnosticsreport| networkdiagnosticsreport|
networkstatusreport| networkstatusreport|
osupdatestatus| osupdatestatus|
peripheralsreport| peripheralsreport|
storagestatusreport| runtimecountersreport|
thunderboltinfo storagestatusreport
<CrOSTelemetryListFieldNameList> ::= "<CrOSTelemetryListFieldName>(,<CrOSTelemetryLIstFieldName>)*" <CrOSTelemetryListFieldNameList> ::= "<CrOSTelemetryListFieldName>(,<CrOSTelemetryLIstFieldName>)*"
gam info crostelemetry <SerialNumber> gam info crostelemetry <SerialNumber>
@@ -2781,7 +2788,7 @@ gam show crostelemetry
gam print crostelemetry [todrive <ToDriveAttribute>*] gam print crostelemetry [todrive <ToDriveAttribute>*]
[(ou|org|orgunit|ou_and_children <OrgUnitItem>)|(cros_sn <SerialNumber>)|(filter <String>)] [(ou|org|orgunit|ou_and_children <OrgUnitItem>)|(cros_sn <SerialNumber>)|(filter <String>)]
<CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>] <CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>]
[reverselists <CrOSTelemetryListFieldNameList>] [reverselists <CrOSTelemetryListFieldNameList>] [oneitemperrow]
[start <Date>] [end <Date>] [listlimit <Number>] [start <Date>] [end <Date>] [listlimit <Number>]
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]

View File

@@ -1,3 +1,17 @@
7.44.01
Added option `oneitemperrow` to `gam print crostelemetry` to have each of a device's
report field entries displayed on a separate row with all of the other device fields.
Added additional fields to `<CrOSTelemetryFieldName>`and `<CrOSTelemetryListFieldName>`:
```
appreport
heartbeatstatusreport
kioskappstatusreport
networkbandwidthreport
runtimecountersreport
```
7.44.00 7.44.00
Added support for User data `archivalTime` and `suspensionTime` that is available Added support for User data `archivalTime` and `suspensionTime` that is available

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.44.00' __version__ = '7.44.01'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
# pylint: disable=wrong-import-position # pylint: disable=wrong-import-position
@@ -25827,6 +25827,7 @@ def doPrintCrOSEntity(entityList):
doPrintCrOSActivity(entityList) doPrintCrOSActivity(entityList)
CROS_TELEMETRY_FIELDS_CHOICE_MAP = { CROS_TELEMETRY_FIELDS_CHOICE_MAP = {
'appreport': 'appReport',
'audiostatusreport': 'audioStatusReport', 'audiostatusreport': 'audioStatusReport',
'batteryinfo': 'batteryInfo', 'batteryinfo': 'batteryInfo',
'batterystatusreport': 'batteryStatusReport', 'batterystatusreport': 'batteryStatusReport',
@@ -25837,35 +25838,41 @@ CROS_TELEMETRY_FIELDS_CHOICE_MAP = {
'deviceid': 'deviceId', 'deviceid': 'deviceId',
'graphicsinfo': 'graphicsInfo', 'graphicsinfo': 'graphicsInfo',
'graphicsstatusreport': 'graphicsStatusReport', 'graphicsstatusreport': 'graphicsStatusReport',
'heartbeatstatusreport': 'heartbeatStatusReport',
'kioskappstatusreport': 'kioskAppStatusReport',
'memoryinfo': 'memoryInfo', 'memoryinfo': 'memoryInfo',
'memorystatusreport': 'memoryStatusReport', 'memorystatusreport': 'memoryStatusReport',
'name': 'name', 'name': 'name',
'networkinfo': 'networkInfo', 'networkbandwidthreport': 'networkBandwidthReport',
'networkdiagnosticsreport': 'networkDiagnosticsReport', 'networkdiagnosticsreport': 'networkDiagnosticsReport',
'networkinfo': 'networkInfo',
'networkstatusreport': 'networkStatusReport', 'networkstatusreport': 'networkStatusReport',
'orgunitid': 'orgUnitId', 'orgunitid': 'orgUnitId',
'osupdatestatus': 'osUpdateStatus', 'osupdatestatus': 'osUpdateStatus',
'peripheralsreport': 'peripheralsReport', 'peripheralsreport': 'peripheralsReport',
'runtimecountersreport': 'runtimeCountersReport',
'serialnumber': 'serialNumber', 'serialnumber': 'serialNumber',
'storageinfo': 'storageInfo', 'storageinfo': 'storageInfo',
'storagestatusreport': 'storageStatusReport', 'storagestatusreport': 'storageStatusReport',
'thunderboltinfo': 'thunderboltInfo', 'thunderboltinfo': 'thunderboltInfo',
} }
CROS_TELEMETRY_LIST_FIELDS_CHOICE_MAP = { CROS_TELEMETRY_LIST_FIELDS_CHOICE_MAP = {
'appreport': 'appReport',
'audiostatusreport': 'audioStatusReport', 'audiostatusreport': 'audioStatusReport',
'batteryinfo': 'batteryInfo',
'batterystatusreport': 'batteryStatusReport', 'batterystatusreport': 'batteryStatusReport',
'bootperformancereport': 'bootPerformanceReport', 'bootperformancereport': 'bootPerformanceReport',
'cpuinfo': 'cpuInfo',
'cpustatusreport': 'cpuStatusReport', 'cpustatusreport': 'cpuStatusReport',
'graphicsstatusreport': 'graphicsStatusReport', 'graphicsstatusreport': 'graphicsStatusReport',
'heartbeatstatusreport': 'heartbeatStatusReport',
'kioskappstatusreport': 'kioskAppStatusReport',
'memorystatusreport': 'memoryStatusReport', 'memorystatusreport': 'memoryStatusReport',
'networkbandwidthreport': 'networkBandwidthReport',
'networkdiagnosticsreport': 'networkDiagnosticsReport', 'networkdiagnosticsreport': 'networkDiagnosticsReport',
'networkstatusreport': 'networkStatusReport', 'networkstatusreport': 'networkStatusReport',
'osupdatestatus': 'osUpdateStatus', 'osupdatestatus': 'osUpdateStatus',
'peripheralsreport': 'peripheralsReport', 'peripheralsreport': 'peripheralsReport',
'runtimecountersreport': 'runtimeCountersReport',
'storagestatusreport': 'storageStatusReport', 'storagestatusreport': 'storageStatusReport',
'thunderboltinfo': 'thunderboltInfo',
} }
CROS_TELEMETRY_SCALAR_FIELDS = ['deviceId', 'serialNumber', 'customer', 'name', 'orgUnitId', 'orgUnitPath'] CROS_TELEMETRY_SCALAR_FIELDS = ['deviceId', 'serialNumber', 'customer', 'name', 'orgUnitId', 'orgUnitPath']
@@ -25887,7 +25894,7 @@ CROS_TELEMETRY_TIME_OBJECTS = {'reportTime', 'lastUpdateTime', 'lastUpdateCheckT
# gam print crostelemetry [todrive <ToDriveAttribute>*] # gam print crostelemetry [todrive <ToDriveAttribute>*]
# [(ou|org|orgunit|ou_and_children <OrgUnitItem>)|(cros_sn <SerialNumber>)|(filter <String>)] # [(ou|org|orgunit|ou_and_children <OrgUnitItem>)|(cros_sn <SerialNumber>)|(filter <String>)]
# <CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>] # <CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>]
# [reverselists <CrOSTelemetryListFieldNameList>] # [reverselists <CrOSTelemetryListFieldNameList>] [oneitemperrow]
# [start <Date>] [end <Date>] [listlimit <Number>] # [start <Date>] [end <Date>] [listlimit <Number>]
# [formatjson [quotechar <Character>]] # [formatjson [quotechar <Character>]]
def doInfoPrintShowCrOSTelemetry(): def doInfoPrintShowCrOSTelemetry():
@@ -25928,13 +25935,32 @@ def doInfoPrintShowCrOSTelemetry():
def _printDevice(device): def _printDevice(device):
_cleanDevice(device) _cleanDevice(device)
if not FJQC.formatJSON: if FJQC.formatJSON:
csvPF.WriteRowTitles(flattenJSON(device, timeObjects=CROS_TELEMETRY_TIME_OBJECTS))
else:
if (not csvPF.rowFilter and not csvPF.rowDropFilter) or csvPF.CheckRowTitles(flattenJSON(device, timeObjects=CROS_TELEMETRY_TIME_OBJECTS)): if (not csvPF.rowFilter and not csvPF.rowDropFilter) or csvPF.CheckRowTitles(flattenJSON(device, timeObjects=CROS_TELEMETRY_TIME_OBJECTS)):
csvPF.WriteRowNoFilter({'deviceId': device['deviceId'], csvPF.WriteRowNoFilter({'deviceId': device['deviceId'],
'JSON': json.dumps(cleanJSON(device, timeObjects=CROS_TELEMETRY_TIME_OBJECTS), 'JSON': json.dumps(cleanJSON(device, timeObjects=CROS_TELEMETRY_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)}) ensure_ascii=False, sort_keys=True)})
return
if not oneItemPerRow:
csvPF.WriteRowTitles(flattenJSON(device, timeObjects=CROS_TELEMETRY_TIME_OBJECTS))
return
listLens = {}
maxLen = 0
for field in CROS_TELEMETRY_LIST_FIELDS_CHOICE_MAP.values():
if field in device:
listLens[field] = len(device[field])
if listLens[field] > maxLen:
maxLen = listLens[field]
baserow = {}
for field in CROS_TELEMETRY_SCALAR_FIELDS:
if field in device:
baserow[field] = device[field]
for i in range(maxLen):
row = baserow.copy()
for field, fieldLen in listLens.items():
if i < fieldLen:
flattenJSON({field: device[field][i]}, flattened=row, timeObjects=CROS_TELEMETRY_TIME_OBJECTS)
csvPF.WriteRowTitles(row)
def _showDevice(device, i=0, count=0): def _showDevice(device, i=0, count=0):
_cleanDevice(device) _cleanDevice(device)
@@ -25961,11 +25987,12 @@ def doInfoPrintShowCrOSTelemetry():
Act.Set(Act.SHOW) Act.Set(Act.SHOW)
else: else:
pfilters = [] pfilters = []
csvPF = CSVPrintFile(['deviceId'], CROS_TELEMETRY_SCALAR_FIELDS, CROS_TELEMETRY_LIST_FIELDS) if Act.csvFormat() else None csvPF = CSVPrintFile(['deviceId'], CROS_TELEMETRY_SCALAR_FIELDS) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
diskPercentOnly = showOrgUnitPath = False diskPercentOnly = showOrgUnitPath = False
listLimit = 0 listLimit = 0
startTime = endTime = None startTime = endTime = None
oneItemPerRow = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
@@ -26021,6 +26048,8 @@ def doInfoPrintShowCrOSTelemetry():
cd = buildGAPIObject(API.DIRECTORY) cd = buildGAPIObject(API.DIRECTORY)
elif myarg == 'storagepercentonly': elif myarg == 'storagepercentonly':
diskPercentOnly = True diskPercentOnly = True
elif csvPF and myarg == 'oneitemperrow':
oneItemPerRow = True
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, False) FJQC.GetFormatJSONQuoteChar(myarg, False)
if fieldsList: if fieldsList:
@@ -26032,6 +26061,8 @@ def doInfoPrintShowCrOSTelemetry():
readMask = ','.join(set(fieldsList)) readMask = ','.join(set(fieldsList))
if csvPF and FJQC.formatJSON: if csvPF and FJQC.formatJSON:
csvPF.SetJSONTitles(['deviceId', 'JSON']) csvPF.SetJSONTitles(['deviceId', 'JSON'])
elif csvPF and not oneItemPerRow:
csvPF.SetIndexedTitles(CROS_TELEMETRY_LIST_FIELDS)
if not pfilters: if not pfilters:
pfilters = [(None, 'All')] pfilters = [(None, 'All')]
for pfilter in pfilters: for pfilter in pfilters: