• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / fx-private-relay / 4276dcd9-8c30-4786-8a41-f9c1cdae7f05

05 Mar 2024 07:15PM CUT coverage: 74.734% (+0.6%) from 74.139%
4276dcd9-8c30-4786-8a41-f9c1cdae7f05

Pull #4452

circleci

jwhitlock
Pass user to create_expected_glean_event

Pass the related user to the test helper create_expected_glean_event, so
that the user-specific values such as fxa_id and date_joined_relay can
be extracted in the helper rather than each test function.
Pull Request #4452: MPP-3352: Add first Glean metrics to measure email mask usage

2084 of 3047 branches covered (68.4%)

Branch coverage included in aggregate %.

251 of 256 new or added lines in 7 files covered. (98.05%)

79 existing lines in 3 files now uncovered.

6763 of 8791 relevant lines covered (76.93%)

20.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/privaterelay/glean/server_events.py
1
"""
2
This Source Code Form is subject to the terms of the Mozilla Public
3
License, v. 2.0. If a copy of the MPL was not distributed with this
4
file, You can obtain one at http://mozilla.org/MPL/2.0/.
5

6
AUTOGENERATED BY glean_parser v12.0.1. DO NOT EDIT. To recreate, run:
7

8
bash .circleci/python_job.bash run build_glean
9
"""
10

11
from __future__ import annotations
1✔
12
from datetime import datetime, timezone
1✔
13
from typing import Any
1✔
14
from uuid import uuid4
1✔
15
import json
1✔
16

17
GLEAN_EVENT_MOZLOG_TYPE = "glean-server-event"
1✔
18

19

20
class EventsServerEventLogger:
1✔
21
    def __init__(
1✔
22
        self, application_id: str, app_display_version: str, channel: str
23
    ) -> None:
24
        """
25
        Create EventsServerEventLogger instance.
26

27
        :param str application_id: The application ID.
28
        :param str app_display_version: The application display version.
29
        :param str channel: The channel.
30
        """
31
        self._application_id = application_id
1✔
32
        self._app_display_version = app_display_version
1✔
33
        self._channel = channel
1✔
34

35
    def _record(self, user_agent: str, ip_address: str, event: dict[str, Any]) -> None:
1✔
36
        now = datetime.now(timezone.utc)
1✔
37
        timestamp = now.isoformat()
1✔
38
        event["timestamp"] = int(1000.0 * now.timestamp())  # Milliseconds since epoch
1✔
39
        event_payload = {
1✔
40
            "metrics": {},
41
            "events": [event],
42
            "ping_info": {
43
                # seq is required in the Glean schema, however is not useful in server context
44
                "seq": 0,
45
                "start_time": timestamp,
46
                "end_time": timestamp,
47
            },
48
            # `Unknown` fields below are required in the Glean schema, however they are
49
            # not useful in server context
50
            "client_info": {
51
                "telemetry_sdk_build": "glean_parser v12.0.1",
52
                "first_run_date": "Unknown",
53
                "os": "Unknown",
54
                "os_version": "Unknown",
55
                "architecture": "Unknown",
56
                "app_build": "Unknown",
57
                "app_display_version": self._app_display_version,
58
                "app_channel": self._channel,
59
            },
60
        }
61
        event_payload_serialized = json.dumps(event_payload)
1✔
62

63
        # This is the message structure that Decoder expects:
64
        # https://github.com/mozilla/gcp-ingestion/pull/2400
65
        ping = {
1✔
66
            "document_namespace": self._application_id,
67
            "document_type": "events",
68
            "document_version": "1",
69
            "document_id": str(uuid4()),
70
            "user_agent": user_agent,
71
            "ip_address": ip_address,
72
            "payload": event_payload_serialized,
73
        }
74

75
        self.emit_record(now, ping)
1✔
76

77
    def emit_record(self, now: datetime, ping: dict[str, Any]) -> None:
1✔
78
        """Log the ping to STDOUT.
79
        Applications might want to override this method to use their own logging.
80
        If doing so, make sure to log the ping as JSON, and to include the
81
        `Type: GLEAN_EVENT_MOZLOG_TYPE`."""
NEW
82
        ping_envelope = {
×
83
            "Timestamp": now.isoformat(),
84
            "Logger": "glean",
85
            "Type": GLEAN_EVENT_MOZLOG_TYPE,
86
            "Fields": ping,
87
        }
NEW
88
        ping_envelope_serialized = json.dumps(ping_envelope)
×
89

NEW
90
        print(ping_envelope_serialized)
×
91

92
    def record_email_blocked(
1✔
93
        self,
94
        user_agent: str,
95
        ip_address: str,
96
        client_id: str,
97
        fxa_id: str,
98
        platform: str,
99
        n_random_masks: int,
100
        n_domain_masks: int,
101
        n_deleted_random_masks: int,
102
        n_deleted_domain_masks: int,
103
        date_joined_relay: int,
104
        premium_status: str,
105
        date_joined_premium: int,
106
        has_extension: bool,
107
        date_got_extension: int,
108
        mask_id: str,
109
        is_random_mask: bool,
110
        is_reply: bool,
111
        reason: str,
112
        can_retry: bool,
113
    ) -> None:
114
        """
115
        Record and submit a email_blocked event:
116
        Relay receives but does not forward an email for a Relay user.
117
        Event is logged to STDOUT via `print`.
118

119
        :param str user_agent: The user agent.
120
        :param str ip_address: The IP address. Will be used to decode Geo information
121
            and scrubbed at ingestion.
122
        :param str client_id: Firefox client ID
123
        :param str fxa_id: Mozilla accounts user ID
124
        :param str platform: Relay client platform
125
        :param int n_random_masks: Number of random masks
126
        :param int n_domain_masks: Number of premium subdomain masks
127
        :param int n_deleted_random_masks: Number of deleted random masks
128
        :param int n_deleted_domain_masks: Number of deleted domain masks
129
        :param int date_joined_relay: Timestamp for joining Relay, seconds since epoch
130
        :param str premium_status: Subscription type and term
131
        :param int date_joined_premium: Timestamp for starting premium_status subscription, seconds since epoch, -1 if not subscribed
132
        :param bool has_extension: The user has the Relay Add-on
133
        :param int date_got_extension: Timestamp for adding Relay Add-on, seconds since epoch, -1 if not used
134
        :param str mask_id: Mask ID, 'R' or 'D' followed by a number
135
        :param bool is_random_mask: The mask is a random mask, instead of a domain mask
136
        :param bool is_reply: The email is a reply from the Relay user
137
        :param str reason: Code describing why the email was blocked
138
        :param bool can_retry: The email processes can retry the email, so it may fail multiple times
139
        """
140
        event = {
1✔
141
            "category": "email",
142
            "name": "blocked",
143
            "extra": {
144
                "client_id": str(client_id),
145
                "fxa_id": str(fxa_id),
146
                "platform": str(platform),
147
                "n_random_masks": str(n_random_masks),
148
                "n_domain_masks": str(n_domain_masks),
149
                "n_deleted_random_masks": str(n_deleted_random_masks),
150
                "n_deleted_domain_masks": str(n_deleted_domain_masks),
151
                "date_joined_relay": str(date_joined_relay),
152
                "premium_status": str(premium_status),
153
                "date_joined_premium": str(date_joined_premium),
154
                "has_extension": str(has_extension).lower(),
155
                "date_got_extension": str(date_got_extension),
156
                "mask_id": str(mask_id),
157
                "is_random_mask": str(is_random_mask).lower(),
158
                "is_reply": str(is_reply).lower(),
159
                "reason": str(reason),
160
                "can_retry": str(can_retry).lower(),
161
            },
162
        }
163
        self._record(user_agent, ip_address, event)
1✔
164

165
    def record_email_forwarded(
1✔
166
        self,
167
        user_agent: str,
168
        ip_address: str,
169
        client_id: str,
170
        fxa_id: str,
171
        platform: str,
172
        n_random_masks: int,
173
        n_domain_masks: int,
174
        n_deleted_random_masks: int,
175
        n_deleted_domain_masks: int,
176
        date_joined_relay: int,
177
        premium_status: str,
178
        date_joined_premium: int,
179
        has_extension: bool,
180
        date_got_extension: int,
181
        mask_id: str,
182
        is_random_mask: bool,
183
        is_reply: bool,
184
    ) -> None:
185
        """
186
        Record and submit a email_forwarded event:
187
        Relay receives and forwards an email for a Relay user.
188
        Event is logged to STDOUT via `print`.
189

190
        :param str user_agent: The user agent.
191
        :param str ip_address: The IP address. Will be used to decode Geo information
192
            and scrubbed at ingestion.
193
        :param str client_id: Firefox client ID
194
        :param str fxa_id: Mozilla accounts user ID
195
        :param str platform: Relay client platform
196
        :param int n_random_masks: Number of random masks
197
        :param int n_domain_masks: Number of premium subdomain masks
198
        :param int n_deleted_random_masks: Number of deleted random masks
199
        :param int n_deleted_domain_masks: Number of deleted domain masks
200
        :param int date_joined_relay: Timestamp for joining Relay, seconds since epoch
201
        :param str premium_status: Subscription type and term
202
        :param int date_joined_premium: Timestamp for starting premium_status subscription, seconds since epoch, -1 if not subscribed
203
        :param bool has_extension: The user has the Relay Add-on
204
        :param int date_got_extension: Timestamp for adding Relay Add-on, seconds since epoch, -1 if not used
205
        :param str mask_id: Mask ID, 'R' or 'D' followed by a number
206
        :param bool is_random_mask: The mask is a random mask, instead of a domain mask
207
        :param bool is_reply: The email is a reply from the Relay user
208
        """
209
        event = {
1✔
210
            "category": "email",
211
            "name": "forwarded",
212
            "extra": {
213
                "client_id": str(client_id),
214
                "fxa_id": str(fxa_id),
215
                "platform": str(platform),
216
                "n_random_masks": str(n_random_masks),
217
                "n_domain_masks": str(n_domain_masks),
218
                "n_deleted_random_masks": str(n_deleted_random_masks),
219
                "n_deleted_domain_masks": str(n_deleted_domain_masks),
220
                "date_joined_relay": str(date_joined_relay),
221
                "premium_status": str(premium_status),
222
                "date_joined_premium": str(date_joined_premium),
223
                "has_extension": str(has_extension).lower(),
224
                "date_got_extension": str(date_got_extension),
225
                "mask_id": str(mask_id),
226
                "is_random_mask": str(is_random_mask).lower(),
227
                "is_reply": str(is_reply).lower(),
228
            },
229
        }
230
        self._record(user_agent, ip_address, event)
1✔
231

232
    def record_email_mask_created(
1✔
233
        self,
234
        user_agent: str,
235
        ip_address: str,
236
        client_id: str,
237
        fxa_id: str,
238
        platform: str,
239
        n_random_masks: int,
240
        n_domain_masks: int,
241
        n_deleted_random_masks: int,
242
        n_deleted_domain_masks: int,
243
        date_joined_relay: int,
244
        premium_status: str,
245
        date_joined_premium: int,
246
        has_extension: bool,
247
        date_got_extension: int,
248
        mask_id: str,
249
        is_random_mask: bool,
250
        created_by_api: bool,
251
        has_website: bool,
252
    ) -> None:
