1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
|
namespace glean {
void glean_enable_logging();
// Initialize the logging system to send JSON messages to a file descriptor
// (Unix) or file handle (Windows).
//
// No-op on Android and iOS. Use `glean_enable_logging` instead.
void glean_enable_logging_to_fd(u64 fd);
// Initializes Glean.
//
// This will fully initialize Glean in a separate thread.
// It will return immediately.
void glean_initialize(InternalConfiguration cfg, ClientInfoMetrics client_info, OnGleanEvents callbacks);
/// Shuts down Glean in an orderly fashion.
void glean_shutdown();
// Creates and initializes a new Glean object for use in a subprocess.
//
// Importantly, this will not send any pings at startup, since that
// sort of management should only happen in the main process.
//
// Must only be used for an uploader process.
// The general API or any metrics API **will not work**.
boolean glean_initialize_for_subprocess(InternalConfiguration cfg);
void glean_set_upload_enabled(boolean enabled);
// Experiment reporting API
void glean_set_experiment_active(string experiment_id, string branch, record<DOMString, string> extra);
void glean_set_experiment_inactive(string experiment_id);
RecordedExperiment? glean_test_get_experiment_data(string experiment_id);
// Experimentation ID API
void glean_set_experimentation_id(string experimentation_id);
string? glean_test_get_experimentation_id();
// EXPERIMENTAL: Register a listener to receive notification of event recordings
//
// tag: String value used later to unregister the listener
// listener: An object which implements the GleanEventListener interface
void glean_register_event_listener(string tag, GleanEventListener listener);
// EXPERIMENTAL: Unregister a previously registered event listener
//
// tag: The tag used when registering the listener
void glean_unregister_event_listener(string tag);
// Server Knobs API
void glean_apply_server_knobs_config(string json);
boolean glean_set_debug_view_tag(string tag);
boolean glean_set_source_tags(sequence<string> tags);
void glean_set_log_pings(boolean value);
void glean_persist_ping_lifetime_data();
void glean_handle_client_active();
void glean_handle_client_inactive();
void glean_submit_ping_by_name(string ping_name, optional string? reason = null);
boolean glean_submit_ping_by_name_sync(string ping_name, optional string? reason = null);
void glean_set_test_mode(boolean enabled);
void glean_test_destroy_glean(boolean clear_stores, optional string? data_path = null);
void glean_set_dirty_flag(boolean flag);
PingUploadTask glean_get_upload_task();
UploadTaskAction glean_process_ping_upload_response(string uuid, UploadResult result);
};
// A `Cow<'static, str>`, but really it's always the owned part.
[Custom]
typedef string CowString;
// The Glean configuration.
//
// This exposes all configurable parameters to the SDK side.
// They should not be exposed directly to users of the SDK (except `upload_enabled`).
dictionary InternalConfiguration {
string data_path;
string application_id;
string language_binding_name;
boolean upload_enabled;
u32? max_events;
boolean delay_ping_lifetime_io;
string app_build;
boolean use_core_mps;
boolean trim_data_to_registered_pings;
LevelFilter? log_level;
PingRateLimit? rate_limit;
boolean enable_event_timestamps;
string? experimentation_id;
boolean enable_internal_pings;
};
// How to specify the rate pings may be uploaded before they are throttled.
dictionary PingRateLimit {
u64 seconds_per_interval;
u32 pings_per_interval;
};
// An enum representing the different logging levels for the `log` crate.
enum LevelFilter {
"Off",
"Error",
"Warn",
"Info",
"Debug",
"Trace",
};
// Values for the `client_info` metrics.
// The language SDK should collect them on `initialize` once.
// They will be re-used, e.g. when upload is toggled from off to on, to re-set them.
//
// See https://mozilla.github.io/glean/book/user/pings/index.html#the-client_info-section for details.
dictionary ClientInfoMetrics {
string app_build;
string app_display_version;
Datetime app_build_date;
string architecture;
string os_version;
string? channel = null;
string? locale = null;
string? device_manufacturer = null;
string? device_model = null;
string? android_sdk_version = null;
i64? windows_build_number = null;
};
[Error]
enum CallbackError {
"UnexpectedError",
};
// A callback object, that is stored within the core logic for the entire lifetime of the application.
//
// This is used to trigger certain actions that need to happen on the foreign-language side.
callback interface OnGleanEvents {
// Initialization finished.
//
// The language SDK can do additional things from within the same initializer thread,
// e.g. starting to observe application events for foreground/background behavior.
// The observer then needs to call the respective client activity API.
void initialize_finished();
// Trigger the uploader whenever a ping was submitted.
//
// This should not block.
// The uploader needs to asynchronously poll Glean for new pings to upload.
[Throws=CallbackError]
void trigger_upload();
// Start the Metrics Ping Scheduler.
//
// *Note*: The implementor
// * DOES NOT need to schedule the uploader.
// * MUST NOT use a dispatched call in the immediate invocation.
//
// Returns whether it submitted a ping immediately.
boolean start_metrics_ping_scheduler();
// Called when upload is disabled and uploads should be stopped
[Throws=CallbackError]
void cancel_uploads();
// Called on shutdown, before Glean is fully shutdown.
//
// * This MUST NOT put any new tasks on the dispatcher.
// * New tasks will be ignored.
// * This SHOULD NOT block arbitrarily long.
// * Shutdown waits for a maximum of 30 seconds.
[Throws=CallbackError]
void shutdown();
};
// A callback handler that receives the IDs of recorded events
callback interface GleanEventListener {
// Called when an event is recorded, indicating the id of the event
void on_event_recorded(string id);
};
// Deserialized experiment data.
dictionary RecordedExperiment {
// The experiment's branch.
string branch;
// Any extra data associated with this experiment.
record<DOMString, string>? extra;
};
// Represents a request to upload a ping.
dictionary PingRequest {
// The Job ID to identify this request,
// this is the same as the ping UUID.
string document_id;
// The path for the server to upload the ping to.
string path;
// The body of the request, as a byte array.
// If gzip encoded, then the `headers` list will
// contain a `Content-Encoding` header with the value `gzip`.
sequence<u8> body;
// A map with all the headers to be sent with the request.
record<DOMString, string> headers;
// Whether the body has {client|ping}_info sections.
boolean body_has_info_sections;
// The ping's name. Likely also somewhere in `path`.
string ping_name;
};
// An enum representing the possible upload tasks to be performed by an uploader.
[Enum]
interface PingUploadTask {
// An upload task.
//
// * request: the ping request for upload
Upload(PingRequest request);
// A flag signaling that the pending pings directories are not done being processed,
// thus the requester should wait and come back later.
//
// * time: The time in milliseconds the requester should wait before requesting a new task.
Wait(u64 time);
// A flag signaling that requester doesn't need to request
// any more upload tasks at this moment.
//
// * unused: _ignored_.
Done(i8 unused);
};
// The result of an attempted ping upload.
[Enum]
interface UploadResult {
// A recoverable failure.
//
// During upload something went wrong,/ e.g. the network connection failed.
// The upload should be retried at a later time.
//
// * unused: _ignored_.
RecoverableFailure(i8 unused);
// An unrecoverable upload failure.
//
// A possible cause might be a malformed URL.
//
// * unused: _ignored_.
UnrecoverableFailure(i8 unused);
// A HTTP response code.
//
// This can still indicate an error, depending on the status code.
//
// * code: The HTTP status code
HttpStatus(i32 code);
// Signal that this uploader is done with work
// and won't accept new work.
Done(i8 unused);
};
// Communicating back whether the uploader loop should continue.
enum UploadTaskAction {
// Instruct the caller to continue with work.
"Next",
// Instruct the caller to end work.
"End",
};
// The supported metrics' lifetimes.
//
// A metric's lifetime determines when its stored data gets reset.
enum Lifetime {
// The metric is reset with each sent ping
"Ping",
// The metric is reset on application restart
"Application",
// The metric is reset with each user profile
"User",
};
// The possible error types for metric recording.
enum ErrorType {
// For when the value to be recorded does not match the metric-specific restrictions
"InvalidValue",
// For when the label of a labeled metric does not match the restrictions
"InvalidLabel",
// For when the metric caught an invalid state while recording
"InvalidState",
// For when the value to be recorded overflows the metric-specific upper range
"InvalidOverflow",
};
interface PingType {
constructor(string name, boolean include_client_id, boolean send_if_empty, boolean precise_timestamps, boolean include_info_sections, boolean enabled, sequence<string> schedules_pings, sequence<string> reason_codes);
void submit(optional string? reason = null);
};
// The common set of data shared across all different metric types.
dictionary CommonMetricData {
// The metric's category.
string category;
// The metric's name.
string name;
// List of ping names to include this metric in.
sequence<string> send_in_pings;
// The metric's lifetime.
Lifetime lifetime;
// Whether or not the metric is disabled.
//
// Disabled metrics are never recorded.
boolean disabled;
// Dynamic label.
//
// When a labeled metric factory creates the specific metric to be recorded to,
// dynamic labels are stored in the specific label so that
// we can validate them when the Glean singleton is available.
string? dynamic_label = null;
};
interface CounterMetric {
constructor(CommonMetricData meta);
void add(optional i32 amount = 1);
i32? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// Different resolutions supported by the time related metric types
// (e.g. DatetimeMetric).
enum TimeUnit {
// Represents nanosecond precision.
"Nanosecond",
// Represents microsecond precision.
"Microsecond",
// Represents millisecond precision.
"Millisecond",
// Represents second precision.
"Second",
// Represents minute precision.
"Minute",
// Represents hour precision.
"Hour",
// Represents day precision.
"Day",
};
interface TimespanMetric {
constructor(CommonMetricData meta, TimeUnit time_unit);
void start();
void stop();
void cancel();
void set_raw_nanos(i64 elapsed);
i64? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface BooleanMetric {
constructor(CommonMetricData meta);
void set(boolean value);
boolean? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface StringMetric {
constructor(CommonMetricData meta);
void set(string value);
string? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface LabeledCounter {
constructor(CommonMetricData meta, sequence<CowString>? labels);
CounterMetric get(string label);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface LabeledBoolean {
constructor(CommonMetricData meta, sequence<CowString>? labels);
BooleanMetric get(string label);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface LabeledString {
constructor(CommonMetricData meta, sequence<CowString>? labels);
StringMetric get(string label);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface StringListMetric {
constructor(CommonMetricData meta);
void add(string value);
void set(sequence<string> value);
sequence<string>? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface UrlMetric {
constructor(CommonMetricData meta);
void set(string value);
string? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface UuidMetric {
constructor(CommonMetricData meta);
void set(string value);
string generate_and_set();
string? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface QuantityMetric {
constructor(CommonMetricData meta);
void set(i64 value);
i64? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// A snapshot of all buckets and the accumulated sum of a distribution.
dictionary DistributionData {
// A map containig the bucket index mapped to the accumulated count.
record<i64, i64> values;
// The accumulated sum of all the samples in the distribution.
i64 sum;
// The total number of entries in the distribution.
i64 count;
};
// Identifier for a running timer.
//
// Its internals are considered private,
// but due to UniFFI's behavior we expose it as a dictionary for now.
dictionary TimerId {
u64 id;
};
interface TimingDistributionMetric {
constructor(CommonMetricData meta, TimeUnit time_unit);
TimerId start();
void stop_and_accumulate(TimerId timer_id);
void cancel(TimerId timer_id);
void accumulate_samples(sequence<i64> samples);
void accumulate_single_sample(i64 sample);
DistributionData? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// Different resolutions supported by the memory related metric types
// (e.g. MemoryDistributionMetric).
enum MemoryUnit {
// 1 byte
"Byte",
// 2^10 bytes
"Kilobyte",
// 2^20 bytes
"Megabyte",
// 2^30 bytes
"Gigabyte",
};
interface MemoryDistributionMetric {
constructor(CommonMetricData meta, MemoryUnit memory_unit);
void accumulate(i64 sample);
void accumulate_samples(sequence<i64> samples);
DistributionData? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// Different kinds of histograms.
enum HistogramType {
// A histogram with linear distributed buckets.
"Linear",
// A histogram with exponential distributed buckets.
"Exponential",
};
interface CustomDistributionMetric {
constructor(CommonMetricData meta, i64 range_min, i64 range_max, i64 bucket_count, HistogramType histogram_type);
void accumulate_samples(sequence<i64> samples);
void accumulate_single_sample(i64 sample);
DistributionData? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// Representation of a date, time and timezone.
dictionary Datetime {
i32 year;
u32 month;
u32 day;
u32 hour;
u32 minute;
u32 second;
u32 nanosecond;
i32 offset_seconds;
};
interface DatetimeMetric {
constructor(CommonMetricData meta, TimeUnit time_unit);
void set(optional Datetime? value = null);
Datetime? test_get_value(optional string? ping_name = null);
string? test_get_value_as_string(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// Represents the recorded data for a single event.
dictionary RecordedEvent {
// The timestamp of when the event was recorded.
//
// This allows to order events from a single process run.
u64 timestamp;
// The event's category.
//
// This is defined by users in the metrics file.
string category;
// The event's name.
//
// This is defined by users in the metrics file.
string name;
// A map of all extra data values.
//
// The set of allowed extra keys is defined by users in the metrics file.
record<DOMString, string>? extra;
};
interface EventMetric {
constructor(CommonMetricData meta, sequence<string> allowed_extra_keys);
void record(record<DOMString, string> extra);
sequence<RecordedEvent>? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
dictionary Rate {
i32 numerator;
i32 denominator;
};
interface RateMetric {
constructor(CommonMetricData meta);
void add_to_numerator(i32 amount);
void add_to_denominator(i32 amount);
Rate? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface DenominatorMetric {
constructor(CommonMetricData meta, sequence<CommonMetricData> numerators);
void add(i32 amount);
i32? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface NumeratorMetric {
constructor(CommonMetricData meta);
void add_to_numerator(i32 amount);
Rate? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
interface TextMetric {
constructor(CommonMetricData meta);
void set(string value);
string? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
};
// JSON data encoded into a string
[Custom]
typedef string JsonValue;
interface ObjectMetric {
constructor(CommonMetricData meta);
void set_string(string object);
JsonValue? test_get_value(optional string? ping_name = null);
i32 test_get_num_recorded_errors(ErrorType error);
void record_schema_error();
};
|