glassfish
  1. glassfish
  2. GLASSFISH-19404

"get --monitor server.transaction-service.activeids-current" does not work when tx monitor-level is set to LOW (both standalone instance and clustered instance)

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 3.1.2.2
    • Fix Version/s: None
    • Component/s: monitoring
    • Labels:
      None

      Description

      when tx monitor-level is set to LOW by the commands below.
      "enable-monitoring --modules transaction-service"
      or
      "set monitoring-service.module-monitoring-levels.transaction-service"

      It could not get any inflight transaction info by the following command
      "get --monitor server.transaction-service.activeids-current"

        Activity

        Hide
        Wu Jie added a comment -

        there is the same phenomenon on admin gui.

        Show
        Wu Jie added a comment - there is the same phenomenon on admin gui.
        Hide
        Wu Jie added a comment -

        when execute "get --monitor server.transaction-service.activeids-current" ,
        it will run into com.sun.enterprise.v3.admin.MonitoringReporter#runLocally() as listing in below.

            private void runLocally() {
        
                // don't run if this is DAS **and** DAS is not in the server list.
                // otherwise we are in an instance and definitely want to run!
                if (isDas() && !dasIsInList())
                    return;
        
                // say the pattern is "something" -->
                // we want "server.something" for DAS and "i1.server.something" for i1
                // Yes -- this is difficult to get perfect!!!  What if user entered
                //"server.something"?
        
                String localPattern = prependServerDot(pattern);
                org.glassfish.flashlight.datatree.TreeNode tn = datareg.get(serverEnv.getInstanceName());
        
                if (tn == null) {
                    // No monitoring data, so nothing to list
                    // officially this is considered a "success"
                    setSuccess(Strings.get("admin.get.monitoring.empty"));
                    return;
                }
        
                List<org.glassfish.flashlight.datatree.TreeNode> ltn = tn.getNodes(localPattern);
                boolean singleStat = false;
        
                if (ltn == null || ltn.isEmpty()) {
                    org.glassfish.flashlight.datatree.TreeNode parent = tn.getPossibleParentNode(localPattern);
        
                    if (parent != null) {★
                        ltn = new ArrayList<org.glassfish.flashlight.datatree.TreeNode>(1);
                        ltn.add(parent);
                        singleStat = true;
                    }
                }
        
                if (!singleStat)
                    localPattern = null; // signal to method call below.  localPattern was already used above...
        
                if (outputType == OutputType.GET)
                    doGet(localPattern, ltn);
                else if (outputType == OutputType.LIST)
                    doList(localPattern, ltn);
        
                if (plainReporter != null) {
                    plainReporter.appendMessage(cliOutput.toString());
                }
            }
        

        when tx monitor-level is HIGH, the parent TreeNode that is marked as "★" above is not null, which has value as the attached file "parentTreeNode.png".
        but the parent TreeNode is null when tx monitor-level is LOW.

        It seems that the transaction info is not registered into TreeNode(MonitoringRuntimeDataRegistry?) ...

        Show
        Wu Jie added a comment - when execute "get --monitor server.transaction-service.activeids-current" , it will run into com.sun.enterprise.v3.admin.MonitoringReporter#runLocally() as listing in below. private void runLocally() { // don't run if this is DAS **and** DAS is not in the server list. // otherwise we are in an instance and definitely want to run! if (isDas() && !dasIsInList()) return ; // say the pattern is "something" --> // we want "server.something" for DAS and "i1.server.something" for i1 // Yes -- this is difficult to get perfect!!! What if user entered // "server.something" ? String localPattern = prependServerDot(pattern); org.glassfish.flashlight.datatree.TreeNode tn = datareg.get(serverEnv.getInstanceName()); if (tn == null ) { // No monitoring data, so nothing to list // officially this is considered a "success" setSuccess(Strings.get( "admin.get.monitoring.empty" )); return ; } List<org.glassfish.flashlight.datatree.TreeNode> ltn = tn.getNodes(localPattern); boolean singleStat = false ; if (ltn == null || ltn.isEmpty()) { org.glassfish.flashlight.datatree.TreeNode parent = tn.getPossibleParentNode(localPattern); if (parent != null ) {★ ltn = new ArrayList<org.glassfish.flashlight.datatree.TreeNode>(1); ltn.add(parent); singleStat = true ; } } if (!singleStat) localPattern = null ; // signal to method call below. localPattern was already used above... if (outputType == OutputType.GET) doGet(localPattern, ltn); else if (outputType == OutputType.LIST) doList(localPattern, ltn); if (plainReporter != null ) { plainReporter.appendMessage(cliOutput.toString()); } } when tx monitor-level is HIGH, the parent TreeNode that is marked as "★" above is not null, which has value as the attached file "parentTreeNode.png". but the parent TreeNode is null when tx monitor-level is LOW. It seems that the transaction info is not registered into TreeNode(MonitoringRuntimeDataRegistry?) ...
        Hide
        marina vatkina added a comment -

        "set monitoring-service.module-monitoring-levels.transaction-service" is not turning monitoring on, you should explicitly set it to LOW or HIGH

        This is the code that turns monitoring on/off is:

                   if (event.getSource() instanceof ModuleMonitoringLevels) {
                        if (eventName.equals(ServerTags.TRANSACTION_SERVICE)) {
                            String newlevel = newValue.toString();
                            _logger.log(Level.FINE, "Changing transaction monitoring level");
                            if ("OFF".equals(newlevel)) {
                                tm.setMonitoringEnabled(false);
                            } else if ("LOW".equals(newlevel) || "HIGH".equals(newlevel)) {
                                tm.setMonitoringEnabled(true);
                            }
                        } // else skip
        

        So no value is considered as a no-op

        Show
        marina vatkina added a comment - "set monitoring-service.module-monitoring-levels.transaction-service" is not turning monitoring on, you should explicitly set it to LOW or HIGH This is the code that turns monitoring on/off is: if (event.getSource() instanceof ModuleMonitoringLevels) { if (eventName.equals(ServerTags.TRANSACTION_SERVICE)) { String newlevel = newValue.toString(); _logger.log(Level.FINE, "Changing transaction monitoring level" ); if ( "OFF" .equals(newlevel)) { tm.setMonitoringEnabled( false ); } else if ( "LOW" .equals(newlevel) || "HIGH" .equals(newlevel)) { tm.setMonitoringEnabled( true ); } } // else skip So no value is considered as a no-op
        Hide
        Wu Jie added a comment -

        I got the difference between "set monitoring-service.module-monitoring-levels.transaction-service" and "enable-monitoring --modules transaction-service".
        but this issue is not related to the source above which is the segment of TransactionServiceConfigListener.

        I observed that there is some difference between OFF->HIGH and OFF->LOW
        when I change tx monitoring level from OFF to HIGH.
        the runtime will run along the route as below.

        Daemon Thread [pool-130-thread-1] (Suspended)
        TransactionServiceStatsProvider.getActiveIds() line: 135
        GeneratedMethodAccessor130.invoke(Object, Object[]) line: not available
        DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
        Method.invoke(Object, Object...) line: 601
        MethodInvokerImpl.getValue() line: 90
        StatsProviderManagerDelegateImpl.resetChildNodeStatistics(String, List<String>, String) line: 556
        StatsProviderManagerDelegateImpl.resetStatistics(StatsProviderRegistry$StatsProviderRegistryElement) line: 539
        StatsProviderManagerDelegateImpl.enableStatsProvider(StatsProviderRegistry$StatsProviderRegistryElement) line: 389
        StatsProviderManagerDelegateImpl.enableStatsProviders(String) line: 329
        MonitoringBootstrap.handleLevelChange(String, String) line: 569
        MonitoringBootstrap.changed(PropertyChangeEvent[]) line: 521
        Transactions$ConfigListenerJob.process(ConfigListener) line: 401
        Transactions$ConfigListenerJob.process(Object) line: 391
        Transactions$ConfigListenerNotifier$1$1.call() line: 281
        Transactions$ConfigListenerNotifier$1$1.call() line: 279
        FutureTask$Sync.innerRun() line: 334
        FutureTask<V>.run() line: 166
        ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1110
        ThreadPoolExecutor$Worker.run() line: 603
        Thread.run() line: 722

        but the situation which is OFF->LOW does not run the route above.

        and look into related source, I doubt the source as following(org.glassfish.admin.monitor.StatsProviderManagerDelegateImpl).

            public void enableStatsProviders(String configElement) {
                //If monitoring-enabled is false, just return
                if (!getMonitoringEnabled())
                    return;
                String configLevel = getMonitoringLevel(configElement);
                //Enable all the StatsProviders for a given configElement
                if (logger.isLoggable(Level.FINE))
                    logger.fine("Enabling all the statsProviders for - " + configElement);
                List<StatsProviderRegistryElement> spreList = statsProviderRegistry.getStatsProviderRegistryElement(configElement);
                if (spreList == null)
                    return;
                for (StatsProviderRegistryElement spre : spreList) {
                    //Check to see if the enable is allowed
                    // Not allowed if statsProvider is registered for Low and configLevel is HIGH
                    boolean isEnableAllowed = spre.isEnableAllowed(configLevel);★
                    if (!spre.isEnabled()) {
                        //OFF->LOW, OFF->HIGH
                        if (isEnableAllowed) {
                            enableStatsProvider(spre);
                        }
                    }
                    else {
                        //Disable if the stats were enabled, but current level is not allowed for these stats(HIGH->LOW) and
                        // stats were registered at HIGH
                        if (!isEnableAllowed) {
                            disableStatsProvider(spre);
                        }// else, Dont do anything LOW->HIGH (stats were registered at LOW)
                    }
                }
            }
        

        the "isEnableAllowed" which is marked as "★" will be false in the situations as below.
        ・OFF->LOW
        ・HIGH->LOW

        I think is there any wrong with the style.
        and the "isEnableAllowed" should be true when OFF->LOW.

        Show
        Wu Jie added a comment - I got the difference between "set monitoring-service.module-monitoring-levels.transaction-service" and "enable-monitoring --modules transaction-service". but this issue is not related to the source above which is the segment of TransactionServiceConfigListener. I observed that there is some difference between OFF->HIGH and OFF->LOW when I change tx monitoring level from OFF to HIGH. the runtime will run along the route as below. Daemon Thread [pool-130-thread-1] (Suspended) TransactionServiceStatsProvider.getActiveIds() line: 135 GeneratedMethodAccessor130.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 601 MethodInvokerImpl.getValue() line: 90 StatsProviderManagerDelegateImpl.resetChildNodeStatistics(String, List<String>, String) line: 556 StatsProviderManagerDelegateImpl.resetStatistics(StatsProviderRegistry$StatsProviderRegistryElement) line: 539 StatsProviderManagerDelegateImpl.enableStatsProvider(StatsProviderRegistry$StatsProviderRegistryElement) line: 389 StatsProviderManagerDelegateImpl.enableStatsProviders(String) line: 329 MonitoringBootstrap.handleLevelChange(String, String) line: 569 MonitoringBootstrap.changed(PropertyChangeEvent[]) line: 521 Transactions$ConfigListenerJob.process(ConfigListener) line: 401 Transactions$ConfigListenerJob.process(Object) line: 391 Transactions$ConfigListenerNotifier$1$1.call() line: 281 Transactions$ConfigListenerNotifier$1$1.call() line: 279 FutureTask$Sync.innerRun() line: 334 FutureTask<V>.run() line: 166 ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1110 ThreadPoolExecutor$Worker.run() line: 603 Thread.run() line: 722 but the situation which is OFF->LOW does not run the route above. and look into related source, I doubt the source as following(org.glassfish.admin.monitor.StatsProviderManagerDelegateImpl). public void enableStatsProviders( String configElement) { //If monitoring-enabled is false , just return if (!getMonitoringEnabled()) return ; String configLevel = getMonitoringLevel(configElement); //Enable all the StatsProviders for a given configElement if (logger.isLoggable(Level.FINE)) logger.fine( "Enabling all the statsProviders for - " + configElement); List<StatsProviderRegistryElement> spreList = statsProviderRegistry.getStatsProviderRegistryElement(configElement); if (spreList == null ) return ; for (StatsProviderRegistryElement spre : spreList) { //Check to see if the enable is allowed // Not allowed if statsProvider is registered for Low and configLevel is HIGH boolean isEnableAllowed = spre.isEnableAllowed(configLevel);★ if (!spre.isEnabled()) { //OFF->LOW, OFF->HIGH if (isEnableAllowed) { enableStatsProvider(spre); } } else { //Disable if the stats were enabled, but current level is not allowed for these stats(HIGH->LOW) and // stats were registered at HIGH if (!isEnableAllowed) { disableStatsProvider(spre); } // else , Dont do anything LOW->HIGH (stats were registered at LOW) } } } the "isEnableAllowed" which is marked as "★" will be false in the situations as below. ・OFF->LOW ・HIGH->LOW I think is there any wrong with the style. and the "isEnableAllowed" should be true when OFF->LOW.
        Hide
        marina vatkina added a comment -

        If this is the case, the error is in monitoring code.

        Show
        marina vatkina added a comment - If this is the case, the error is in monitoring code.
        Hide
        Wu Jie added a comment -

        the logic of "isEnableAllowed" is abstracted from org.glassfish.admin.monitor.StatsProviderRegistry as following:

                public boolean isEnableAllowed(String userConfigLevelStr) {
                    Integer userConfigLevel = StatsProviderRegistry.configLevelsMap.get(userConfigLevelStr.toUpperCase());
                    if ((userConfigLevel != null) && (userConfigLevel >= configLevel))//※the value of configLevel is always "1" which equals to "HIGH"
                        return true;
                    return false;
                }
        

        ※the value of configLevel is always "1" which equals to "HIGH" which related to the following source.

            static final String[] defaultConfigLevels = new String[] {"LOW","HIGH"};
            public static final Map<String, Integer> configLevelsMap = new ConcurrentHashMap();
        
            public StatsProviderRegistry(MonitoringRuntimeDataRegistry mrdr) {
                this.mrdr = mrdr;
                for (int i = 0; i < defaultConfigLevels.length; i++) {
                    configLevelsMap.put(defaultConfigLevels[i].toUpperCase(), i);
                }
            }
        
            public void registerStatsProvider(StatsProviderInfo spInfo) {
                String configLevelStr = spInfo.getConfigLevel();
        
                if (configLevelStr == null) {
                    // Pick the highest in the configLevels
                    spInfo.setConfigLevel(defaultConfigLevels[defaultConfigLevels.length-1]);//★
                }
        
                StatsProviderRegistryElement spre =
                            new StatsProviderRegistryElement(spInfo);
                initialize(spre, spInfo.getConfigElement(), spInfo.getStatsProvider());
            }
        

        the source which marked as "★" set the configLevelStr to "HIGH".

        as the logic above, the "isEnableAllowed" returns false regardless of OFF->LOW or HIGH->LOW.
        and I think the src logic may be modified as below.
        ① set configLevelStr to "LOW" as initial value.
        ② change the StatsProviderInfo#configLevel when monitoring level has been changed(LOW or HIGH).

        Show
        Wu Jie added a comment - the logic of "isEnableAllowed" is abstracted from org.glassfish.admin.monitor.StatsProviderRegistry as following: public boolean isEnableAllowed( String userConfigLevelStr) { Integer userConfigLevel = StatsProviderRegistry.configLevelsMap.get(userConfigLevelStr.toUpperCase()); if ((userConfigLevel != null ) && (userConfigLevel >= configLevel)) //※the value of configLevel is always "1" which equals to "HIGH" return true ; return false ; } ※the value of configLevel is always "1" which equals to "HIGH" which related to the following source. static final String [] defaultConfigLevels = new String [] { "LOW" , "HIGH" }; public static final Map< String , Integer > configLevelsMap = new ConcurrentHashMap(); public StatsProviderRegistry(MonitoringRuntimeDataRegistry mrdr) { this .mrdr = mrdr; for ( int i = 0; i < defaultConfigLevels.length; i++) { configLevelsMap.put(defaultConfigLevels[i].toUpperCase(), i); } } public void registerStatsProvider(StatsProviderInfo spInfo) { String configLevelStr = spInfo.getConfigLevel(); if (configLevelStr == null ) { // Pick the highest in the configLevels spInfo.setConfigLevel(defaultConfigLevels[defaultConfigLevels.length-1]); //★ } StatsProviderRegistryElement spre = new StatsProviderRegistryElement(spInfo); initialize(spre, spInfo.getConfigElement(), spInfo.getStatsProvider()); } the source which marked as "★" set the configLevelStr to "HIGH". as the logic above, the "isEnableAllowed" returns false regardless of OFF->LOW or HIGH->LOW. and I think the src logic may be modified as below. ① set configLevelStr to "LOW" as initial value. ② change the StatsProviderInfo#configLevel when monitoring level has been changed(LOW or HIGH).
        Hide
        Wu Jie added a comment -

        I create a patch and it works fine. cloud you please confirm it.

        Show
        Wu Jie added a comment - I create a patch and it works fine. cloud you please confirm it.

          People

          • Assignee:
            Byron Nevins
            Reporter:
            Wu Jie
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: