Skip to content

Commit 111b06c

Browse files
committed
Bug2007406 - Add server knobs config to ping_info
This adds the currently applied server knobs config to all pings in the ping_info section, or omits it if no server knobs config is applied. This should help to calculate effective sampling rates for metrics and pings that are being sampled in the client.
1 parent 0d30476 commit 111b06c

File tree

6 files changed

+238
-0
lines changed

6 files changed

+238
-0
lines changed

docs/user/user/server-knobs/metrics/experimenter-configuration.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,38 @@ This configuration would be what is entered into the branch configuration setup
2121
}
2222
}
2323
```
24+
25+
## Server Knobs Configuration in Pings
26+
27+
When Server Knobs configuration is applied through `applyServerKnobsConfig`, the entire configuration is automatically recorded as an `ObjectMetric` and included in the `ping_info` section of all pings. This makes it easier to identify which metrics are being controlled by Server Knobs and to calculate effective sampling rates in analysis.
28+
29+
The configuration is stored using a standard `ObjectMetric` (at `glean.internal.server_knobs_config`), which provides schema definition support for downstream tooling and requires minimal changes to ingestion pipeline schemas.
30+
31+
### How It Appears in Pings
32+
33+
The complete Server Knobs configuration is included in `ping_info.server_knobs_config`:
34+
35+
```json
36+
{
37+
"ping_info": {
38+
"seq": 123,
39+
"start_time": "2024-01-01T00:00:00Z",
40+
"end_time": "2024-01-01T01:00:00Z",
41+
"server_knobs_config": {
42+
"metrics_enabled": {
43+
"urlbar.engagement": true,
44+
"urlbar.impression": true
45+
},
46+
"pings_enabled": {},
47+
"event_threshold": null
48+
}
49+
},
50+
"metrics": {
51+
"counter": {
52+
"urlbar.engagement": 5,
53+
"urlbar.impression": 2
54+
}
55+
}
56+
}
57+
```
58+

docs/user/user/server-knobs/other/max-events.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,38 @@ For instance, if you wanted to disable batching in order to transmit an events p
1414
}
1515
}
1616
```
17+
18+
## Server Knobs Configuration in Pings
19+
20+
When Server Knobs configuration is applied through `applyServerKnobsConfig`, the entire configuration is automatically recorded as an `ObjectMetric` and included in the `ping_info` section of all pings. This makes it easier to identify which metrics are being controlled by Server Knobs and to calculate effective sampling rates in analysis.
21+
22+
The configuration is stored using a standard `ObjectMetric` (at `glean.internal.server_knobs_config`), which provides schema definition support for downstream tooling and requires minimal changes to ingestion pipeline schemas.
23+
24+
### How It Appears in Pings
25+
26+
The complete Server Knobs configuration is included in `ping_info.server_knobs_config`:
27+
28+
```json
29+
{
30+
"ping_info": {
31+
"seq": 123,
32+
"start_time": "2024-01-01T00:00:00Z",
33+
"end_time": "2024-01-01T01:00:00Z",
34+
"server_knobs_config": {
35+
"metrics_enabled": {
36+
"urlbar.engagement": true,
37+
"urlbar.impression": true
38+
},
39+
"pings_enabled": {},
40+
"event_threshold": null
41+
}
42+
},
43+
"metrics": {
44+
"counter": {
45+
"urlbar.engagement": 5,
46+
"urlbar.impression": 2
47+
}
48+
}
49+
}
50+
```
51+

