Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add statistics aggregation #531

Merged
merged 5 commits into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@ with the help of the `myriad_compile` tool. When producing blobs, the following
Example of command execution:

<path-to-openvino-folder>/deployment_tools/inference_engine/lib/intel64/myriad_compile -m ./ResNet50.xml -o ResNet50.blob -ip U8 -VPU_NUMBER_OF_SHAVES 4 -VPU_NUMBER_OF_CMX_SLICES 4

## Usage statistics

By default, the demo script will collect anonymous usage statistics during runtime. These include:
- Device-specific information (like mxid, connected cameras, device state and connection type)
- Environment-specific information (like OS type, python version, package versions)

We gather this data to better understand what environemnts are our users using, as well as assist better in support questions.

**All of the data we collect is anonymous and you can disable it at any time**. To do so, click on the "Misc" tab and disable sending the statistics.

## Reporting issues

Expand Down
32 changes: 31 additions & 1 deletion depthai_demo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import argparse
import json
import os
import sys
import time
Expand All @@ -14,6 +15,7 @@

from depthai_helpers.arg_manager import parseArgs
from depthai_helpers.config_manager import ConfigManager, DEPTHAI_ZOO, DEPTHAI_VIDEOS
from depthai_helpers.metrics import MetricManager
from depthai_helpers.version_check import checkRequirementsVersion
from depthai_sdk import FPSHandler, loadModule, getDeviceInfo, downloadYTVideo, Previews, resizeLetterbox
from depthai_sdk.managers import NNetManager, PreviewManager, PipelineManager, EncodingManager, BlobManager
Expand Down Expand Up @@ -58,9 +60,10 @@ def run_all(self, conf):
self.setup(conf)
self.run()

def __init__(self, displayFrames=True, onNewFrame = noop, onShowFrame = noop, onNn = noop, onReport = noop, onSetup = noop, onTeardown = noop, onIter = noop, shouldRun = lambda: True):
def __init__(self, displayFrames=True, onNewFrame = noop, onShowFrame = noop, onNn = noop, onReport = noop, onSetup = noop, onTeardown = noop, onIter = noop, shouldRun = lambda: True, collectMetrics=False):
self._openvinoVersion = None
self._displayFrames = displayFrames
self.toggleMetrics(collectMetrics)

