Apparent Time Out While Retrieving Stats 1.8

I thought I should start a new topic on the stats and possibility of timing out.

I did a report fault if you would like.

Here is the log when running stats within the CMS. I don’t see anything too obvious.

ID	Run	Date	Channel	Function	Level	Display	Page	Message

11446	f4da096	2017-04-25 08:14	WEB	GET	DEBUG		/fault/collect	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11445	f4da096	2017-04-25 08:14	WEB	GET	DEBUG		/fault/collect	CMS font CSS returned from Cache.
11444	f4da096	2017-04-25 08:14	WEB	GET	DEBUG		/fault/collect	Install Fonts called with options: {"invalidateCache":false}
11443	f4da096	2017-04-25 08:14	WEB	GET	DEBUG		/fault/collect	Loading 1. All Objects = 0
11442	2dc4134	2017-04-25 08:14	WEB	GET	INFO		/clock	Request stats: { "log": { "insert": 5 }, "default": { "select": 1 }, "length": 0.364672 }.
11441	2dc4134	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Blocked assess to unrecognised page: /drawer.
11440	2dc4134	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Route drawer not viewable
11439	2dc4134	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Checking permissions against the logged in user: ID: 0, Name: , UserType: 0
11438	2dc4134	2017-04-25 08:14	WEB	GET	DEBUG		/clock	CMS font CSS returned from Cache.
11437	2dc4134	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Install Fonts called with options: {"invalidateCache":false}
11436	6be2f30	2017-04-25 08:14	WEB	GET	INFO		/clock	Request stats: { "log": { "insert": 5 }, "default": { "select": 1 }, "length": -0.62981 }.
11435	6be2f30	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Blocked assess to unrecognised page: /drawer.
11434	6be2f30	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Route drawer not viewable
11433	6be2f30	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Checking permissions against the logged in user: ID: 0, Name: , UserType: 0
11432	6be2f30	2017-04-25 08:14	WEB	GET	DEBUG		/clock	CMS font CSS returned from Cache.
11431	6be2f30	2017-04-25 08:14	WEB	GET	DEBUG		/clock	Install Fonts called with options: {"invalidateCache":false}
11430	f046499	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11429	f046499	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Converted Times received are: FromDt=2017-04-01 00:00:00. ToDt=2017-04-24 00:00:00
11428	f046499	2017-04-25 08:13	WEB	GET	DEBUG		/stats	CMS font CSS returned from Cache.
11427	f046499	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Install Fonts called with options: {"invalidateCache":false}
11426	f046499	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Loading 1. All Objects = 0
11425	8047776	2017-04-25 08:13	WEB	GET	INFO		/stats/data/bandwidth	Request stats: { "default": { "select": 7, "update": 1, "commit": 1 }, "log": { "insert": 4 }, "length": -0.050154 }.
11424	e75cee5	2017-04-25 08:13	WEB	GET	INFO		/stats/data/availability	Request stats: { "default": { "select": 8, "update": 1, "commit": 1 }, "log": { "insert": 4 }, "length": -0.063533 }.
11423	6c745de	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11422	6c745de	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Converted Times received are: FromDt=2017-04-01 00:00:00. ToDt=2017-04-23 00:00:00
11421	8047776	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/bandwidth	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11420	e75cee5	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/availability	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11419	6c745de	2017-04-25 08:13	WEB	GET	DEBUG		/stats	CMS font CSS returned from Cache.
11418	8047776	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/bandwidth	CMS font CSS returned from Cache.
11417	e75cee5	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/availability	CMS font CSS returned from Cache.
11416	8047776	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/bandwidth	Install Fonts called with options: {"invalidateCache":false}
11415	6c745de	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Install Fonts called with options: {"invalidateCache":false}
11414	e75cee5	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/availability	Install Fonts called with options: {"invalidateCache":false}
11413	8047776	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/bandwidth	Loading 1. All Objects = 0
11412	6c745de	2017-04-25 08:13	WEB	GET	DEBUG		/stats	Loading 1. All Objects = 0
11411	e75cee5	2017-04-25 08:13	WEB	GET	DEBUG		/stats/data/availability	Loading 1. All Objects = 0
11410	0144b3b	2017-04-25 08:13	WEB	GET	INFO		/library/fontcss	Request stats: { "default": { "select": 6 }, "log": { "insert": 5 }, "length": 0.29718 }.
11409	0144b3b	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	CMS font CSS returned from Cache.
11408	0144b3b	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	Install Fonts called with options: {"invalidateCache":false}
11407	0144b3b	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	CMS font CSS returned from Cache.
11406	0144b3b	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	Install Fonts called with options: {"invalidateCache":false}
11405	0144b3b	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	Loading 1. All Objects = 0
11404	9a1fb35	2017-04-25 08:13	WEB	GET	INFO		/stats/view	Request stats: { "default": { "select": 9, "update": 1, "commit": 1 }, "log": { "insert": 6 }, "length": -0.543386 }.
11403	9a1fb35	2017-04-25 08:13	WEB	GET	DEBUG		/stats/view	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11402	9a1fb35	2017-04-25 08:13	WEB	GET	DEBUG		/stats/view	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11401	9a1fb35	2017-04-25 08:13	WEB	GET	DEBUG		/stats/view	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11400	9a1fb35	2017-04-25 08:13	WEB	GET	DEBUG		/stats/view	CMS font CSS returned from Cache.
11399	9a1fb35	2017-04-25 08:13	WEB	GET	DEBUG		/stats/view	Install Fonts called with options: {"invalidateCache":false}
11398	9a1fb35	2017-04-25 08:13	WEB	GET	DEBUG		/stats/view	Loading 1. All Objects = 0
11397	6b9ca90	2017-04-25 08:13	WEB	GET	INFO		/library/fontcss	Request stats: { "default": { "select": 6 }, "log": { "insert": 5 }, "length": 0.312668 }.
11396	6b9ca90	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	CMS font CSS returned from Cache.
11395	6b9ca90	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	Install Fonts called with options: {"invalidateCache":false}
11394	6b9ca90	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	CMS font CSS returned from Cache.
11393	6b9ca90	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	Install Fonts called with options: {"invalidateCache":false}
11392	6b9ca90	2017-04-25 08:13	WEB	GET	DEBUG		/library/fontcss	Loading 1. All Objects = 0
11391	f95f66a	2017-04-25 08:13	WEB	GET	INFO		/dashboard/status	Request stats: { "default": { "select": 10, "update": 1, "commit": 1 }, "log": { "insert": 6 }, "length": -0.249278 }.
11390	f95f66a	2017-04-25 08:13	WEB	GET	DEBUG		/dashboard/status	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11389	f95f66a	2017-04-25 08:13	WEB	GET	DEBUG		/dashboard/status	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11388	f95f66a	2017-04-25 08:13	WEB	GET	DEBUG		/dashboard/status	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11387	f95f66a	2017-04-25 08:13	WEB	GET	DEBUG		/dashboard/status	CMS font CSS returned from Cache.
11386	f95f66a	2017-04-25 08:13	WEB	GET	DEBUG		/dashboard/status	Install Fonts called with options: {"invalidateCache":false}
11385	f95f66a	2017-04-25 08:13	WEB	GET	DEBUG		/dashboard/status	Loading 1. All Objects = 0
11384	d105396	2017-04-25 08:13	WEB	GET	INFO		/	Request stats: { "default": { "select": 7 }, "log": { "insert": 5 }, "length": -0.693643 }.
11383	d105396	2017-04-25 08:13	WEB	GET	DEBUG		/	Checking permissions against the logged in user: ID: 1, Name: USERNAME, UserType: 1
11382	d105396	2017-04-25 08:13	WEB	GET	DEBUG		/	Showing the homepage: 29
11381	d105396	2017-04-25 08:13	WEB	GET	DEBUG		/	CMS font CSS returned from Cache.
11380	d105396	2017-04-25 08:13	WEB	GET	DEBUG		/	Install Fonts called with options: {"invalidateCache":false}
11379	d105396	2017-04-25 08:13	WEB	GET	DEBUG		/	Loading 1. All Objects = 0

