Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bean subscription #426

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
4fc47e2
Initial bean listening, adds attributes that match config
scottopell Apr 7, 2023
e104ed2
Moves bean subscription into dedicated thread
scottopell Apr 10, 2023
9fee19d
Removes ConnectionListener
scottopell Apr 10, 2023
0b996df
Adds test covering basic bean subscription functionality
scottopell Apr 12, 2023
75a1bbc
Consolidate attribute matching and take 'ACTION' into account
scottopell Apr 12, 2023
9e624cf
Utilize 'synchronized' keyword for simpler locking
scottopell Apr 12, 2023
75d9296
Adds audit logging to bean refresh to catch any gaps in bean subscrip…
scottopell Apr 12, 2023
e4b2e6d
Shortens test timeframes for subscription to be processed
scottopell Apr 17, 2023
ff15967
Back to explicit locking
scottopell Apr 17, 2023
e0600d3
Removes un-necessary lockholder class
scottopell Apr 17, 2023
64d8438
implements bean unsubscription
scottopell Apr 17, 2023
fe8c168
Merge branch 'master' into feat/bean-listener
scottopell May 19, 2023
7f7c1a6
Adds extra logging instructions for misbehaving jmx server
scottopell May 19, 2023
1bd15f0
Adds dedicated remote container bean subscription tests
scottopell May 19, 2023
4fd1b09
Removes old mutex debugging code
scottopell May 22, 2023
57f1970
Adds bean unsubscription test and (failing) bean subscription w/ netw…
scottopell May 22, 2023
6670056
Adds JMX connection listener to mark instance as broken on connection…
scottopell May 22, 2023
d74319a
Removes un-needed bean subscriber thread
scottopell May 23, 2023
fe7705c
Clarifies bean-audit logging
scottopell May 23, 2023
c26e91b
Updates in-proc bean subscription tests with more attribute counting …
scottopell May 23, 2023
d746e40
Removes explicit locking in favor of 'synchronized'
scottopell May 23, 2023
090f0dc
Adds owned thread to process mbean subscription events
scottopell May 23, 2023
c3fbfe6
Remove some unused logs and accidental regressions
scottopell May 23, 2023
addb80f
Addresses linting errors
scottopell May 24, 2023
08cee1b
Renames ambiguous interface from BeanListener -> BeanTracker
scottopell May 24, 2023
27dc057
Fixes bug where metricReached would display multiple times incorrectly
scottopell May 24, 2023
642ee12
Corrects old name and var decl
scottopell May 31, 2023
4d9ce86
Merge branch 'master' into feat/bean-listener
scottopell Jun 5, 2023
e8c2b68
Adds toggle to turn on bean subscription globally
scottopell Jun 5, 2023
d1bd7b8
Merge branch 'master' into feat/bean-listener
scottopell Jul 5, 2023
79ce047
Adds env vars to enable subscription globally for validation
scottopell Jul 5, 2023
dcf963c
Updates TestBeanSubscription to use container IP directly similar to …
scottopell Jul 6, 2023
781db37
Merge branch 'master' into feat/bean-listener
scottopell Dec 27, 2023
905532a
Re-land changes from #481
scottopell Dec 27, 2023
bad14d0
Removes random idea for deployment validation
scottopell Dec 27, 2023
be3c9b4
Relands bean match ratio from #487
scottopell Dec 27, 2023
c118cc2
Fixes whoopsie
scottopell Dec 27, 2023
ea0bf5b
Fixes divide by zero bug introduced in previous commit
scottopell Dec 27, 2023
82bbc94
Adds tlm for beans registered and unregistered
scottopell Dec 27, 2023
b40c5d6
Update tools/misbehaving-jmx-server/README.md
scottopell Dec 28, 2023
34290a1
Fixes linting errors
scottopell Dec 28, 2023
617f4f6
Merge branch 'master' into feat/bean-listener
scottopell Jan 17, 2024
01e760c
Removes per-instance bean-subscription enablement in favor of applica…
scottopell Jan 17, 2024
34ab16b
Merge branch 'master' into feat/bean-listener
scottopell Jan 17, 2024
03eeff0
Merge branch 'master' into feat/bean-listener
scottopell Jan 25, 2024
95820e9
Fixes linter warning
scottopell Jan 25, 2024
f916745
Fixes spy usage in bean sub tests
scottopell Jan 25, 2024
ff5e64f
Adds env var enablement for backwards compatibility during rollout
scottopell Feb 8, 2024
5dfcd96
Merge branch 'master' into feat/bean-listener
scottopell Feb 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/main/java/org/datadog/jmxfetch/BeanListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.datadog.jmxfetch;

import javax.management.ObjectName;

public interface BeanListener {
public void beanRegistered(ObjectName mBeanName);
public void beanUnregistered(ObjectName mBeanName);
}
29 changes: 29 additions & 0 deletions src/main/java/org/datadog/jmxfetch/BeanSubscriber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.datadog.jmxfetch;

import java.util.concurrent.CompletableFuture;
import java.util.List;

public class BeanSubscriber implements Runnable {
private List<String> beanScopes;
private Connection connection;
private BeanListener listener;
public CompletableFuture<Boolean> subscriptionSuccessful;

BeanSubscriber(List<String> beanScopes, Connection connection, BeanListener listener) {
this.beanScopes = beanScopes;
this.connection = connection;
this.listener = listener;
this.subscriptionSuccessful = new CompletableFuture<Boolean>();
}

public void run() {
try {
connection.subscribeToBeanScopes(beanScopes, this.listener);
this.subscriptionSuccessful.complete(true);

Thread.currentThread().join();
} catch (Exception e) {
this.subscriptionSuccessful.complete(false);
}
}
}
42 changes: 42 additions & 0 deletions src/main/java/org/datadog/jmxfetch/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
Expand All @@ -21,8 +23,16 @@
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerDelegate;
import javax.management.relation.MBeanServerNotificationFilter;
import javax.management.MBeanServerNotification;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
Expand All @@ -36,6 +46,38 @@ public class Connection {
protected Map<String, Object> env;
protected JMXServiceURL address;

private static class BeanNotificationListener implements NotificationListener {
private BeanListener bl;

public BeanNotificationListener(BeanListener bl) {
this.bl = bl;
}
public void handleNotification(Notification notification, Object handback) {
if (!(notification instanceof MBeanServerNotification)) {
log.warn("Got unknown notification, expected MBeanServerNotification but got {}", notification.getClass());
return;
}
MBeanServerNotification mbs = (MBeanServerNotification) notification;
log.debug("MBeanNotification: ts {} seqNum: {} msg: '{}' userData: {} ", mbs.getTimeStamp(), mbs.getSequenceNumber(), mbs.getMessage(), mbs.getUserData());
ObjectName mBeanName = mbs.getMBeanName();
if (mbs.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
bl.beanRegistered(mBeanName);
} else if (mbs.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
this.bl.beanUnregistered(mBeanName);
}
}
}

public void subscribeToBeanScopes(List<String> beanScopes, BeanListener bl) throws MalformedObjectNameException, IOException, InstanceNotFoundException{
BeanNotificationListener listener = new BeanNotificationListener(bl);
for (String scope : beanScopes) {
ObjectName name = new ObjectName(scope);
MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter();
filter.enableObjectName(name);
}
mbs.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, listener, null, null);
}

/** Gets attributes for matching bean name. */
public MBeanAttributeInfo[] getAttributesForBean(ObjectName beanName)
throws InstanceNotFoundException, IntrospectionException, ReflectionException,
Expand Down
Loading