self.onNewFrame = onNewFrame
self.onShowFrame = onShowFrame
Expand Down Expand Up @@ -89,6 +92,12 @@ def setCallbacks(self, onNewFrame=None, onShowFrame=None, onNn=None, onReport=No
if shouldRun is not None:
self.shouldRun = shouldRun

def toggleMetrics(self, enabled):
if enabled:
self.metrics = MetricManager()
else:
self.metrics = None

def setup(self, conf: ConfigManager):
print("Setting up demo...")
self._conf = conf
Expand Down Expand Up @@ -122,6 +131,8 @@ def setup(self, conf: ConfigManager):
self._pm.setNnManager(self._nnManager)

self._device = dai.Device(self._pm.pipeline.getOpenVINOVersion(), self._deviceInfo, usb2Mode=self._conf.args.usbSpeed == "usb2")
if self.metrics is not None:
self.metrics.reportDevice(self._device)
if self._deviceInfo.desc.protocol == dai.XLinkProtocol.X_LINK_USB_VSC:
print("USB Connection speed: {}".format(self._device.getUsbSpeed()))
self._conf.adjustParamsToDevice(self._device)
Expand Down Expand Up @@ -583,6 +594,7 @@ def onSetup(self, instance):
else:
self.signals.setDataSignal.emit(["countLabels", []])
self.signals.setDataSignal.emit(["depthEnabled", self.conf.useDepth])
self.signals.setDataSignal.emit(["statisticsAccepted", self.instance.metrics is not None])
self.signals.setDataSignal.emit(["modelChoices", sorted(self.conf.getAvailableZooModels(), key=cmp_to_key(lambda a, b: -1 if a == "mobilenet-ssd" else 1 if b == "mobilenet-ssd" else -1 if a < b else 1))])


Expand Down Expand Up @@ -620,7 +632,17 @@ def showError(self, error):
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec()

def setupDataCollection(self):
try:
with Path(".consent").open() as f:
accepted = json.load(f)["statistics"]
except:
accepted = True

self._demoInstance.toggleMetrics(accepted)

def start(self):
self.setupDataCollection()
self.running = True
self.worker = Worker(self._demoInstance, parent=self, conf=self.confManager, selectedPreview=self.selectedPreview)
self.worker.signals.updatePreviewSignal.connect(self.updatePreview)
Expand Down Expand Up @@ -757,6 +779,14 @@ def guiOnReloadDevices(self):
if len(devices) > 0:
self.worker.signals.setDataSignal.emit(["restartRequired", True])

def guiOnStaticticsConsent(self, value):
try:
with Path('.consent').open('w') as f:
json.dump({"statistics": value}, f)
except:
pass
self.worker.signals.setDataSignal.emit(["restartRequired", True])

def guiOnToggleColorEncoding(self, enabled, fps):
oldConfig = self.confManager.args.encode or {}
if enabled:
Expand Down
60 changes: 60 additions & 0 deletions depthai_helpers/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from datetime import datetime

import pyrebase
import depthai as dai

from log_system_information import make_sys_report


class MetricManager:
def __init__(self):
self.config = {
"apiKey": "AIzaSyDCrQs4SYUXZiN1qASxaiMU33YKSImp6kw",
"authDomain": "depthai-data.firebaseapp.com",
"databaseURL": "https://depthai-data-default-rtdb.firebaseio.com/",
"storageBucket": "depthai-data.appspot.com"
}

self.firebase = pyrebase.initialize_app(self.config)
self.db = self.firebase.database()
self.demo_table = self.db.child("demo")

def reportDevice(self, device: dai.Device):
try:
device_info = device.getDeviceInfo()
mxid = device_info.getMxId()
except:
return
try:
cameras = list(map(lambda camera: camera.name, device.getConnectedCameras()))
except:
cameras = []
try:
usb = device.getUsbSpeed().name
except:
usb = "None"
sys_report = make_sys_report(anonymous=True, skipUsb=True)
data = {
"mxid": mxid,
"timestamp": datetime.utcnow().isoformat(),
"system": sys_report,
"api": {
"version": dai.__version__
},
"device": {
"cameras": cameras,
"state": device_info.state.name,
"name": device_info.desc.name,
"platform": device_info.desc.platform.name,
"protocol": device_info.desc.protocol.name,
"usb": usb
}
}
self.demo_table.update({
f"devices/{mxid}": data
})

if __name__ == "__main__":
mm = MetricManager()
with dai.Device() as device:
mm.reportDevice(device)
4 changes: 4 additions & 0 deletions gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ def applyAndRestart(self):
def reloadDevices(self):
DemoQtGui.instance.guiOnReloadDevices()

@Slot(bool)
def toggleStatisticsConsent(self, value):
DemoQtGui.instance.guiOnStaticticsConsent(value)

@Slot(str)
def selectDevice(self, value):
DemoQtGui.instance.guiOnSelectDevice(value)
Expand Down
32 changes: 30 additions & 2 deletions gui/views/MiscProperties.qml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ ListView {
id: textField3
x: 110
y: 352
width: 227
width: 170
height: 27
bottomPadding: 7
placeholderText: qsTr("/path/to/report.csv")
Expand All @@ -203,7 +203,7 @@ ListView {
id: textField4
x: 116
y: 150
width: 227
width: 170
height: 27
bottomPadding: 7
placeholderText: qsTr("/path/to/output/directory/")
Expand All @@ -225,6 +225,34 @@ ListView {
verticalAlignment: Text.AlignVCenter
font.family: "Courier"
}

Text {
id: textOptions
x: 350
y: 8
width: 185
height: 30
color: "#ffffff"
text: qsTr("Demo options")
font.pixelSize: 26
horizontalAlignment: Text.AlignHCenter
font.family: "Courier"
font.styleName: "Regular"
}

Switch {
id: consentSwitch
x: 350
y: 40
checked: statisticsAccepted
width: 250
height: 27
text: qsTr("Send anonymous usage data")
bottomPadding: 5
onToggled: {
appBridge.toggleStatisticsConsent(consentSwitch.checked)
}
}
}
}
/*##^##
Expand Down
1 change: 1 addition & 0 deletions gui/views/root.qml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ ApplicationWindow {
property var restartRequired
property var deviceChoices
property var depthEnabled: true
property var statisticsAccepted: true

AppBridge {
id: appBridge
Expand Down
98 changes: 51 additions & 47 deletions log_system_information.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,57 @@
#!/usr/bin/env python3

import json
import subprocess
import sys
from pip._internal.operations.freeze import freeze
import platform

try:
import usb.core
except ImportError:
subprocess.check_call([sys.executable, "-m", "pip", "install", "pyusb"])
import usb.core


def get_usb():
speeds = ["Unknown", "Low", "Full", "High", "Super", "SuperPlus"]
format_hex = lambda val: f"{val:#0{6}x}"
try:
for dev in usb.core.find(find_all=True):
yield {
"port": dev.port_number,
"vendor_id": format_hex(dev.idVendor),
"product_id": format_hex(dev.idProduct),
"speed": speeds[dev.speed] if dev.speed < len(speeds) else dev.speed
}
except usb.core.NoBackendError:
yield "No USB backend found"


data = {
"architecture": ' '.join(platform.architecture()).strip(),
"machine": platform.machine(),
"platform": platform.platform(),
"processor": platform.processor(),
"python_build": ' '.join(platform.python_build()).strip(),
"python_compiler": platform.python_compiler(),
"python_implementation": platform.python_implementation(),
"python_version": platform.python_version(),
"release": platform.release(),
"system": platform.system(),
"version": platform.version(),
"win32_ver": ' '.join(platform.win32_ver()).strip(),
"uname": ' '.join(platform.uname()).strip(),
"packages": list(freeze(local_only=True)),
"usb": list(get_usb()),
}

with open("log_system_information.json", "w") as f:
json.dump(data, f, indent=4)

print(json.dumps(data, indent=4))
print("System info gathered successfully - saved as \"log_system_information.json\"")

def make_sys_report(anonymous=False, skipUsb=False):
def get_usb():
try:
import usb.core
except ImportError:
yield "NoLib"
return
speeds = ["Unknown", "Low", "Full", "High", "Super", "SuperPlus"]
format_hex = lambda val: f"{val:#0{6}x}"
try:
for dev in usb.core.find(find_all=True):
yield {
"port": dev.port_number,
"vendor_id": format_hex(dev.idVendor),
"product_id": format_hex(dev.idProduct),
"speed": speeds[dev.speed] if dev.speed < len(speeds) else dev.speed
}
except usb.core.NoBackendError:
yield "No USB backend found"

result = {
"architecture": ' '.join(platform.architecture()).strip(),
"machine": platform.machine(),
"platform": platform.platform(),
"processor": platform.processor(),
"python_build": ' '.join(platform.python_build()).strip(),
"python_compiler": platform.python_compiler(),
"python_implementation": platform.python_implementation(),
"python_version": platform.python_version(),
"release": platform.release(),
"system": platform.system(),
"version": platform.version(),
"win32_ver": ' '.join(platform.win32_ver()).strip(),
"packages": list(freeze(local_only=True)),
}

if not skipUsb:
result["usb"] = list(get_usb())
if not anonymous:
result["uname"] = ' '.join(platform.uname()).strip(),
return result


if __name__ == "__main__":
data = make_sys_report()
with open("log_system_information.json", "w") as f:
json.dump(data, f, indent=4)

print(json.dumps(data, indent=4))
print("System info gathered successfully - saved as \"log_system_information.json\"")
3 changes: 2 additions & 1 deletion requirements-optional.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
open3d==0.10.0.0; platform_machine != "armv6l" and platform_machine != "armv7l" and python_version < "3.9"
ffmpy3==0.2.4
ffmpy3==0.2.4
pyusb==1.2.1
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
requests==2.24.0
requests==2.11.1
argcomplete==1.12.1
opencv-python==4.5.4.58 ; platform_machine != "aarch64" and platform_machine != "armv6l" and platform_machine != "armv7l" and python_version == "3.10"
opencv-python==4.5.1.48 ; platform_machine != "aarch64" and platform_machine != "armv6l" and platform_machine != "armv7l" and python_version != "3.10"
Expand All @@ -10,3 +10,4 @@ opencv-contrib-python==4.4.0.46 ; platform_machine == "armv6l" or platform_machi
PySide6==6.2.0
--extra-index-url https://artifacts.luxonis.com/artifactory/luxonis-python-snapshot-local/
depthai==2.13.0.0
pyrebase==3.0.27