1717package com .mongodb .internal .connection ;
1818
1919import com .mongodb .MongoDriverInformation ;
20+ import com .mongodb .annotations .ThreadSafe ;
2021import com .mongodb .internal .VisibleForTesting ;
2122import com .mongodb .internal .build .MongoDriverVersion ;
2223import com .mongodb .lang .Nullable ;
3233import java .io .File ;
3334import java .nio .charset .StandardCharsets ;
3435import java .nio .file .Files ;
36+ import java .util .ArrayList ;
3537import java .util .List ;
38+ import java .util .concurrent .locks .ReentrantReadWriteLock ;
3639import java .util .function .Consumer ;
3740
3841import static com .mongodb .assertions .Assertions .isTrueArgument ;
42+ import static com .mongodb .internal .Locks .withLock ;
3943import static com .mongodb .internal .connection .FaasEnvironment .getFaasEnvironment ;
4044import static java .lang .String .format ;
4145import static java .lang .System .getProperty ;
4246import static java .nio .file .Paths .get ;
4347
4448/**
49+ * Represents metadata of the current MongoClient.
50+ *
51+ * Metadata is used to identify the client in the server logs and metrics.
52+ *
4553 * <p>This class is not part of the public API and may be removed or changed at any time</p>
4654 */
47- public final class ClientMetadataHelper {
55+ @ ThreadSafe
56+ public class ClientMetadata {
4857 private static final String SEPARATOR = "|" ;
49-
5058 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+ });
6573 }
6674
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 );
6980 }
7081
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+ });
7890 }
7991
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 ) {
8294 if (applicationName != null ) {
8395 isTrueArgument ("applicationName UTF-8 encoding length <= 128" ,
8496 applicationName .getBytes (StandardCharsets .UTF_8 ).length <= 128 );
@@ -87,27 +99,26 @@ public static BsonDocument createClientMetadataDocument(@Nullable final String a
8799 // client fields are added in "preservation" order:
88100 BsonDocument client = new BsonDocument ();
89101 tryWithLimit (client , d -> putAtPath (d , "application.name" , applicationName ));
90- MongoDriverInformation baseDriverInfor = getDriverInformation ( null );
102+
91103 // required fields:
92104 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 ( ));
95107 });
96108 tryWithLimit (client , d -> putAtPath (d , "os.type" , getOperatingSystemType (getOperatingSystemName ())));
97109 // full driver information:
98- MongoDriverInformation fullDriverInfo = getDriverInformation (mongoDriverInformation );
99110 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 ()));
102113 });
103114
104115 // optional fields:
105116 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 ();
108119
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 ())));
111122 tryWithLimit (client , d -> putAtPath (d , "os.name" , getOperatingSystemName ()));
112123 tryWithLimit (client , d -> putAtPath (d , "os.architecture" , getProperty ("os.arch" , "unknown" )));
113124 tryWithLimit (client , d -> putAtPath (d , "os.version" , getProperty ("os.version" , "unknown" )));
@@ -123,7 +134,6 @@ public static BsonDocument createClientMetadataDocument(@Nullable final String a
123134 return client ;
124135 }
125136
126-
127137 private static void putAtPath (final BsonDocument d , final String path , @ Nullable final String value ) {
128138 if (value == null ) {
129139 return ;
@@ -180,7 +190,7 @@ static boolean clientMetadataDocumentTooLarge(final BsonDocument document) {
180190 return buffer .getPosition () > MAXIMUM_CLIENT_METADATA_ENCODED_SIZE ;
181191 }
182192
183- public enum ContainerRuntime {
193+ private enum ContainerRuntime {
184194 DOCKER ("docker" ) {
185195 @ Override
186196 boolean isCurrentRuntimeContainer () {
@@ -210,8 +220,8 @@ boolean isCurrentRuntimeContainer() {
210220 return false ;
211221 }
212222
213- static ContainerRuntime determineExecutionContainer () {
214- for (ContainerRuntime allegedContainer : ContainerRuntime .values ()) {
223+ static ClientMetadata . ContainerRuntime determineExecutionContainer () {
224+ for (ClientMetadata . ContainerRuntime allegedContainer : ClientMetadata . ContainerRuntime .values ()) {
215225 if (allegedContainer .isCurrentRuntimeContainer ()) {
216226 return allegedContainer ;
217227 }
@@ -245,8 +255,8 @@ boolean isCurrentOrchestrator() {
245255 return false ;
246256 }
247257
248- static Orchestrator determineExecutionOrchestrator () {
249- for (Orchestrator alledgedOrchestrator : Orchestrator .values ()) {
258+ static ClientMetadata . Orchestrator determineExecutionOrchestrator () {
259+ for (ClientMetadata . Orchestrator alledgedOrchestrator : ClientMetadata . Orchestrator .values ()) {
250260 if (alledgedOrchestrator .isCurrentOrchestrator ()) {
251261 return alledgedOrchestrator ;
252262 }
@@ -255,17 +265,6 @@ static Orchestrator determineExecutionOrchestrator() {
255265 }
256266 }
257267
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-
269268 private static String listToString (final List <String > listOfStrings ) {
270269 StringBuilder stringBuilder = new StringBuilder ();
271270 int i = 0 ;
@@ -279,6 +278,95 @@ private static String listToString(final List<String> listOfStrings) {
279278 return stringBuilder .toString ();
280279 }
281280
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+ }
283371 }
284372}
0 commit comments