17
17
package com .mongodb .internal .connection ;
18
18
19
19
import com .mongodb .MongoDriverInformation ;
20
+ import com .mongodb .annotations .ThreadSafe ;
20
21
import com .mongodb .internal .VisibleForTesting ;
21
22
import com .mongodb .internal .build .MongoDriverVersion ;
22
23
import com .mongodb .lang .Nullable ;
32
33
import java .io .File ;
33
34
import java .nio .charset .StandardCharsets ;
34
35
import java .nio .file .Files ;
36
+ import java .util .ArrayList ;
35
37
import java .util .List ;
38
+ import java .util .concurrent .locks .ReentrantReadWriteLock ;
36
39
import java .util .function .Consumer ;
37
40
38
41
import static com .mongodb .assertions .Assertions .isTrueArgument ;
42
+ import static com .mongodb .internal .Locks .withLock ;
39
43
import static com .mongodb .internal .connection .FaasEnvironment .getFaasEnvironment ;
40
44
import static java .lang .String .format ;
41
45
import static java .lang .System .getProperty ;
42
46
import static java .nio .file .Paths .get ;
43
47
44
48
/**
49
+ * Represents metadata of the current MongoClient.
50
+ *
51
+ * Metadata is used to identify the client in the server logs and metrics.
52
+ *
45
53
* <p>This class is not part of the public API and may be removed or changed at any time</p>
46
54
*/
47
- public final class ClientMetadataHelper {
55
+ @ ThreadSafe
56
+ public class ClientMetadata {
48
57
private static final String SEPARATOR = "|" ;
49
-
50
58
private static final int MAXIMUM_CLIENT_METADATA_ENCODED_SIZE = 512 ;
51
-
52
- @ VisibleForTesting ( otherwise = VisibleForTesting . AccessModifier . PRIVATE )
53
- static String getOperatingSystemType ( final String operatingSystemName ) {
54
- if ( nameStartsWith ( operatingSystemName , "linux" )) {
55
- return "Linux" ;
56
- } else if ( nameStartsWith ( operatingSystemName , "mac" ) ) {
57
- return "Darwin" ;
58
- } else if ( nameStartsWith ( operatingSystemName , "windows" )) {
59
- return "Windows" ;
60
- } else if ( nameStartsWith ( operatingSystemName , "hp-ux" , "aix" , "irix" , "solaris" , "sunos" )) {
61
- return "Unix" ;
62
- } else {
63
- return "unknown" ;
64
- }
59
+ private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock ();
60
+ private final String applicationName ;
61
+ private BsonDocument clientMetadataBsonDocument ;
62
+ private DriverInformation driverInformation ;
63
+
64
+ public ClientMetadata ( @ Nullable final String applicationName , final MongoDriverInformation mongoDriverInformation ) {
65
+ this . applicationName = applicationName ;
66
+ withLock ( readWriteLock . writeLock (), () -> {
67
+ this . driverInformation = DriverInformation . from (
68
+ mongoDriverInformation . getDriverNames (),
69
+ mongoDriverInformation . getDriverVersions (),
70
+ mongoDriverInformation . getDriverPlatforms ());
71
+ this . clientMetadataBsonDocument = createClientMetadataDocument ( applicationName , driverInformation ) ;
72
+ });
65
73
}
66
74
67
- private static String getOperatingSystemName () {
68
- return getProperty ("os.name" , "unknown" );
75
+ /**
76
+ * Returns mutable BsonDocument that represents the client metadata.
77
+ */
78
+ public BsonDocument getBsonDocument () {
79
+ return withLock (readWriteLock .readLock (), () -> clientMetadataBsonDocument );
69
80
}
70
81
71
- private static boolean nameStartsWith (final String name , final String ... prefixes ) {
72
- for (String prefix : prefixes ) {
73
- if (name .toLowerCase ().startsWith (prefix .toLowerCase ())) {
74
- return true ;
75
- }
76
- }
77
- return false ;
82
+ public void append (final MongoDriverInformation mongoDriverInformationToAppend ) {
83
+ withLock (readWriteLock .writeLock (), () -> {
84
+ this .driverInformation .append (
85
+ mongoDriverInformationToAppend .getDriverNames (),
86
+ mongoDriverInformationToAppend .getDriverVersions (),
87
+ mongoDriverInformationToAppend .getDriverPlatforms ());
88
+ this .clientMetadataBsonDocument = createClientMetadataDocument (applicationName , driverInformation );
89
+ });
78
90
}
79
91
80
- public static BsonDocument createClientMetadataDocument (@ Nullable final String applicationName ,
81
- @ Nullable final MongoDriverInformation mongoDriverInformation ) {
92
+ private static BsonDocument createClientMetadataDocument (@ Nullable final String applicationName ,
93
+ final DriverInformation driverInformation ) {
82
94
if (applicationName != null ) {
83
95
isTrueArgument ("applicationName UTF-8 encoding length <= 128" ,
84
96
applicationName .getBytes (StandardCharsets .UTF_8 ).length <= 128 );
@@ -87,27 +99,26 @@ public static BsonDocument createClientMetadataDocument(@Nullable final String a
87
99
// client fields are added in "preservation" order:
88
100
BsonDocument client = new BsonDocument ();
89
101
tryWithLimit (client , d -> putAtPath (d , "application.name" , applicationName ));
90
- MongoDriverInformation baseDriverInfor = getDriverInformation ( null );
102
+
91
103
// required fields:
92
104
tryWithLimit (client , d -> {
93
- putAtPath (d , "driver.name" , listToString ( baseDriverInfor . getDriverNames () ));
94
- putAtPath (d , "driver.version" , listToString ( baseDriverInfor . getDriverVersions () ));
105
+ putAtPath (d , "driver.name" , driverInformation . getInitialDriverName ( ));
106
+ putAtPath (d , "driver.version" , driverInformation . getInitialDriverVersion ( ));
95
107
});
96
108
tryWithLimit (client , d -> putAtPath (d , "os.type" , getOperatingSystemType (getOperatingSystemName ())));
97
109
// full driver information:
98
- MongoDriverInformation fullDriverInfo = getDriverInformation (mongoDriverInformation );
99
110
tryWithLimit (client , d -> {
100
- putAtPath (d , "driver.name" , listToString (fullDriverInfo . getDriverNames ()));
101
- putAtPath (d , "driver.version" , listToString (fullDriverInfo . getDriverVersions ()));
111
+ putAtPath (d , "driver.name" , listToString (driverInformation . getAllDriverNames ()));
112
+ putAtPath (d , "driver.version" , listToString (driverInformation . getAllDriverVersions ()));
102
113
});
103
114
104
115
// optional fields:
105
116
FaasEnvironment faasEnvironment = getFaasEnvironment ();
106
- ContainerRuntime containerRuntime = ContainerRuntime .determineExecutionContainer ();
107
- Orchestrator orchestrator = Orchestrator .determineExecutionOrchestrator ();
117
+ ClientMetadata . ContainerRuntime containerRuntime = ClientMetadata . ContainerRuntime .determineExecutionContainer ();
118
+ ClientMetadata . Orchestrator orchestrator = ClientMetadata . Orchestrator .determineExecutionOrchestrator ();
108
119
109
- tryWithLimit (client , d -> putAtPath (d , "platform" , listToString ( baseDriverInfor . getDriverPlatforms () )));
110
- tryWithLimit (client , d -> putAtPath (d , "platform" , listToString (fullDriverInfo . getDriverPlatforms ())));
120
+ tryWithLimit (client , d -> putAtPath (d , "platform" , driverInformation . getInitialDriverPlatform ( )));
121
+ tryWithLimit (client , d -> putAtPath (d , "platform" , listToString (driverInformation . getAllDriverPlatforms ())));
111
122
tryWithLimit (client , d -> putAtPath (d , "os.name" , getOperatingSystemName ()));
112
123
tryWithLimit (client , d -> putAtPath (d , "os.architecture" , getProperty ("os.arch" , "unknown" )));
113
124
tryWithLimit (client , d -> putAtPath (d , "os.version" , getProperty ("os.version" , "unknown" )));
@@ -123,7 +134,6 @@ public static BsonDocument createClientMetadataDocument(@Nullable final String a
123
134
return client ;
124
135
}
125
136
126
-
127
137
private static void putAtPath (final BsonDocument d , final String path , @ Nullable final String value ) {
128
138
if (value == null ) {
129
139
return ;
@@ -180,7 +190,7 @@ static boolean clientMetadataDocumentTooLarge(final BsonDocument document) {
180
190
return buffer .getPosition () > MAXIMUM_CLIENT_METADATA_ENCODED_SIZE ;
181
191
}
182
192
183
- public enum ContainerRuntime {
193
+ private enum ContainerRuntime {
184
194
DOCKER ("docker" ) {
185
195
@ Override
186
196
boolean isCurrentRuntimeContainer () {
@@ -210,8 +220,8 @@ boolean isCurrentRuntimeContainer() {
210
220
return false ;
211
221
}
212
222
213
- static ContainerRuntime determineExecutionContainer () {
214
- for (ContainerRuntime allegedContainer : ContainerRuntime .values ()) {
223
+ static ClientMetadata . ContainerRuntime determineExecutionContainer () {
224
+ for (ClientMetadata . ContainerRuntime allegedContainer : ClientMetadata . ContainerRuntime .values ()) {
215
225
if (allegedContainer .isCurrentRuntimeContainer ()) {
216
226
return allegedContainer ;
217
227
}
@@ -245,8 +255,8 @@ boolean isCurrentOrchestrator() {
245
255
return false ;
246
256
}
247
257
248
- static Orchestrator determineExecutionOrchestrator () {
249
- for (Orchestrator alledgedOrchestrator : Orchestrator .values ()) {
258
+ static ClientMetadata . Orchestrator determineExecutionOrchestrator () {
259
+ for (ClientMetadata . Orchestrator alledgedOrchestrator : ClientMetadata . Orchestrator .values ()) {
250
260
if (alledgedOrchestrator .isCurrentOrchestrator ()) {
251
261
return alledgedOrchestrator ;
252
262
}
@@ -255,17 +265,6 @@ static Orchestrator determineExecutionOrchestrator() {
255
265
}
256
266
}
257
267
258
- static MongoDriverInformation getDriverInformation (@ Nullable final MongoDriverInformation mongoDriverInformation ) {
259
- MongoDriverInformation .Builder builder = mongoDriverInformation != null ? MongoDriverInformation .builder (mongoDriverInformation )
260
- : MongoDriverInformation .builder ();
261
- return builder
262
- .driverName (MongoDriverVersion .NAME )
263
- .driverVersion (MongoDriverVersion .VERSION )
264
- .driverPlatform (format ("Java/%s/%s" , getProperty ("java.vendor" , "unknown-vendor" ),
265
- getProperty ("java.runtime.version" , "unknown-version" )))
266
- .build ();
267
- }
268
-
269
268
private static String listToString (final List <String > listOfStrings ) {
270
269
StringBuilder stringBuilder = new StringBuilder ();
271
270
int i = 0 ;
@@ -279,6 +278,95 @@ private static String listToString(final List<String> listOfStrings) {
279
278
return stringBuilder .toString ();
280
279
}
281
280
282
- private ClientMetadataHelper () {
281
+ @ VisibleForTesting (otherwise = VisibleForTesting .AccessModifier .PRIVATE )
282
+ public static String getOperatingSystemType (final String operatingSystemName ) {
283
+ if (nameStartsWith (operatingSystemName , "linux" )) {
284
+ return "Linux" ;
285
+ } else if (nameStartsWith (operatingSystemName , "mac" )) {
286
+ return "Darwin" ;
287
+ } else if (nameStartsWith (operatingSystemName , "windows" )) {
288
+ return "Windows" ;
289
+ } else if (nameStartsWith (operatingSystemName , "hp-ux" , "aix" , "irix" , "solaris" , "sunos" )) {
290
+ return "Unix" ;
291
+ } else {
292
+ return "unknown" ;
293
+ }
294
+ }
295
+
296
+ private static String getOperatingSystemName () {
297
+ return getProperty ("os.name" , "unknown" );
298
+ }
299
+
300
+ private static boolean nameStartsWith (final String name , final String ... prefixes ) {
301
+ for (String prefix : prefixes ) {
302
+ if (name .toLowerCase ().startsWith (prefix .toLowerCase ())) {
303
+ return true ;
304
+ }
305
+ }
306
+ return false ;
307
+ }
308
+
309
+ /**
310
+ * Holds driver information of client.driver field
311
+ * in {@link ClientMetadata#clientMetadataBsonDocument}.
312
+ */
313
+ private static class DriverInformation {
314
+ private final List <String > driverNames ;
315
+ private final List <String > driverVersions ;
316
+ private final List <String > driverPlatforms ;
317
+ private final String initialPlatform ;
318
+
319
+ DriverInformation () {
320
+ this .driverNames = new ArrayList <>();
321
+ driverNames .add (MongoDriverVersion .NAME );
322
+
323
+ this .driverVersions = new ArrayList <>();
324
+ driverVersions .add (MongoDriverVersion .VERSION );
325
+
326
+ this .initialPlatform = format ("Java/%s/%s" , getProperty ("java.vendor" , "unknown-vendor" ),
327
+ getProperty ("java.runtime.version" , "unknown-version" ));
328
+ this .driverPlatforms = new ArrayList <>();
329
+ driverPlatforms .add (initialPlatform );
330
+ }
331
+
332
+ static DriverInformation from (final List <String > driverNames ,
333
+ final List <String > driverVersions ,
334
+ final List <String > driverPlatforms ) {
335
+ DriverInformation driverInformation = new DriverInformation ();
336
+ return driverInformation .append (driverNames , driverVersions , driverPlatforms );
337
+ }
338
+
339
+ DriverInformation append (final List <String > driverNames ,
340
+ final List <String > driverVersions ,
341
+ final List <String > driverPlatforms ) {
342
+ this .driverNames .addAll (driverNames );
343
+ this .driverVersions .addAll (driverVersions );
344
+ this .driverPlatforms .addAll (driverPlatforms );
345
+ return this ;
346
+ }
347
+
348
+ public String getInitialDriverPlatform () {
349
+ return initialPlatform ;
350
+ }
351
+
352
+ public String getInitialDriverName () {
353
+ return MongoDriverVersion .NAME ;
354
+ }
355
+
356
+ public String getInitialDriverVersion () {
357
+ return MongoDriverVersion .VERSION ;
358
+ }
359
+
360
+ public List <String > getAllDriverNames () {
361
+ return driverNames ;
362
+ }
363
+
364
+ public List <String > getAllDriverVersions () {
365
+ return driverVersions ;
366
+ }
367
+
368
+ public List <String > getAllDriverPlatforms () {
369
+ return driverPlatforms ;
370
+ }
283
371
}
284
372
}
0 commit comments