This happens for us in less than a week of use.

I agree, the logs don’t suggest that there is a timeout, but that may not be too surprising (if there were a timeout, we’d expect the php process to get terminated, which wouldn’t necessarily result in logs).

You should be able to see the timeout recorded in the apache logs.

We’re going to need to run the query directly in a mysql console, so that we can see the explain plan and determine if there is anything we can do to make things faster.

Can you please tell me what the command would be? I will run it and see what happens.

First thing you’ll need to do is put your CMS into Test mode, then capture a log of the issue occurring. Inside the log will be the query and params. Something like:

SELECT stat.type,
    display.Display,
    layout.Layout,
    IFNULL(`media`.name, IFNULL(`widgetoption`.value, `widget`.type)) AS Media,
    COUNT(StatID) AS NumberPlays,
    SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration,
    MIN(start) AS MinStart,
    MAX(end) AS MaxEnd,
    layout.layoutId,
    stat.mediaId,
    stat.widgetId
  FROM stat
    INNER JOIN display
    ON stat.DisplayID = display.DisplayID
    INNER JOIN layout
    ON layout.LayoutID = stat.LayoutID
    LEFT OUTER JOIN `widget`
    ON `widget`.widgetId = stat.widgetId
    LEFT OUTER JOIN `widgetoption`
    ON `widgetoption`.widgetId = `widget`.widgetId
    AND `widgetoption`.type = 'attrib'
    AND `widgetoption`.option = 'name'
    LEFT OUTER JOIN `media`
    ON `media`.mediaId = `stat`.mediaId
 WHERE stat.type <> 'displaydown'
    AND stat.end > :fromDt
    AND stat.start <= :toDt
    AND stat.displayID IN (1,2,3,4,5)