docs/user/user/server-knobs/pings/experimenter-configuration.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,38 @@ This configuration would be what is entered into the branch configuration setup
1919
}
2020
}
2121
```
22+
23+
## Server Knobs Configuration in Pings
24+
25+
When Server Knobs configuration is applied through `applyServerKnobsConfig`, the entire configuration is automatically recorded as an `ObjectMetric` and included in the `ping_info` section of all pings. This makes it easier to identify which metrics are being controlled by Server Knobs and to calculate effective sampling rates in analysis.
26+
27+
The configuration is stored using a standard `ObjectMetric` (at `glean.internal.server_knobs_config`), which provides schema definition support for downstream tooling and requires minimal changes to ingestion pipeline schemas.
28+
29+
### How It Appears in Pings
30+
31+
The complete Server Knobs configuration is included in `ping_info.server_knobs_config`:
32+
33+
```json
34+
{
35+
"ping_info": {
36+
"seq": 123,
37+
"start_time": "2024-01-01T00:00:00Z",
38+
"end_time": "2024-01-01T01:00:00Z",
39+
"server_knobs_config": {
40+
"metrics_enabled": {
41+
"urlbar.engagement": true,
42+
"urlbar.impression": true
43+
},
44+
"pings_enabled": {},
45+
"event_threshold": null
46+
}
47+
},
48+
"metrics": {
49+
"counter": {
50+
"urlbar.engagement": 5,
51+
"urlbar.impression": 2
52+
}
53+
}
54+
}
55+
```
56+

glean-core/metrics.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,44 @@ glean.internal.metrics:
398398
- glean-team@mozilla.com
399399
expires: never
400400

401+
server_knobs_config:
402+
type: object
403+
lifetime: application
404+
send_in_pings:
405+
- glean_internal_info
406+
description: |
407+
The Server Knobs configuration applied via applyServerKnobsConfig.
408+
This contains the complete configuration including metrics_enabled,
409+
pings_enabled, and event_threshold settings that control metric
410+
recording behavior through remote configuration.
411+
bugs:
412+
- https://bugzilla.mozilla.org/show_bug.cgi?id=2007406
413+
data_reviews:
414+
- https://bugzilla.mozilla.org/show_bug.cgi?id=2007406
415+
data_sensitivity:
416+
- technical
417+
notification_emails:
418+
- glean-team@mozilla.com
419+
expires: never
420+
structure:
421+
type: object
422+
properties:
423+
metrics_enabled:
424+
type: object
425+
description: |
426+
Map of metric identifiers (category.name) to boolean values
427+
indicating whether the metric is enabled.
428+
pings_enabled:
429+
type: object
430+
description: |
431+
Map of ping names to boolean values indicating whether
432+
the ping is enabled.
433+
event_threshold:
434+
type: integer
435+
description: |
436+
Optional threshold for event buffering before an events
437+
ping is collected and submitted. Can be null if not set.
438+
401439
402440
glean.internal.metrics.attribution:
403441
source:

glean-core/src/core/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,17 @@ impl Glean {
11131113
.get_value(self, None)
11141114
}
11151115

1116+
/// Returns the ObjectMetric used to store Server Knobs configuration.
1117+
pub(crate) fn server_knobs_metric() -> metrics::ObjectMetric {
1118+
metrics::ObjectMetric::new(CommonMetricData {
1119+
name: "server_knobs_config".into(),
1120+
category: "glean.internal".into(),
1121+
send_in_pings: vec![INTERNAL_STORAGE.into()],
1122+
lifetime: Lifetime::Application,
1123+
..Default::default()
1124+
})
1125+
}
1126+
11161127
/// Set configuration to override the default state, typically initiated from a
11171128
/// remote_settings experiment or rollout
11181129
///
@@ -1136,6 +1147,15 @@ impl Glean {
11361147

11371148
remote_settings_config.event_threshold = cfg.event_threshold;
11381149

1150+
// Store the Server Knobs configuration as an ObjectMetric
1151+
// This allows it to be included in pings automatically
1152+
let config_clone = remote_settings_config.clone();
1153+
drop(remote_settings_config); // Release lock before storage operation
1154+
1155+
// Store the configuration using the server knobs ObjectMetric
1156+
let server_knobs_metric = Self::server_knobs_metric();
1157+
server_knobs_metric.set_sync(self, serde_json::to_value(&config_clone).unwrap());
1158+
11391159
// Update remote_settings epoch
11401160
self.remote_settings_epoch.fetch_add(1, Ordering::SeqCst);
11411161
}

glean-core/src/ping/mod.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ impl PingMaker {
162162
.insert("experiments".to_string(), experiment_data);
163163
};
164164

165+
// Get the Server Knobs configuration, if available.
166+
let server_knobs_metric = crate::Glean::server_knobs_metric();
167+
if let Some(config_json) = server_knobs_metric.get_value(glean, INTERNAL_STORAGE) {
168+
let server_knobs_config = serde_json::from_str(&config_json).unwrap();
169+
map.as_object_mut()
170+
.unwrap() // safe unwrap, we created the object above
171+
.insert("server_knobs_config".to_string(), server_knobs_config);
172+
}
173+
165174
map
166175
}
167176

@@ -533,4 +542,70 @@ mod test {
533542
assert_eq!(0, ping_maker.get_ping_seq(&glean, "store1"));
534543
assert_eq!(1, ping_maker.get_ping_seq(&glean, "store1"));
535544
}
545+
546+
#[test]
547+
fn test_server_knobs_config_appears_in_ping_info() {
548+
use crate::metrics::RemoteSettingsConfig;
549+
use std::collections::HashMap;
550+
551+
let (glean, _t) = new_glean(None);
552+
553+
// Apply complete Server Knobs config with all three fields
554+
let mut metrics_enabled = HashMap::new();
555+
metrics_enabled.insert("test.counter".to_string(), true);
556+
557+
let mut pings_enabled = HashMap::new();
558+
pings_enabled.insert("custom".to_string(), false);
559+
560+
let config = RemoteSettingsConfig {
561+
metrics_enabled,
562+
pings_enabled,
563+
event_threshold: Some(10),
564+
};
565+
glean.apply_server_knobs_config(config);
566+
567+
// Verify complete config structure appears in ping_info
568+
let ping_maker = PingMaker::new();
569+
let ping_info = ping_maker.get_ping_info(&glean, "store1", None, TimeUnit::Minute);
570+
571+
let server_knobs = &ping_info["server_knobs_config"];
572+
assert_eq!(server_knobs["metrics_enabled"]["test.counter"], true);
573+
assert_eq!(server_knobs["pings_enabled"]["custom"], false);
574+
assert_eq!(server_knobs["event_threshold"], 10);
575+
}
576+
577+
#[test]
578+
fn test_server_knobs_not_included_when_no_config() {
579+
let (glean, _t) = new_glean(None);
580+
581+
let ping_maker = PingMaker::new();
582+
let ping_info = ping_maker.get_ping_info(&glean, "store1", None, TimeUnit::Minute);
583+
584+
assert!(ping_info.get("server_knobs_config").is_none());
585+
}
586+
587+
#[test]
588+
fn test_server_knobs_appears_in_all_pings() {
589+
use crate::metrics::RemoteSettingsConfig;
590+
use std::collections::HashMap;
591+
592+
let (glean, _t) = new_glean(None);
593+
594+
let mut metrics_enabled = HashMap::new();
595+
metrics_enabled.insert("test.counter".to_string(), true);
596+
597+
let config = RemoteSettingsConfig {
598+
metrics_enabled,
599+
..Default::default()
600+
};
601+
glean.apply_server_knobs_config(config);
602+
603+
// Verify config appears in multiple different pings
604+
let ping_maker = PingMaker::new();
605+
let ping_info1 = ping_maker.get_ping_info(&glean, "store1", None, TimeUnit::Minute);
606+
let ping_info2 = ping_maker.get_ping_info(&glean, "store2", None, TimeUnit::Minute);
607+
608+
assert_eq!(ping_info1["server_knobs_config"]["metrics_enabled"]["test.counter"], true);
609+
assert_eq!(ping_info2["server_knobs_config"]["metrics_enabled"]["test.counter"], true);
610+
}
536611
}

0 commit comments

Comments
 (0)