8
8
import static datadog .trace .api .telemetry .LoginEvent .LOGIN_SUCCESS ;
9
9
import static datadog .trace .api .telemetry .LoginEvent .SIGN_UP ;
10
10
import static datadog .trace .util .Strings .toHexString ;
11
+ import static java .util .Collections .emptyMap ;
11
12
12
13
import datadog .appsec .api .blocking .BlockingException ;
14
+ import datadog .appsec .api .user .User ;
15
+ import datadog .appsec .api .user .UserService ;
13
16
import datadog .trace .api .EventTracker ;
14
17
import datadog .trace .api .GlobalTracer ;
15
18
import datadog .trace .api .ProductTraceSource ;
27
30
import datadog .trace .bootstrap .instrumentation .api .Tags ;
28
31
import java .security .MessageDigest ;
29
32
import java .security .NoSuchAlgorithmException ;
33
+ import java .util .Base64 ;
30
34
import java .util .Map ;
31
35
import java .util .function .BiFunction ;
32
36
33
- public class AppSecEventTracker extends EventTracker {
37
+ public class AppSecEventTracker extends EventTracker implements UserService {
34
38
35
39
private static final int HASH_SIZE_BYTES = 16 ; // 128 bits
36
40
private static final String ANON_PREFIX = "anon_" ;
@@ -40,7 +44,9 @@ public class AppSecEventTracker extends EventTracker {
40
44
private static final String SIGNUP_TAG = "users.signup" ;
41
45
42
46
public static void install () {
43
- GlobalTracer .setEventTracker (new AppSecEventTracker ());
47
+ final AppSecEventTracker tracker = new AppSecEventTracker ();
48
+ GlobalTracer .setEventTracker (tracker );
49
+ User .setUserService (tracker );
44
50
}
45
51
46
52
@ Override
@@ -68,6 +74,15 @@ public final void trackCustomEvent(String eventName, Map<String, String> metadat
68
74
onCustomEvent (SDK , eventName , metadata );
69
75
}
70
76
77
+ @ Override
78
+ public void trackUserEvent (
79
+ final String userId , final Map <String , String > metadata , final boolean propagated ) {
80
+ if (userId == null || userId .isEmpty ()) {
81
+ throw new IllegalArgumentException ("UserId is null or empty" );
82
+ }
83
+ onUserEvent (SDK , userId , metadata , propagated );
84
+ }
85
+
71
86
public void onUserNotFound (final UserIdCollectionMode mode ) {
72
87
if (!isEnabled (mode )) {
73
88
return ;
@@ -88,6 +103,14 @@ public void onUserNotFound(final UserIdCollectionMode mode) {
88
103
}
89
104
90
105
public void onUserEvent (final UserIdCollectionMode mode , final String userId ) {
106
+ onUserEvent (mode , userId , emptyMap (), false );
107
+ }
108
+
109
+ public void onUserEvent (
110
+ final UserIdCollectionMode mode ,
111
+ final String userId ,
112
+ final Map <String , String > metadata ,
113
+ final boolean propagated ) {
91
114
if (!isEnabled (mode )) {
92
115
return ;
93
116
}
@@ -105,9 +128,15 @@ public void onUserEvent(final UserIdCollectionMode mode, final String userId) {
105
128
}
106
129
if (mode != SDK ) {
107
130
segment .setTagTop ("_dd.appsec.usr.id" , finalUserId );
131
+ } else if (propagated ) {
132
+ // only the SDK can propagate usr.id
133
+ segment .setTagTop ("_dd.p.usr.id" , encodeBase64 (finalUserId ));
108
134
}
109
135
if (isNewUser (mode , segment )) {
110
136
segment .setTagTop ("usr.id" , finalUserId );
137
+ if (metadata != null && !metadata .isEmpty ()) {
138
+ segment .setTagTop ("usr" , metadata );
139
+ }
111
140
segment .setTagTop ("_dd.appsec.user.collection_mode" , mode .fullName ());
112
141
segment .setTagTop (Tags .ASM_KEEP , true );
113
142
segment .setTagTop (Tags .PROPAGATED_TRACE_SOURCE , ProductTraceSource .ASM );
@@ -357,6 +386,10 @@ protected static String anonymizeUser(final UserIdCollectionMode mode, final Str
357
386
return ANON_PREFIX + toHexString (hash );
358
387
}
359
388
389
+ protected static String encodeBase64 (final String userId ) {
390
+ return Base64 .getEncoder ().encodeToString (userId .getBytes ());
391
+ }
392
+
360
393
protected boolean isEnabled (final UserIdCollectionMode mode ) {
361
394
return mode == SDK || (ActiveSubsystems .APPSEC_ACTIVE && mode != DISABLED );
362
395
}
0 commit comments