# monitor

* [monitor](#monitor)
  * [monitor for controller](#monitor-for-controller)
  * [monitor for agents](#monitor-for-agents)

> \[!TIP|label:get sizer dynamically]
>
> ```groovy
> Closure sizer = { long size ->
>   List units    = [ 'bytes', 'KB', 'MB', 'GB', 'TB', 'PB' ]
>   double bits   = size
>   String result = bits > 0 ? "${bits.round(2)} bytes" : '0'
>   units.eachWithIndex { unit, index ->
>     if ( bits < 1024 ) return
>     bits   = bits / 1024
>     result = "${bits.round(2)} ${units.get(index+1)}"
>   }
>   result
> }
> ```

### monitor

> \[!NOTE|label:references:]
>
> * [Jenkins : Monitoring Scripts](https://wiki.jenkins.io/display/JENKINS/Monitoring+Scripts)
> * [Monitoring dashboard for Jenkins memory usage analysis.](https://medium.com/@maheshd7878/monitoring-dashboard-for-jenkins-memory-usage-analysis-31f4a70285b5)
> * [Documentation of JavaMelody](https://github.com/javamelody/javamelody/wiki/UserGuide)
> * [Class index](https://javadoc.io/doc/net.bull.javamelody/javamelody-core/1.68.1/index-all.html)
>   * [Class JavaInformations](https://javadoc.io/static/net.bull.javamelody/javamelody-core/1.68.1/net/bull/javamelody/internal/model/JavaInformations.html)
>   * [Class MemoryInformations](https://javadoc.io/static/net.bull.javamelody/javamelody-core/1.68.1/net/bull/javamelody/internal/model/MemoryInformations.html)

#### monitor for controller

* memory

  ```groovy

  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  Closure sizer = { long size ->
    List units    = [ 'bytes', 'KB', 'MB', 'GB', 'TB', 'PB' ]
    double bits   = size
    String result = bits > 0 ? "${bits.round(2)} bytes" : '0'
    units.eachWithIndex { unit, index ->
      if ( bits < 1024 ) return
      bits   = bits / 1024
      result = "${bits.round(2)} ${units.get(index+1)}"
    }
    result
  }

  memory = new MemoryInformations()
  println """
             used memory : ${sizer(memory.usedMemory)}
              max memory : ${sizer(memory.maxMemory)}
           used perm gen : ${sizer(memory.usedPermGen)}
            max perm gen : ${sizer(memory.maxPermGen)}
           used non heap : ${sizer(memory.usedNonHeapMemory)}
    used physical memory : ${sizer(memory.usedPhysicalMemorySize)}
         used swap space : ${sizer(memory.usedSwapSpaceSize)}
  """
  ```
* http sessions

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  println SessionListener.getSessionCount() + " sessions:"
  sessions = SessionListener.getAllSessionsInformations()
  sessions.each { session ->
    println session
  }
  ```
* thread dumps

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  java = new JavaInformations(Parameters.getServletContext(), true)
  threads = java.getThreadInformationsList()
  println threads.size() + " threads (" + java.activeThreadCount + " http threads active):"
  threads.each { thread ->
    println "\n${thread}"
    thread.getStackTrace().each { s ->
      println "    " + s
    }
  }
  ```
* deadlock threads

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  java = new JavaInformations(Parameters.getServletContext(), true)
  threads = java.getThreadInformationsList()
  deadlocked = new java.util.ArrayList()
  for (thread in threads) {
    if (thread.deadlocked)
      deadlocked.add(thread)
  }
  println deadlocked.size() + " deadlocked threads / " + threads.size() + " threads (" + java.activeThreadCount + " http threads active)"
  deadlocked.each { thread ->
    println "\n${thread}"
    thread.getStackTrace().each { s ->
      println "    " + s
    }
  }
  ```
* JVM data

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  java = new JavaInformations( Parameters.getServletContext(), true )
  println """
                          sessions count : ${java.sessionCount}
               active HTTP threads count : ${java.activeThreadCount}
                           threads count : ${java.threadCount}
                     system load average : ${java.systemLoadAverage}
                         system cpu load : ${java.systemCpuLoad}
                    available processors : ${java.availableProcessors}
                                    host : ${java.host}
                                      os : ${java.os}
                            java version : ${java.javaVersion}
                             jvm version : ${java.jvmVersion}
                                     pid : ${java.pid}
                             server info : ${java.serverInfo}
                            context path : ${java.contextPath}
                              start date : ${java.startDate}
    free disk space in Jenkins directory : ${Math.round(java.freeDiskSpaceInTemp / 1024 / 1024)} Mb
  """
  ```

  * result

    ```groovy
                          sessions count : 10
               active HTTP threads count : 1
                           threads count : 551
                     system load average : 0.23
                         system cpu load : 0.21985650348135538
                    available processors : 72
                                    host : devops-jenkins-bf57ddfbc-26mjz@10.244.13.138
                                      os : Linux, 4.19.12-1.el7.elrepo.x86_64 , amd64/64
                            java version : OpenJDK Runtime Environment, 11.0.18+10
                             jvm version : OpenJDK 64-Bit Server VM, 11.0.18+10, mixed mode
                                     pid : 7
                             server info : jetty/10.0.13
                            context path :
                              start date : Wed May 10 23:45:43 PDT 2023
    free disk space in Jenkins directory : 1709602 Mb
    ```
* heap histogram ( dangerous )

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  classes = VirtualMachine.createHeapHistogram().getHeapHistogram()
  println "class    instances    bytes    source"
  println "====================================="
  classes.each { c ->
    println c.name + "    " + c.instancesCount + "    " + c.bytes + "    " + c.source
  }
  ```
* heap dump ( dangerous )

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  if (System.getProperty("java.vendor").contains("IBM")) {
    Action.HEAP_DUMP.ibmHeapDump()
    println I18N.getString("heap_dump_genere_ibm")
  } else {
    heapDumpPath = Action.HEAP_DUMP.heapDump().getPath()
    println I18N.getFormattedString("heap_dump_genere", heapDumpPath)
  }
  ```
* MBean attribute value

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  exampleAttribute = "java.lang:type=OperatingSystem.ProcessCpuTime"
  println exampleAttribute + " = " + MBeans.getConvertedAttributes(exampleAttribute)
  ```
* stats of builds and build steps having mean time greater than severe threshold

  > \[!NOTE|label:by default:] By default, severe threshold = 2 x stddev of all durations and warning threshold = 1 x stddev

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  buildCounter = CounterRunListener.getBuildCounter()
  aggreg = new CounterRequestAggregation(buildCounter)
  aggreg.getRequests().findAll{ request ->
    request.getMean() >= aggreg.getSevereThreshold() ||
    request.getCpuTimeMean() >= aggreg.getSevereThreshold()
  }.each { request ->
    println """
      ${request.getName()} :
                         hits = ${request.getHits()}
                         mean = ${request.getMean()}
                          max = ${request.getMaximum()}
                       stddev = ${request.getStandardDeviation()}
                  cpuTimeMean = ${request.getCpuTimeMean()}
        systemErrorPercentage = ${request.getSystemErrorPercentage()}
    """
  }
  ```
* GC

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  before = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
  System.gc()
  after = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()

  println I18N.getFormattedString( "ramasse_miette_execute", Math.round((before - after) / 1024) )
  ```
* alerts

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  Closure sizer = { long size ->
    List units    = [ 'bytes', 'KB', 'MB', 'GB', 'TB', 'PB' ]
    double bits   = size
    String result = bits > 0 ? "${bits.round(2)} bytes" : '0'
    units.eachWithIndex { unit, index ->
      if ( bits < 1024 ) return
      bits   = bits / 1024
      result = "${bits.round(2)} ${units.get(index+1)}"
    }
    result
  }

  java = new JavaInformations(Parameters.getServletContext(), true)
  memory = java.memoryInformations

  println """
                             used memory = ${sizer(memory.usedMemory)}
               active HTTP threads count = ${java.activeThreadCount}
                     system load average = ${java.systemLoadAverage}
    free disk space in Jenkins directory = ${sizer(java.freeDiskSpaceInTemp)}
  """

  threads = java.getThreadInformationsList()
  deadlocked = new java.util.ArrayList()
  threads.each { thread ->
    if ( thread.deadlocked ) deadlocked.add(thread)
  }
  println deadlocked.size() + " deadlocked threads / " + threads.size() + " threads"
  deadlocked.each { thread ->
    println """
      ${thread} :
        ${thread.getStackTrace().collect { it }.join('\n' + ' '*10)}
    """
  }

  if (java.systemLoadAverage > 50                    ) throw new Exception( "Alert for Jenkins: systemLoadAverage is " + java.systemLoadAverage )
  if (java.activeThreadCount > 100                   ) throw new Exception( "Alert for Jenkins: activeThreadCount is " + java.activeThreadCount )
  if (deadlocked.size() > 0                          ) throw new Exception( "Alert for Jenkins: " + deadlocked.size( ) + " deadlocked threads"  )
  if (java.freeDiskSpaceInTemp / 1024 / 1024 < 10000 ) throw new Exception( "Alert for Jenkins: only " + Math.round(java.freeDiskSpaceInTemp / 1024 / 1024 ) + " Mb free disk space left"                                  )
  ```

#### monitor for agents

* jvm data, memory data, deadlocked threads

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  Closure sizer = { long size ->
    List units    = [ 'bytes', 'KB', 'MB', 'GB', 'TB', 'PB' ]
    String result = bits > 0 ? "${bits.round(2)} bytes" : '0'
    double bits   = size
    units.eachWithIndex { unit, index ->
      if ( bits < 1024 ) return
      bits   = bits / 1024
      result = "${bits.round(2)} ${units.get(index+1)}"
    }
    result
  }

  // null for all nodes, not null for a particular node
  String nodeName   = null
  Map mapByNodeName = new RemoteCallHelper(nodeName).collectJavaInformationsListByName()

  mapByNodeName.keySet().each { node ->
    java = mapByNodeName.get(node)
    println """
      Node : ${node} :
                   sessions count : ${java.sessionCount}
        active HTTP threads count : ${java.activeThreadCount}
                    threads count : ${java.threadCount}
              system load average : ${java.systemLoadAverage}
                  system cpu load : ${java.systemCpuLoad}
             available processors : ${java.availableProcessors}
                             host : ${java.host}
                               os : ${java.os}
                     java version : ${java.javaVersion}
                      jvm version : ${java.jvmVersion}
                              pid : ${java.pid}
                      server info : ${java.serverInfo}
                     context path : ${java.contextPath}
                       start date : ${java.startDate}
    """

    memory = java.memoryInformations
    println """
                      used memory : ${sizer(memory.usedMemory)}
                       max memory : ${sizer(memory.maxMemory)}
                    used perm gen : ${sizer(memory.usedPermGen)}
                     max perm gen : ${sizer(memory.maxPermGen)}
                    used non heap : ${sizer(memory.usedNonHeapMemory)}
             used physical memory : ${sizer(memory.usedPhysicalMemorySize)}
                  used swap space : ${sizer(memory.usedSwapSpaceSize)}
    """

    threads = java.getThreadInformationsList()
    List deadlocked = threads.findAll{ it.deadlocked }
    println """
                           thread : ${deadlocked.size()} deadlocked threads / ${threads.size()} threads ( ${java.activeThreadCount} threads active )
    """
    deadlocked.collectEntries { thread -> [ "${thread}" : ${thread.getStackTrace().collect{ t}} ] }
              .each { thread, s ->
                 println """
                   ${thread} :
                   ${s.join('\n' + ' '*20)}
                 """
              }
    println ' '*10 + '*'*60
  }
  ```
* aa

  ```groovy
  import net.bull.javamelody.*
  import net.bull.javamelody.internal.model.*
  import net.bull.javamelody.internal.common.*

  String exampleAttributes = "java.lang:type=OperatingSystem.ProcessCpuTime|java.lang:type=Memory.HeapMemoryUsage"
  // null for all nodes, not null for a particular node
  String nodeName = null
  List values = new RemoteCallHelper(nodeName).collectJmxValues(exampleAttributes)
  values.each { value ->
    println exampleAttributes + " = " + value
  }
  ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://imarslo.gitbook.io/book/jenkins/script/monitor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
