3333from orangecanvas .registry import cache
3434from orangecanvas .application .application import CanvasApplication
3535from orangecanvas .application .outputview import TextStream , ExceptHook
36+ from orangecanvas .document .usagestatistics import UsageStatistics
3637from orangecanvas .gui .splashscreen import SplashScreen
3738from orangecanvas import config as canvasconfig
3839from orangecanvas .main import (
4647from Orange .canvas .utils .overlay import NotificationWidget , NotificationOverlay
4748from Orange .canvas .mainwindow import MainWindow
4849from Orange .widgets import gui
50+ from Orange .version import version as current , release as is_release
4951
5052
5153log = logging .getLogger (__name__ )
5254
55+ statistics_server_url = os .getenv (
56+ 'ORANGE_STATISTICS_API_URL' , "https://orange.biolab.si/usage-statistics"
57+ )
58+
5359
5460def make_sql_logger (level = logging .INFO ):
5561 sql_log = logging .getLogger ('sql_log' )
@@ -111,6 +117,7 @@ def handle_permission_response(button):
111117 if permDialog .buttonRole (button ) != permDialog .DismissRole :
112118 settings .setValue ("error-reporting/permission-requested" , True )
113119 if permDialog .buttonRole (button ) == permDialog .AcceptRole :
120+ UsageStatistics .set_enabled (True )
114121 settings .setValue ("error-reporting/send-statistics" , True )
115122
116123 permDialog .clicked .connect (handle_permission_response )
@@ -127,8 +134,6 @@ def check_for_updates():
127134 if check_updates and time .time () - last_check_time > ONE_DAY :
128135 settings .setValue ('startup/last-update-check-time' , int (time .time ()))
129136
130- from Orange .version import version as current
131-
132137 class GetLatestVersion (QThread ):
133138 resultReady = pyqtSignal (str )
134139
@@ -191,6 +196,54 @@ def handle_click(b):
191196 return None
192197
193198
199+ def send_usage_statistics ():
200+ def send_statistics (url ):
201+ """Send the statistics to the remote at `url`"""
202+ import json
203+ import requests
204+ settings = QSettings ()
205+ if not settings .value ("error-reporting/send-statistics" , False ,
206+ type = bool ):
207+ log .info ("Not sending usage statistics (preferences setting)." )
208+ return
209+ if not UsageStatistics .is_enabled ():
210+ log .info ("Not sending usage statistics (disabled)." )
211+ return
212+
213+ usage = UsageStatistics ()
214+ data = usage .load ()
215+ data = [
216+ dict ({"Orange Version" : d .get ("Application Version" , "" )}, ** d )
217+ for d in data
218+ ]
219+ try :
220+ r = requests .post (url , files = {'file' : json .dumps (data )})
221+ if r .status_code != 200 :
222+ log .warning ("Error communicating with server while attempting to send "
223+ "usage statistics." )
224+ return
225+ # success - wipe statistics file
226+ log .info ("Usage statistics sent." )
227+ with open (usage .filename (), 'w' , encoding = "utf-8" ) as f :
228+ json .dump ([], f )
229+ except (ConnectionError , requests .exceptions .RequestException ):
230+ log .warning ("Connection error while attempting to send usage statistics." )
231+ except Exception :
232+ log .warning ("Failed to send usage statistics." )
233+
234+ class SendUsageStatistics (QThread ):
235+ def run (self ):
236+ try :
237+ send_statistics (statistics_server_url )
238+ except Exception : # pylint: disable=broad-except
239+ # exceptions in threads would crash Orange
240+ log .warning ("Failed to send usage statistics." )
241+
242+ thread = SendUsageStatistics ()
243+ thread .start ()
244+ return thread
245+
246+
194247def main (argv = None ):
195248 # Allow termination with CTRL + C
196249 signal .signal (signal .SIGINT , signal .SIG_DFL )
@@ -341,9 +394,13 @@ def onrequest(url):
341394 app .fileOpenRequest .connect (onrequest )
342395
343396 settings = QSettings ()
344-
345397 settings .setValue ('startup/launch-count' , settings .value ('startup/launch-count' , 0 , int ) + 1 )
346398
399+ if settings .value ("error-reporting/send-statistics" , False , type = bool ) \
400+ and is_release :
401+ UsageStatistics .set_enabled (True )
402+ log .info ("Enabling usage statistics tracking" )
403+
347404 stylesheet = options .stylesheet or defaultstylesheet
348405 stylesheet_string = None
349406
@@ -471,6 +528,7 @@ def show_message(message):
471528
472529 # local references prevent destruction
473530 update_check = check_for_updates ()
531+ send_stat = send_usage_statistics ()
474532
475533 # Tee stdout and stderr into Output dock
476534 log_view = canvas_window .output_view ()
@@ -504,6 +562,7 @@ def show_message(message):
504562
505563 del canvas_window
506564 del update_check
565+ del send_stat
507566
508567 app .processEvents ()
509568 app .flush ()
0 commit comments