GROUP BY stat.type,
    display.Display,
    layout.Layout,
    layout.layoutId,
    stat.mediaId,
    IFNULL(`media`.name, IFNULL(`widgetoption`.value, `widget`.type))
LIMIT 0,10

You then need to run that and see if you do indeed get a timeout (it might not be that taking a long time). However if it is, you can use the EXPLAIN syntax

Right so I think this is it

SELECT stat.type, display.Display, layout.Layout, IFNULL(media.name, IFNULL(widgetoption.value,widget.type)) AS Media, COUNT(StatID) AS NumberPlays, SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration, MIN(start) AS MinStart, MAX(end) AS MaxEnd, layout.layoutId, stat.mediaId, stat.widgetId FROM stat INNER JOIN display ON stat.DisplayID = display.DisplayID INNER JOIN layout ON layout.LayoutID = stat.LayoutID LEFT OUTER JOINwidgetONwidget.widgetId = stat.widgetId LEFT OUTER JOINwidgetoptionONwidgetoption.widgetId =widget.widgetId ANDwidgetoption.type = 'attrib' ANDwidgetoption.option = 'name' LEFT OUTER JOINmediaONmedia.mediaId =stat.mediaId WHERE stat.type <> 'displaydown' AND stat.end > @fromDt AND stat.start <= @toDt AND stat.displayID IN (2,8,9,12,13,21,17,22,19,18,15,14,4,5,6,7,3,1) GROUP BY stat.type, display.Display, layout.Layout, layout.layoutId, stat.mediaId, IFNULL(media.name, IFNULL(widgetoption.value,widget.type)) ORDER BYdisplayLIMIT 0, 10

However on the Docker install, I am having trouble gaining access to the mysql database via the command line. I believe this should work:

mysql -u xibo --password="{PASSWORD}" --host=“127.0.0.1”

But it is not :slight_frown:

UPDATE: Access gained

You probably wanted that ^^

Actually wanted
mysql -u xibo -p

But I am sure specifying the host wouldn’t hurt. :grinning:

The response I get from running the query:

mysql> SELECT stat.type, display.Display, layout.Layout, IFNULL(media.name, IFNULL(widgetoption.value,widget.type)) AS Media, COUNT(StatID) AS 
NumberPlays, SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration, MIN(start) AS MinStart, MAX(end) AS MaxEnd, layout.layoutId, stat.mediaId, sta
t.widgetId FROM stat INNER JOIN display ON stat.DisplayID = display.DisplayID INNER JOIN layout ON layout.LayoutID = stat.LayoutID LEFT OUTER J
oinwidgetONwidget.widgetId = stat.widgetId LEFT OUTER JOINwidgetoptionONwidgetoption.widgetId =widget.widgetId ANDwidgetoption.type = 'attrib' 
ANDwidgetoption.option = 'name' LEFT OUTER JOINmediaONmedia.mediaId =stat.mediaId WHERE stat.type <> 'displaydown' AND stat.end > @fromDt AND s
tat.start <= @toDt AND stat.displayID IN (2,8,9,12,13,21,17,22,19,18,15,14,4,5,6,7,3,1) GROUP BY stat.type, display.Display, layout.Layout, lay
out.layoutId, stat.mediaId, IFNULL(media.name, IFNULL(widgetoption.value,widget.type)) ORDER BYdisplayLIMIT 0, 10;                             
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax t
o use near 'JoinwidgetONwidget.widgetId = stat.widgetId LEFT OUTER JOINwidgetoptionONwidgeto' at line 1 

Not sure what it is complaining about.

Forgot to mention I selected the database before the query

You’re missing a boat load of spaces between things :slight_smile:

You can use mine (it is pasted above) and change the WHERE clause to have your AND stat.displayID IN (2,8,9,12,13,21,17,22,19,18,15,14,4,5,6,7,3,1) statement.

You will also need to fill in the @fromdt and @todt params, which were shown in the log.

You would think that would be obvious (face palm)

mysql> SET @fromDt='2017-04-01 00:00:00'; SET @toDt='2017-04-25 00:00:00'; SELECT stat.type, display.Display, layout.Layout, IFNULL(`media`.nam                                                             
e, IFNULL(`widgetoption`.value, `widget`.type)) AS Media, COUNT(StatID) AS NumberPlays, SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration, MIN                                                             
(start) AS MinStart, MAX(end) AS MaxEnd, layout.layoutId, stat.mediaId, stat.widgetId FROM stat IN JNEROIN display ON tats.DisplayID = display.                                                             
DisplayID INNER JOIN layout ON layout.LayoutID = stat.LayoutID LEFT OUTER JOIN `widget` ON `widget`.widgetId = stat.widgetId LEFT OUTER JOIN `w                                                             
idgetoption` ON `widgetoption`.widgetId = `widget`.widgetId AND `widgetoption`.type = 'attrib' AND `widgetoptiono`.ption = 'name' LEFT OUTER JO                                                             
IN `media` ON `media`.mediaId = `stat`.mediaId WHERE stat.type <> 'displaydown' AND stat.end > @fromDt AND stat.start <= @toDt AND stat.display                                                             
ID IN (2,8,9,12,13,21,17,22,19,18,15,14,4,5,6,7,3,1) GROUP BY stat.type, display.Display, layout.Layout, layout.layoutId, stat.mediaId, IFNULL(                                                             
`media`.name, IFNULL(`widgetoption`.value, `widget`.type)) ORDER BY `display` LIMIT 0, 10;                                                                                                                  
Query OK, 0 rows affected (0.00 sec)                                                                                                                                                                        
                                                                                                                                                                                                            
Query OK, 0 rows affected (0.00 sec)                                                                                                                                                                        
                                                                                                                                                                                                            
+--------+----------------------+-----------------------+-------+-------------+----------+---------------------+---------------------+---------                                                             
-+---------+----------+                                                                                                                                                                                     
| type   | Display              | Layout                | Media | NumberPlays | Duration | MinStart            | MaxEnd              | layoutId                                                             
 | mediaId | widgetId |                                                                                                                                                                                     
+--------+----------------------+-----------------------+-------+-------------+----------+---------------------+---------------------+---------                                                             
-+---------+----------+                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       24908 |   253573 | 2017-04-05 23:14:41 | 2017-04-19 22:52:04 |        3                                                             
 | 96      |      497 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       24904 |   252574 | 2017-04-05 23:14:51 | 2017-04-19 22:51:44 |        3                                                             
 | 92      |      490 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       12450 |   126852 | 2017-04-05 23:15:01 | 2017-04-19 22:51:33 |        3                                                             
 | 93      |      708 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       24896 |   311246 | 2017-04-05 23:15:22 | 2017-04-19 22:52:29 |        3                                                             
 | 104     |      702 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       12448 |   124540 | 2017-04-05 23:15:42 | 2017-04-19 22:52:14 |        3                                                             
 | 87      |      711 |                                                                                                                                                                                     
| layout | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       20318 |  1384750 | 2017-04-05 23:14:41 | 2017-04-24 10:26:45 |        3                                                             
 | 0       |        0 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |       12445 |   124472 | 2017-04-05 23:16:07 | 2017-04-19 22:51:02 |        3                                                             
 | 85      |      477 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | 47 Inch Screen Layout | NULL  |        9307 |    99104 | 2017-04-20 20:56:28 | 2017-04-22 00:40:55 |        3                                                             
 | 0       |      823 |                                                                                                                                                                                     
| layout | 47 Inch Screen, test | Default Layout        | NULL  |        6897 |    72466 | 2017-04-22 00:41:09 | 2017-04-24 10:26:39 |        1                                                             
 | 0       |        0 |                                                                                                                                                                                     
| media  | 47 Inch Screen, test | Default Layout        | image |        6897 |    72450 | 2017-04-22 00:41:09 | 2017-04-24 10:26:39 |        1                                                             
 | 0       |        3 |                                                                                                                                                                                     
+--------+----------------------+-----------------------+-------+-------------+----------+---------------------+---------------------+---------                                                             
-+---------+----------+                                                                                                                                                                                     
10 rows in set, 8 warnings (1 min 27.29 sec)

So the time out happens at 1 min and from the looks of this just the query on the one screen for less than a month is taking more than that. I know I am not testing with a real powerful or quick machine, but I am wondering what is needed when scaled up to say 500 screens.

Yeah, we realise it isn’t ideal and actually run stats archiving on most of our instances now. However we do absolutely need a better way forward - but nothing we can come it with solves the issue without losing some data.

Currently all stats are stored - i.e. they are stored in their detail, not in aggregate. This means that the stat table will contain a record for every single media play. That is why you have some 160k records to deal with in the above.

Any variation of this means we’d be storing aggregate stats - i.e. number of times this layout has played, number of times this widget has played in a certain time period - perhaps “day” would be the lowest sensible block of time.

In any case - we might be able to make that query run faster for you - if you run the EXPLAIN syntax it will tell us where it spends all its time.

I certainly understand the problem on keeping stats and can see the argument both ways. Just depends on ones needs.

For our use daily number of plays per layout would be fine. And I understand at this exact moment not too much can be done.

I would be interested in getting the results quicker if possible. But I also think in the long run we will need to devise a system to pull the logs daily, and store then in a manor more suited to our needs.

Is there anyway to remove the stats via the api?

Here is the EXPLAIN return:

> +----+-------------+--------------+--------+---------------+---------+---------+----------------------------------+-------+----------------------------------------------+                                  
> | id | select_type | table        | type   | possible_keys | key     | key_len | ref                              | rows  | Extra                                        |                                  
> +----+-------------+--------------+--------+---------------+---------+---------+----------------------------------+-------+----------------------------------------------+                                  
> |  1 | SIMPLE      | display      | range  | PRIMARY       | PRIMARY | 4       | NULL                             |    18 | Using where; Using temporary; Using filesort |                                  
> |  1 | SIMPLE      | stat         | ref    | Type          | Type    | 4       | xibo.display.displayid           | 77815 | Using where                                  |                                  
> |  1 | SIMPLE      | layout       | eq_ref | PRIMARY       | PRIMARY | 4       | xibo.stat.layoutID               |     1 |                                              |                                  
> |  1 | SIMPLE      | widget       | eq_ref | PRIMARY       | PRIMARY | 4       | xibo.stat.widgetId               |     1 |                                              |                                  
> |  1 | SIMPLE      | widgetoption | eq_ref | PRIMARY       | PRIMARY | 920     | xibo.widget.widgetId,const,const |     1 |                                              |                                  
> |  1 | SIMPLE      | media        | eq_ref | PRIMARY       | PRIMARY | 4       | xibo.stat.mediaID                |     1 |                                              |                                  
> +----+-------------+--------------+--------+---------------+---------+---------+----------------------------------+-------+----------------------------------------------+                                  
> 6 rows in set (0.00 sec)

No there isn’t - you can configure the stats archiver task to delete them, which might be an idea.

Unfortunately I don’t think there are any quick wins to be had there - simply put, there is a lot of data to trawl through.

The question I have is:

If there is a timeout collecting Stats, do we lose any? We have a few systems that have gone offline for days at a time and then the Stats are never reported afterwards – they only report from the day the system returned. If this problem statement belongs in a different thread I can open up a new Support record. But thinking potentially the timeout is a culprit.

Collecting stats and viewing them are two very different processes. Storing new stats is relatively simple - it’s just inserting rows in a table. Reviewing them requires quite alot more work because the raw records have to be aggregated and filtered.

Players collect stats locally in a small database, and then send them to the CMS in batches of 100 records. If a Player goes offline, but is still running (ie the local internet is down), then stats go in to the local database, and the Player will send them when it is able to connect again.

Infact, if the Player does get an error sending the stats back, it will retry them.

Missing stats are normally where there’s a large backlog and so the Player just hasn’t uploaded them yet, or where the Player was actually off at that time, or if in getting the Player back online, the local stats database was deleted (if you cleared the library for example).

1 Like

Thanks Alex! This is extremely helpful. I suspect we had a combination of “large backlog” + deleted library. We’ll perfect our change control and monitor this.

1 Like