253
        """
254
        Record and submit a email_mask_created event:
255
        A Relay user creates an email mask.
256
        Event is logged to STDOUT via `print`.
257

258
        :param str user_agent: The user agent.
259
        :param str ip_address: The IP address. Will be used to decode Geo information
260
            and scrubbed at ingestion.
261
        :param str client_id: Firefox client ID
262
        :param str fxa_id: Mozilla accounts user ID
263
        :param str platform: Relay client platform
264
        :param int n_random_masks: Number of random masks
265
        :param int n_domain_masks: Number of premium subdomain masks
266
        :param int n_deleted_random_masks: Number of deleted random masks
267
        :param int n_deleted_domain_masks: Number of deleted domain masks
268
        :param int date_joined_relay: Timestamp for joining Relay, seconds since epoch
269
        :param str premium_status: Subscription type and term
270
        :param int date_joined_premium: Timestamp for starting premium_status subscription, seconds since epoch, -1 if not subscribed
271
        :param bool has_extension: The user has the Relay Add-on
272
        :param int date_got_extension: Timestamp for adding Relay Add-on, seconds since epoch, -1 if not used
273
        :param str mask_id: Mask ID, 'R' or 'D' followed by a number
274
        :param bool is_random_mask: The mask is a random mask, instead of a domain mask
275
        :param bool created_by_api: The mask was created via the API, rather than an incoming email
276
        :param bool has_website: The mask was created by the Add-on or integration on a website
277
        """
278
        event = {
1✔
279
            "category": "email_mask",
280
            "name": "created",
281
            "extra": {
282
                "client_id": str(client_id),
283
                "fxa_id": str(fxa_id),
284
                "platform": str(platform),
285
                "n_random_masks": str(n_random_masks),
286
                "n_domain_masks": str(n_domain_masks),
287
                "n_deleted_random_masks": str(n_deleted_random_masks),
288
                "n_deleted_domain_masks": str(n_deleted_domain_masks),
289
                "date_joined_relay": str(date_joined_relay),
290
                "premium_status": str(premium_status),
291
                "date_joined_premium": str(date_joined_premium),
292
                "has_extension": str(has_extension).lower(),
293
                "date_got_extension": str(date_got_extension),
294
                "mask_id": str(mask_id),
295
                "is_random_mask": str(is_random_mask).lower(),
296
                "created_by_api": str(created_by_api).lower(),
297
                "has_website": str(has_website).lower(),
298
            },
299
        }
300
        self._record(user_agent, ip_address, event)
1✔
301

302
    def record_email_mask_deleted(
1✔
303
        self,
304
        user_agent: str,
305
        ip_address: str,
306
        client_id: str,
307
        fxa_id: str,
308
        platform: str,
309
        n_random_masks: int,
310
        n_domain_masks: int,
311
        n_deleted_random_masks: int,
312
        n_deleted_domain_masks: int,
313
        date_joined_relay: int,
314
        premium_status: str,
315
        date_joined_premium: int,
316
        has_extension: bool,
317
        date_got_extension: int,
318
        mask_id: str,
319
        is_random_mask: bool,
320
    ) -> None:
321
        """
322
        Record and submit a email_mask_deleted event:
323
        A Relay user deletes an email mask.
324
        Event is logged to STDOUT via `print`.
325

326
        :param str user_agent: The user agent.
327
        :param str ip_address: The IP address. Will be used to decode Geo information
328
            and scrubbed at ingestion.
329
        :param str client_id: Firefox client ID
330
        :param str fxa_id: Mozilla accounts user ID
331
        :param str platform: Relay client platform
332
        :param int n_random_masks: Number of random masks
333
        :param int n_domain_masks: Number of premium subdomain masks
334
        :param int n_deleted_random_masks: Number of deleted random masks
335
        :param int n_deleted_domain_masks: Number of deleted domain masks
336
        :param int date_joined_relay: Timestamp for joining Relay, seconds since epoch
337
        :param str premium_status: Subscription type and term
338
        :param int date_joined_premium: Timestamp for starting premium_status subscription, seconds since epoch, -1 if not subscribed
339
        :param bool has_extension: The user has the Relay Add-on
340
        :param int date_got_extension: Timestamp for adding Relay Add-on, seconds since epoch, -1 if not used
341
        :param str mask_id: Mask ID, 'R' or 'D' followed by a number
342
        :param bool is_random_mask: The mask is a random mask, instead of a domain mask
343
        """
