|
1 .. _healthreport_architecture: |
|
2 |
|
3 ============ |
|
4 Architecture |
|
5 ============ |
|
6 |
|
7 ``healthreporter.jsm`` contains the main interface for FHR, the |
|
8 ``HealthReporter`` type. An instance of this is created by the |
|
9 :ref:`data_reporting_service`. |
|
10 |
|
11 ``providers.jsm`` contains numerous ``Metrics.Provider`` and |
|
12 ``Metrics.Measurement`` used for collecting application metrics. If you |
|
13 are looking for the FHR probes, this is where they are. |
|
14 |
|
15 Storage |
|
16 ======= |
|
17 |
|
18 Firefox Health Report stores data in 3 locations: |
|
19 |
|
20 * Metrics measurements and provider state is stored in a SQLite database |
|
21 (via ``Metrics.Storage``). |
|
22 * Service state (such as the IDs of documents uploaded) is stored in a |
|
23 JSON file on disk (via OS.File). |
|
24 * Lesser state and run-time options are stored in preferences. |
|
25 |
|
26 Preferences |
|
27 =========== |
|
28 |
|
29 Preferences controlling behavior of Firefox Health Report live in the |
|
30 ``datareporting.healthreport.*`` branch. |
|
31 |
|
32 Service and Data Control |
|
33 ------------------------ |
|
34 |
|
35 The follow preferences control behavior of the service and data upload. |
|
36 |
|
37 service.enabled |
|
38 Controls whether the entire health report service runs. The overall |
|
39 service performs data collection, storing, and submission. |
|
40 |
|
41 This is the primary kill switch for Firefox Health Report |
|
42 outside of the build system variable. i.e. if you are using an |
|
43 official Firefox build and wish to disable FHR, this is what you |
|
44 should set to false to prevent FHR from not only submitting but |
|
45 also collecting data. |
|
46 |
|
47 uploadEnabled |
|
48 Whether uploading of data is enabled. This is the preference the |
|
49 checkbox in the preferences UI reflects. If this is |
|
50 disabled, FHR still collects data - it just doesn't upload it. |
|
51 |
|
52 service.loadDelayMsec |
|
53 How long (in milliseconds) after initial application start should FHR |
|
54 wait before initializing. |
|
55 |
|
56 FHR may initialize sooner than this if the FHR service is requested. |
|
57 This will happen if e.g. the user goes to ``about:healthreport``. |
|
58 |
|
59 service.loadDelayFirstRunMsec |
|
60 How long (in milliseconds) FHR should wait to initialize on first |
|
61 application run. |
|
62 |
|
63 FHR waits longer than normal to initialize on first application run |
|
64 because first-time initialization can use a lot of I/O to initialize |
|
65 the SQLite database and this I/O should not interfere with the |
|
66 first-run user experience. |
|
67 |
|
68 documentServerURI |
|
69 The URI of a Bagheera server that FHR should interface with for |
|
70 submitting documents. |
|
71 |
|
72 You typically do not need to change this. |
|
73 |
|
74 documentServerNamespace |
|
75 The namespace on the document server FHR should upload documents to. |
|
76 |
|
77 You typically do not need to change this. |
|
78 |
|
79 infoURL |
|
80 The URL of a page containing more info about FHR, it's privacy |
|
81 policy, etc. |
|
82 |
|
83 about.reportUrl |
|
84 The URL to load in ``about:healthreport``. |
|
85 |
|
86 service.providerCategories |
|
87 A comma-delimited list of category manager categories that contain |
|
88 registered ``Metrics.Provider`` records. Read below for how provider |
|
89 registration works. |
|
90 |
|
91 If the entire service is disabled, you lose data collection. This means |
|
92 that **local** data analysis won't be available because there is no data |
|
93 to analyze! Keep in mind that Firefox Health Report can be useful even |
|
94 if it's not submitting data to remote servers! |
|
95 |
|
96 Logging |
|
97 ------- |
|
98 |
|
99 The following preferences allow you to control the logging behavior of |
|
100 Firefox Health Report. |
|
101 |
|
102 logging.consoleEnabled |
|
103 Whether to write log messages to the web console. This is true by |
|
104 default. |
|
105 |
|
106 logging.consoleLevel |
|
107 The minimum log level FHR messages must have to be written to the |
|
108 web console. By default, only FHR warnings or errors will be written |
|
109 to the web console. During normal/expected operation, no messages of |
|
110 this type should be produced. |
|
111 |
|
112 logging.dumpEnabled |
|
113 Whether to write log messages via ``dump()``. If true, FHR will write |
|
114 messages to stdout/stderr. |
|
115 |
|
116 This is typically only enabled when developing FHR. |
|
117 |
|
118 logging.dumpLevel |
|
119 The minimum log level messages must have to be written via |
|
120 ``dump()``. |
|
121 |
|
122 State |
|
123 ----- |
|
124 |
|
125 currentDaySubmissionFailureCount |
|
126 How many submission failures the client has encountered while |
|
127 attempting to upload the most recent document. |
|
128 |
|
129 lastDataSubmissionFailureTime |
|
130 The time of the last failed document upload. |
|
131 |
|
132 lastDataSubmissionRequestedTime |
|
133 The time of the last document upload attempt. |
|
134 |
|
135 lastDataSubmissionSuccessfulTime |
|
136 The time of the last successful document upload. |
|
137 |
|
138 nextDataSubmissionTime |
|
139 The time the next data submission is scheduled for. FHR will not |
|
140 attempt to upload a new document before this time. |
|
141 |
|
142 pendingDeleteRemoteData |
|
143 Whether the client currently has a pending request to delete remote |
|
144 data. If true, the client will attempt to delete all remote data |
|
145 before an upload is performed. |
|
146 |
|
147 FHR stores various state in preferences. |
|
148 |
|
149 Registering Providers |
|
150 ===================== |
|
151 |
|
152 Firefox Health Report providers are registered via the category manager. |
|
153 See ``HealthReportComponents.manifest`` for providers defined in this |
|
154 directory. |
|
155 |
|
156 Essentially, the category manager receives the name of a JS type and the |
|
157 URI of a JSM to import that exports this symbol. At run-time, the |
|
158 providers registered in the category manager are instantiated. |
|
159 |
|
160 Providers are registered via the category manager to make registration |
|
161 simple and less prone to errors. Any XPCOM component can create a |
|
162 category manager entry. Therefore, new data providers can be added |
|
163 without having to touch core Firefox Health Report code. Additionally, |
|
164 category manager registration means providers are more likely to be |
|
165 registered on FHR's terms, when it wants. If providers were registered |
|
166 in code at application run-time, there would be the risk of other |
|
167 components prematurely instantiating FHR (causing a performance hit if |
|
168 performed at an inopportune time) or semi-complicated code around |
|
169 observers or listeners. Category manager entries are only 1 line per |
|
170 provider and leave FHR in control: they are simple and safe. |
|
171 |
|
172 Document Generation and Lifecycle |
|
173 ================================= |
|
174 |
|
175 FHR will attempt to submit a JSON document containing data every 24 wall |
|
176 clock hours. |
|
177 |
|
178 At upload time, FHR will query the database for **all** information from |
|
179 the last 180 days and assemble this data into a JSON document. We |
|
180 attempt to upload this JSON document with a client-generated UUID to the |
|
181 configured server. |
|
182 |
|
183 Before we attempt upload, the generated UUID is stored in the JSON state |
|
184 file on local disk. At this point, the client assumes the document with |
|
185 that UUID has been successfully stored on the server. |
|
186 |
|
187 If the client is aware of other document UUIDs that presumably exist on |
|
188 the server, those UUIDs are sent with the upload request so the client |
|
189 can request those UUIDs be deleted. This helps ensure that each client |
|
190 only has 1 document/UUID on the server at any one time. |
|
191 |
|
192 Importance of Persisting UUIDs |
|
193 ------------------------------ |
|
194 |
|
195 The choices of how, where, and when document UUIDs are stored and updated |
|
196 are very important. One should not attempt to change things unless she |
|
197 has a very detailed understanding of why things are the way they are. |
|
198 |
|
199 The client is purposefully very conservative about forgetting about |
|
200 generated UUIDs. In other words, once a UUID is generated, the client |
|
201 deliberately holds on to that UUID until it's very confident that UUID |
|
202 is no longer stored on the server. The reason we do this is because |
|
203 *orphaned* documents/UUIDs on the server can lead to faulty analysis, |
|
204 such as over-reporting the number of Firefox installs that stop being |
|
205 used. |
|
206 |
|
207 When uploading a new UUID, we update the state and save the state file |
|
208 to disk *before* an upload attempt because if the upload succeeds but |
|
209 the response never makes it back to the client, we want the client to |
|
210 know about the uploaded UUID so it can delete it later to prevent an |
|
211 orphan. |
|
212 |
|
213 We maintain a list of UUIDs locally (not simply the last UUID) because |
|
214 multiple upload attempts could fail the same way as the previous |
|
215 paragraph describes and we have no way of knowing which (if any) |
|
216 actually succeeded. The safest approach is to assume every document |
|
217 produced managed to get uploaded some how. |
|
218 |
|
219 We store the UUIDs on a file on disk and not anywhere else because we |
|
220 want storage to be robust. We originally stored UUIDs in preferences, |
|
221 which only flush to disk periodically. Writes to preferences were |
|
222 apparently getting lost. We switched to writing directly to files to |
|
223 eliminate this window. |