Skip to content

Commit e4da07f

Browse files
[Backport 7.82.x] removed user_id from ai-usage event (#54272)
Backport 2fff8b4 from #54019. ___ <!--Please give us some feedback on your experience writing this PR ! https://app.datadoghq.com/forms/43db4c02-6837-400c-8083-692e141b1b88 !--> ### What does this PR do? This PR removes `user_id` field from AI-usage event. `user_id `is taken care of by the backend, ensuring consistent attribution across browser-extension and desktop-monitor modes. ### Motivation [WINA-2958](https://datadoghq.atlassian.net/browse/WINA-2958) ### Describe how you validated your changes Validation is done through end-to-end testing. ### Additional Notes [WINA-2958]: https://datadoghq.atlassian.net/browse/WINA-2958?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: avonengel <axel.vonengel@datadoghq.com>
1 parent 330a261 commit e4da07f

6 files changed

Lines changed: 20 additions & 35 deletions

File tree

cmd/ai_prompt_logger/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Relevant config keys under `desktop_monitoring`:
8484

8585
Broad runtime names such as `node.exe`/`node`, `python.exe`/`python`, and `conhost.exe` are not direct AI-tool matches by default because they need command-line or path inspection to avoid false positives.
8686

87-
Desktop events use the extension-compatible field semantics: tool display name, provider, user ID, and approved flag. The event source is `desktop_app`.
87+
Desktop events use the extension-compatible field semantics: tool display name, provider, and approved flag. The event source is `desktop_app`.
8888

8989
On Windows, `--desktop-monitor` detaches from the scheduler-created console after startup. When file logging is enabled for diagnostics or startup config errors need to be reported, logs are written to `C:\ProgramData\Datadog\logs\ai-usage-desktop-monitor.log`, falling back to `%LOCALAPPDATA%\Datadog\logs\ai-usage-desktop-monitor.log` if the ProgramData log path is unavailable. Each record includes the process ID and user. The log rotates at 10 MB with one `.1` backup.
9090

@@ -117,7 +117,6 @@ Request (shape used by the AI usage extension):
117117
{
118118
"type": "SEND_USAGE_EVENT",
119119
"tool": "example",
120-
"user_id": "user-1",
121120
"approved": true
122121
}
123122
```

cmd/ai_prompt_logger/scripts/test_host.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def test_send_usage_event(proc):
5454
{
5555
'type': 'SEND_USAGE_EVENT',
5656
'tool': 'test-tool',
57-
'user_id': 'test-user',
5857
'approved': True,
5958
},
6059
)

cmd/ai_prompt_logger/src/datadog.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ pub struct AiUsageEvent {
248248
pub detection_type: String,
249249
pub source: String,
250250
pub tool: String,
251-
pub user_id: String,
252251
pub hostname: String,
253252
pub approved: bool,
254253
#[serde(skip_serializing_if = "Option::is_none")]
@@ -257,18 +256,11 @@ pub struct AiUsageEvent {
257256

258257
impl AiUsageEvent {
259258
/// Create a new event with the fixed fields pre-populated.
260-
pub fn new(
261-
detection_type: &str,
262-
tool: String,
263-
user_id: String,
264-
hostname: String,
265-
approved: bool,
266-
) -> Self {
259+
pub fn new(detection_type: &str, tool: String, hostname: String, approved: bool) -> Self {
267260
Self::new_with_source(
268261
detection_type,
269262
"browser_extension",
270263
tool,
271-
user_id,
272264
hostname,
273265
approved,
274266
)
@@ -278,7 +270,6 @@ impl AiUsageEvent {
278270
detection_type: &str,
279271
source: &str,
280272
tool: String,
281-
user_id: String,
282273
hostname: String,
283274
approved: bool,
284275
) -> Self {
@@ -288,7 +279,6 @@ impl AiUsageEvent {
288279
detection_type: detection_type.to_string(),
289280
source: source.to_string(),
290281
tool,
291-
user_id,
292282
hostname,
293283
approved,
294284
provider: None,
@@ -310,13 +300,8 @@ mod tests {
310300

311301
#[test]
312302
fn ai_usage_body_keeps_event_fields_at_top_level() {
313-
let mut event = AiUsageEvent::new(
314-
"observed",
315-
"gemini".to_string(),
316-
"user@example.com".to_string(),
317-
"host-1".to_string(),
318-
true,
319-
);
303+
let mut event =
304+
AiUsageEvent::new("observed", "gemini".to_string(), "host-1".to_string(), true);
320305
event.provider = Some("Google".to_string());
321306

322307
let body = DatadogClient::ai_usage_body(&event).expect("AI usage body should serialize");
@@ -334,6 +319,7 @@ mod tests {
334319
Some(&Value::String("Google".to_string()))
335320
);
336321
assert_eq!(body.get("approved"), Some(&Value::Bool(true)));
322+
assert!(!body.contains_key("user_id"));
337323
assert!(!body.contains_key("message"));
338324
assert!(!body.contains_key("ddsource"));
339325
assert!(!body.contains_key("service"));

cmd/ai_prompt_logger/src/desktop/mod.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@ fn poll_once(
181181
return;
182182
}
183183

184-
let user_id = resolve_user_id();
185184
let hostname = resolve_hostname();
186185
for detection in detections {
187186
logger.info(format!(
@@ -198,7 +197,6 @@ fn poll_once(
198197
"observed",
199198
"desktop_app",
200199
detection.tool,
201-
user_id.clone(),
202200
hostname.clone(),
203201
detection.approved,
204202
);
@@ -327,15 +325,6 @@ fn read_write_activity_observed(delta: &ProcessActivityDelta) -> bool {
327325
.any(|delta| delta > 0)
328326
}
329327

330-
/// Resolve the user identifier attached to observed desktop usage events.
331-
fn resolve_user_id() -> String {
332-
std::env::var("USERNAME")
333-
.or_else(|_| std::env::var("USER"))
334-
.ok()
335-
.filter(|user| !user.is_empty())
336-
.unwrap_or_else(|| "unknown".to_string())
337-
}
338-
339328
/// Emit debug details about hosted AI candidates and their foreground process ancestry.
340329
fn log_process_tree_diagnostics(
341330
foreground: &ProcessInfo,
@@ -579,6 +568,7 @@ fn descendant_pids_of(
579568
mod tests {
580569
use super::*;
581570
use crate::datadog::DesktopMonitoringConfig;
571+
use crate::desktop::matcher::ProcessEdge;
582572

583573
fn config() -> DesktopMonitoringConfig {
584574
DesktopMonitoringConfig {

cmd/ai_prompt_logger/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ enum Request {
3636
tool: String,
3737
#[serde(default)]
3838
provider: Option<String>,
39-
user_id: String,
4039
#[serde(default)]
4140
approved: bool,
4241
},
@@ -107,11 +106,10 @@ fn handle_message(dd_client: &DatadogClient, request: Request) -> Response {
107106
Request::SendUsageEvent {
108107
tool,
109108
provider,
110-
user_id,
111109
approved,
112110
} => {
113111
let resolved_host = resolve_hostname();
114-
let mut event = AiUsageEvent::new("observed", tool, user_id, resolved_host, approved);
112+
let mut event = AiUsageEvent::new("observed", tool, resolved_host, approved);
115113
let prov = provider
116114
.as_deref()
117115
.filter(|s| !s.is_empty())
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Each section from every release note are combined when the
2+
# CHANGELOG.rst is rendered. So the text needs to be worded so that
3+
# it does not depend on any information only available in another
4+
# section. This may mean repeating some details, but each section
5+
# must be readable independently of the other.
6+
#
7+
# Each section note must be formatted as reStructuredText.
8+
---
9+
fixes:
10+
- |
11+
Removed ``user_id`` field from AI usage event to avoid inconsistency
12+
between Chrome extension mode and desktop-monitor mode. ``user_id``
13+
is taken care of by Datadog backend.

0 commit comments

Comments
 (0)