344
        event = {
1✔
345
            "category": "email_mask",
346
            "name": "deleted",
347
            "extra": {
348
                "client_id": str(client_id),
349
                "fxa_id": str(fxa_id),
350
                "platform": str(platform),
351
                "n_random_masks": str(n_random_masks),
352
                "n_domain_masks": str(n_domain_masks),
353
                "n_deleted_random_masks": str(n_deleted_random_masks),
354
                "n_deleted_domain_masks": str(n_deleted_domain_masks),
355
                "date_joined_relay": str(date_joined_relay),
356
                "premium_status": str(premium_status),
357
                "date_joined_premium": str(date_joined_premium),
358
                "has_extension": str(has_extension).lower(),
359
                "date_got_extension": str(date_got_extension),
360
                "mask_id": str(mask_id),
361
                "is_random_mask": str(is_random_mask).lower(),
362
            },
363
        }
364
        self._record(user_agent, ip_address, event)
1✔
365

366
    def record_email_mask_label_updated(
1✔
367
        self,
368
        user_agent: str,
369
        ip_address: str,
370
        client_id: str,
371
        fxa_id: str,
372
        platform: str,
373
        n_random_masks: int,
374
        n_domain_masks: int,
375
        n_deleted_random_masks: int,
376
        n_deleted_domain_masks: int,
377
        date_joined_relay: int,
378
        premium_status: str,
379
        date_joined_premium: int,
380
        has_extension: bool,
381
        date_got_extension: int,
382
        mask_id: str,
383
        is_random_mask: bool,
384
    ) -> None:
385
        """
386
        Record and submit a email_mask_label_updated event:
387
        A Relay users updates an email mask's label.
388
        Event is logged to STDOUT via `print`.
389

390
        :param str user_agent: The user agent.
391
        :param str ip_address: The IP address. Will be used to decode Geo information
392
            and scrubbed at ingestion.
393
        :param str client_id: Firefox client ID
394
        :param str fxa_id: Mozilla accounts user ID
395
        :param str platform: Relay client platform
396
        :param int n_random_masks: Number of random masks
397
        :param int n_domain_masks: Number of premium subdomain masks
398
        :param int n_deleted_random_masks: Number of deleted random masks
399
        :param int n_deleted_domain_masks: Number of deleted domain masks
400
        :param int date_joined_relay: Timestamp for joining Relay, seconds since epoch
401
        :param str premium_status: Subscription type and term
402
        :param int date_joined_premium: Timestamp for starting premium_status subscription, seconds since epoch, -1 if not subscribed
403
        :param bool has_extension: The user has the Relay Add-on
404
        :param int date_got_extension: Timestamp for adding Relay Add-on, seconds since epoch, -1 if not used
405
        :param str mask_id: Mask ID, 'R' or 'D' followed by a number
406
        :param bool is_random_mask: The mask is a random mask, instead of a domain mask
407
        """
408
        event = {
1✔
409
            "category": "email_mask",
410
            "name": "label_updated",
411
            "extra": {
412
                "client_id": str(client_id),
413
                "fxa_id": str(fxa_id),
414
                "platform": str(platform),
415
                "n_random_masks": str(n_random_masks),
416
                "n_domain_masks": str(n_domain_masks),
417
                "n_deleted_random_masks": str(n_deleted_random_masks),
418
                "n_deleted_domain_masks": str(n_deleted_domain_masks),
419
                "date_joined_relay": str(date_joined_relay),
420
                "premium_status": str(premium_status),
421
                "date_joined_premium": str(date_joined_premium),
422
                "has_extension": str(has_extension).lower(),
423
                "date_got_extension": str(date_got_extension),
424
                "mask_id": str(mask_id),
425
                "is_random_mask": str(is_random_mask).lower(),
426
            },
427
        }
428
        self._record(user_agent, ip_address, event)
1✔
429

430

431
def create_events_server_event_logger(
1✔
432
    application_id: str,
433
    app_display_version: str,
434
    channel: str,
435
) -> EventsServerEventLogger:
436
    """
437
    Factory function that creates an instance of Glean Server Event Logger to record
438
    `events` ping events.
439
    :param str application_id: The application ID.
440
    :param str app_display_version: The application display version.
441
    :param str channel: The channel.
442
    :return: An instance of EventsServerEventLogger.
443
    :rtype: EventsServerEventLogger
444
    """
NEW
445
    return EventsServerEventLogger(application_id, app_display_version, channel)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc