Skip to content

Commit 498bc90

Browse files
committed
Feat: Let user specify a user agent prefix
This patch exposes an option in `SessionOptions` that a user can set, which will be prefixed to the beginning of the user agent sent to the broker during session negotiation. This prefix does not need to be set, but if it is, it must consist only of printable ASCII characters and must be less than 128 characters long. Signed-off-by: Patrick M. Niedzielski <[email protected]>
1 parent 138b049 commit 498bc90

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

bmq-sdk/src/main/java/com/bloomberg/bmq/SessionOptions.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Bloomberg Finance L.P.
2+
* Copyright 2022-2025 Bloomberg Finance L.P.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -62,6 +62,10 @@
6262
* HostHealthMonitor} interface responsible for notifying the session when the health of the
6363
* host machine has changed. A {@code hostHealthMonitor} must be specified in oder for queues
6464
* opened through the session to suspend on unhealthy hosts.
65+
* <li>{@code userAgentPrefix}: String to include in the user agent for broker telemetry. This
66+
* string must only contain printable characters and must be less than 128 characters long.
67+
* This is provided for libraries that are wrapping this SDK. Applications directly using the
68+
* SDK are encouraged <strong>NOT</strong> to set this value.
6569
* </ul>
6670
*
6771
* <H2>Thread Safety</H2>
@@ -215,6 +219,8 @@ public int highWaterMark() {
215219

216220
private final HostHealthMonitor hostHealthMonitor;
217221

222+
private final String userAgentPrefix;
223+
218224
private SessionOptions() {
219225
brokerUri = DEFAULT_URI;
220226
startTimeout = DEFAULT_START_TIMEOUT;
@@ -226,6 +232,7 @@ private SessionOptions() {
226232
configureQueueTimeout = QUEUE_OPERATION_TIMEOUT;
227233
closeQueueTimeout = QUEUE_OPERATION_TIMEOUT;
228234
hostHealthMonitor = null;
235+
userAgentPrefix = "";
229236
}
230237

231238
private SessionOptions(Builder builder) {
@@ -239,6 +246,7 @@ private SessionOptions(Builder builder) {
239246
configureQueueTimeout = builder.configureQueueTimeout;
240247
closeQueueTimeout = builder.closeQueueTimeout;
241248
hostHealthMonitor = builder.hostHealthMonitor;
249+
userAgentPrefix = builder.userAgentPrefix;
242250
}
243251

244252
/**
@@ -383,6 +391,16 @@ public HostHealthMonitor hostHealthMonitor() {
383391
return hostHealthMonitor;
384392
}
385393

394+
/**
395+
* Returns the string that will be prefixed to the user agent used by {@link
396+
* com.bloomberg.bmq.Session} to identify itself to the broker.
397+
*
398+
* @return String user agent string prefix
399+
*/
400+
public String userAgentPrefix() {
401+
return userAgentPrefix;
402+
}
403+
386404
/** Helper class to create a {@code SesssionOptions} object with custom settings. */
387405
public static class Builder {
388406
private URI brokerUri;
@@ -397,6 +415,9 @@ public static class Builder {
397415
private Duration closeQueueTimeout;
398416

399417
private HostHealthMonitor hostHealthMonitor;
418+
419+
private String userAgentPrefix;
420+
400421
/**
401422
* Creates a {@code SesssionOptions} object based on this {@code Builder} properties.
402423
*
@@ -417,6 +438,7 @@ private Builder(SessionOptions options) {
417438
configureQueueTimeout = options.configureQueueTimeout;
418439
closeQueueTimeout = options.closeQueueTimeout;
419440
hostHealthMonitor = options.hostHealthMonitor;
441+
userAgentPrefix = options.userAgentPrefix;
420442
}
421443

422444
/**
@@ -558,5 +580,29 @@ public Builder setHostHealthMonitor(HostHealthMonitor value) {
558580
hostHealthMonitor = Argument.expectNonNull(value, "host health monitor");
559581
return this;
560582
}
583+
584+
/**
585+
* Sets the user agent prefix. This string is prefixed to a user agent constructed by the
586+
* SDK. This is intended ONLY for other libraries that wrap this SDK to identify themselves
587+
* for broker telemetry. Applications that are directly using this SDK are encouraged not
588+
* to set this.
589+
*
590+
* @param value String user agent prefix
591+
* @return Builder this object
592+
* @throws NullPointerException if the specified value is null
593+
* @throws IllegalArgumentException in case the specified value contains non-ASCII
594+
* characters, contains non-printable characters (i.e., control characters), or is
595+
* longer than 127 characters.
596+
*/
597+
public Builder setUserAgentPrefix(String value) {
598+
Argument.expectNonNull(value, "user agent prefix");
599+
Argument.expectCondition(
600+
value.codePoints().allMatch(c -> c < 128 && !Character.isISOControl(c)),
601+
"user agent prefix must be printable ASCII");
602+
Argument.expectCondition(
603+
value.length() < 128, "user agent prefix must be shorter than 128 characters");
604+
userAgentPrefix = value;
605+
return this;
606+
}
561607
}
562608
}

bmq-sdk/src/main/java/com/bloomberg/bmq/impl/TcpBrokerConnection.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,13 @@ private NegotiationMessageChoice createNegoMsg() {
378378
}
379379

380380
private String constructUserAgent() {
381+
String prefix = "";
382+
if (connectionOptions.userAgentPrefix().length() > 0) {
383+
prefix = connectionOptions.userAgentPrefix() + " ";
384+
}
381385
String javaVersion = "java" + SystemUtil.getJavaVersionString();
382386
String sdkVersion = VersionUtil.getJarVersion();
383-
return "com.bloomberg.bmq(" + javaVersion + "):" + sdkVersion;
387+
return prefix + "com.bloomberg.bmq(" + javaVersion + "):" + sdkVersion;
384388
}
385389

386390
private WriteStatus negotiate() throws IOException {

bmq-sdk/src/main/java/com/bloomberg/bmq/impl/infr/net/ConnectionOptions.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 Bloomberg Finance L.P.
2+
* Copyright 2022-2025 Bloomberg Finance L.P.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,12 +39,14 @@ public final class ConnectionOptions {
3939
private int startNumRetries = DEFAULT_START_NUM_RETRIES;
4040
private Duration startRetryInterval = DEFAULT_START_RETRY_INTERVAL;
4141
private WriteBufferWaterMark writeWaterMark = new WriteBufferWaterMark();
42+
private String userAgentPrefix = "";
4243

4344
public ConnectionOptions() {}
4445

4546
public ConnectionOptions(SessionOptions sesOpts) {
4647
brokerUri = sesOpts.brokerUri();
4748
writeWaterMark = sesOpts.writeBufferWaterMark();
49+
userAgentPrefix = sesOpts.userAgentPrefix();
4850
}
4951

5052
public ConnectionOptions setBrokerUri(URI value) {
@@ -80,6 +82,17 @@ public ConnectionOptions setWriteBufferWaterMark(WriteBufferWaterMark value) {
8082
return this;
8183
}
8284

85+
public ConnectionOptions setUserAgentPrefix(String value) {
86+
Argument.expectNonNull(value, "user agent prefix");
87+
Argument.expectCondition(
88+
value.codePoints().allMatch(c -> c < 128 && !Character.isISOControl(c)),
89+
"user agent prefix must be printable ASCII");
90+
Argument.expectCondition(
91+
value.length() < 128, "user agent prefix must be shorter than 128 characters");
92+
userAgentPrefix = value;
93+
return this;
94+
}
95+
8396
public URI brokerUri() {
8497
return brokerUri;
8598
}
@@ -99,4 +112,8 @@ public Duration startRetryInterval() {
99112
public WriteBufferWaterMark writeBufferWaterMark() {
100113
return writeWaterMark;
101114
}
115+
116+
public String userAgentPrefix() {
117+
return userAgentPrefix;
118+
}
102119
}

0 commit comments

Comments
 (0)