{"id":33485025,"url":"https://github.com/apple/pollianna","last_synced_at":"2026-01-16T12:28:42.779Z","repository":{"id":326316445,"uuid":"1098762102","full_name":"apple/pollianna","owner":"apple","description":null,"archived":false,"fork":false,"pushed_at":"2025-11-27T03:53:05.000Z","size":182,"stargazers_count":54,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-29T21:31:35.073Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apple.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-18T05:34:01.000Z","updated_at":"2025-11-29T16:17:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/apple/pollianna","commit_stats":null,"previous_names":["apple/pollianna"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/apple/pollianna","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apple%2Fpollianna","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apple%2Fpollianna/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apple%2Fpollianna/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apple%2Fpollianna/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apple","download_url":"https://codeload.github.com/apple/pollianna/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apple%2Fpollianna/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-11-25T16:00:34.251Z","updated_at":"2026-01-16T12:28:42.764Z","avatar_url":"https://github.com/apple.png","language":"Java","funding_links":[],"categories":["指标库"],"sub_categories":[],"readme":"# Pollianna\nPollianna is a Java library and Java command line agent\nthat accumulates JVM metrics over user-determined polling intervals and exposes them via JMX,\nso that they can be consumed by both Java and non-Java telemetry data sinks.\n\nPollianna also has an API which exposes the same JVM metrics through method calls.\nAdditionally, it allows specifying an OpenTelemetry compatible endpoint to publish metrics to.\n\nThe offered metrics are intended to facilitate Java service deployment configuration and operation\nand to support best-practice continuous monitoring.\n\n* [List of Metrics](docs/metrics-list.md)\n* [Specific Garbage Collector Considerations](docs/gc-specifics.md)\n\n## Metrics Delivery\n\nThere are three distinct but not mutually exclusive ways to use Pollianna.\n1. Register JMX beans that serve JVM metrics data via bean attributes.\n   You can then apply a JMX scraper such as Prometheus to transport metrics from these JXM Beans.\n2. Configure an OpenTelemetry endpoint.\n   Pollianna will then directly send your selected metrics there.\n3. Retrieve JVM metric data by local API calls. \n   No JMX involved. \n   How you further disseminate the metric data is then up to you.\n\n### 1. Starting JMX Beans\n\nAll Pollianna JMX beans must be instated in one of these three ways:\n- by a call to a Java method, typically very early in the `main()` program,\n- by adding Pollianna as a Java command line agent to a JVM command line,\n- by attaching Pollianna as a Java agent to a running JVM.\n\n#### Starting JMX Beans by a Static Method Call\nPollianna can be started by:\n```java\nPollianna.start();\n```\nWithout any arguments, this call installs and starts the \"Jvm\" bean,\nso is equivalent:\n```java\nPollianna.start(\"Jvm\");\n```\n\nIf arguments are given, they configure, install, and start\none or several of Pollianna's JVM observation beans.\nAll arguments must be of type `String` and they are evaluated left-to-right.\n\nIf an argument begins with the keyword `file` followed by a colon (':'),\nthen it specifies a file path and all arguments in that file,\nseparated by semicolons (';'), are evaluated.\nExamples:\n```java\nPollianna.start(\"file:relative-path/pollianna-arguments.txt\");\n```\n```java\nPollianna.start(\"file:/absolute-path/pollianna-arguments.txt\");\n```\n\nIf an argument begins with the keyword `interval` followed by a colon (':'),\nthen the rest of the argument specifies the interval time in seconds\nto be used for periodic sampling (of RT and NMT metrics). The default is 10.\nExample:\n```java\nPollianna.start(\"interval:5\");\n```\n\nOtherwise, an argument specifies a bean name.\nIf that name is followed by a pipe character ('|'),\nthen only the bean attributes listed after the colon will be exposed to JMX.\nIf an attribute has a non-primitive return type then its name has\nthe base name of a getter method in that type as a suffix.\nExample: if the bean named before the colon has an attribute \"Pause\"\nstemming from its getter method `getPause()`,\nand the return type of `getPause()` has a getter method 'getMax()',\nthen the complete attribute name is \"PauseMax\".\nExample bean argument with select attributes:\n```java\n\"GcAggregate|PauseMax,CycleAvg,AllocationRateMax\"\n```\nIf the same bean name is specified multiple times, only the right-most argument applies.\n\nThe available beans are: `Jvm`, `RtAggregate`, `RtSample`, `GcAggregate`, `GcSample`, `CompilerAggregate`, and `CompilerSample`.\nIf the JDK in use supports NMT data discovery by a dedicated JMX bean (see below),\nthen these additional beans are available: `NmtAggregate` and `NmtSample`.\n\nExample with multiple arguments:\n```java\nPollianna.start(\"interval:20\", \"RtSample\", \"GcAggregate|PauseMax,CycleAvg,AllocationRateMax\", \"file:morePolliannaArguments.txt\");\n```\n\n#### Pollianna as Java Command Line Agent\nAdding this to your JVM command line invokes Pollianna without touching your application's source code.\n```bash\n-javaagent:pollianna-1.16.1.jar\n```\nYou can provide the same arguments as for a Pollianna invocation by method call,\nexcept that they have to be combined into one single string in which they are separated by semicolons.\nFull example:\n```shell\njava -Xms4G -Xmx4G \\\n     -javaagent:pollianna-1.16.1.jar=\"interval:20;NmtSample;GcAggregate|PauseMax,CycleAvg,AllocationRateMax;file:morePolliannaArguments.txt\" \\\n     MyApplication\n```\nThis sets the sampling interval for NMT data to every 20 seconds, \nstarts the `NmtSample` bean, starts the `GcAggregate` bean with a few select attributes,\nand then reads and applies additional arguments from local file `\"morePolliannaArguments.txt\"`.\n\n#### Attaching the Pollianna Agent to a Running JVM\n\nInstead of specifying the agent on the command line,\noperators can also dynamically attach it to a running Java program.\nThis leaves the original deployment code intact,\nbut requires additional code for the agent's deployment,\nits activation, and local service PID discovery.\n\n#### Enabling NMT Data\nPollianna beans for Native Memory Tracking (NMT) data will only function if:\n1. The observed JDK provides all the classes and methods which are reflectively referenced in \"NmtAccess.java\".\n   (Vanilla OpenJDK does not have these.)\n2. The command line option `-XX:NativeMemoryTracking=summary` or `-XX:NativeMemoryTracking=detail` is used. \n   Only `summary` is needed for Pollianna, but you can also choose `detail` if needed for other purposes.\n\n### 2. Publishing Metrics with OpenTelemetry\n\nCollected metrics can be published to an OpenTelemetry-compatible target,\nconfigured by the following parameters:\n\n| Argument name                   | Required | Description                                                                |\n|:--------------------------------|:--------:|:---------------------------------------------------------------------------|\n| `otel_endpoint`                 |  `yes`   | OpenTelemetry gRPC endpoint.                                               |\n| `otel_service_name`             |  `yes`   | Service name to attach to all metrics                                      |\n| `otel_trusted_root`             |  `yes`   | Path to trusted CA file (PEM).                                             |\n| `otel_client_keystore`          |  `yes`   | Path to keystore with mTLS credentials.                                    |\n| `otel_client_keystore_password` |   `no`   | Path to file containing keystore password, defaults to empty password.     |\n| `otel_headers`                  |   `no`   | Headers to set and send with requests. Supports env vars for values.       |\n| `otel_labels`                   |   `no`   | Additional labels to set on metrics. Supports env vars for values.         |\n| `otel_interval`                 |   `no`   | The metrics polling and OTel publishing interval, in seconds. Default: 60. |\n\nExample command line:\n\n```shell\njava -Xms4G -Xmx4G \\\n     -javaagent:/somewhere/pollianna-1.16.1-iso.jar=\"Jvm;otel_endpoint:https://example-ingestion-gateway.telemetry.example.com:2345;otel_service_name:my_service;otel_client_keystore:/somewhere/application.p12;otel_trusted_root:/somewhere/trusted-root.pem;otel_headers:WORKSPACE=my_workspace,MY_EXTRAS=my_extras;otel_labels:cluster=a_custer,namespace=a_namespace,pod=$HOSTNAME;otel_interval:360\" MyApplication\n```\n\nThis will publish the default metrics, see `JVM Essentials` in [metrics-list.md](./docs/metrics-list.md#jvm-essentials).\nAlternative metric sets can be hand-picked with the same syntax as described above.\n\nNote: It is necessary to use the \"fat\" or the \"iso\" JAR variant,\neither of which includes the necessary dependencies to use OpenTelemetry,\nor to include the [dependencies](#releases) on the class path.\n\n### 3. Pollianna API\n\nIf you have other means of transporting and consuming metrics than through JMX or OpenTelemetry,\nyou can query JVM metrics by local calls to Pollianna's API.\nIt is then up to you how to further disseminate the gathered data.\n\nThe names of the involved classes correspond directly to the names of the above JMX beans, plus the suffix \"Seed\".\nExample: there is a JMX bean name \"GcAggregate\" and an API class `GcAggregateSeed`.\nBackground: a \"seed\" is what is inside a \"bean\", without the shell, the JMX wrapper.\nExample:\n```java\nfinal JvmSeed jvm = new JvmSeed();\njvm.startRecording();\n...\nfinal double maxJavaHeapWorkloadPercentage = jvm.getGcWorkloadMax()\n...\n```\n\nSee [Pollianna API Examples](src/test/java/com/apple/pollianna/PolliannaApiExamples.java) for more details on\nhow to create seed objects and how to activate and query them. \nThere is an example for each available seed class.\nBoth aggregating and sampling style are supported.\n\n#### GC Aggregating and Sampling\nAll GC metrics are produced by listening to _**asynchronous**_ GC events that occur inside the JVM.\nThey are captured whenever GC activities occur,\nwhich is decoupled from when users query Pollianna for GC data.\nThis is the same for aggregate and sampled GC data, since a GC \"sample\" is a remembered value,\nlike any aggregate, albeit with no computation involved.\nIn either case you need to call `startRecording()` to begin processing GC events,\nwhich makes GC metrics available.\n\n#### NMT Aggregating\n\nNMT data are based on _**synchronous**_ polling from outside the JVM.\nNMT aggregating is always performed periodically, at a fixed interval,\nThis is started by calling `startRecording()`.\nThis interval, with default value 10 seconds, can only be changed globally,\nand only before any sampling seed or JMX bean has started recording.\nFor example, this call changes the NMT recording interval from the default to 5 seconds:\n```java\nPeridodicAggregator.setIntervalSeconds(5);\n```\n\n#### NMT Sampling\n\nFor NMT sampling you have a choice between two strategies:\n1. Call `startRecording()` to have samples recorded periodically in the background.\n   When you query results, they will maximally be as old as the length of the global sampling interval.\n2. Call `recordNow()` to explicitly invoke one sample recording at any given time. \n   If you query a result immediately after this, it will be current.\n\nYou can use both approaches, but whichever recording is the most recent when querying determines the resulting values.\n\n### Sampling and Aggregating Miscellaneous Other Runtime Data\n\nSampling with `RtSampleSeed` works exactly as with `NmtSampleSeed`,\nwith the same choice between `startRecording()` and `recordNow()`.\nAnd the same basic calls that apply to `NmtAggregatSeed` also apply to `RtAggregateSeed`.\n\nExample:\n```java\n    final RtAggregateSeed seed = new RtAggregateSeed();\n    final long mappedMemoryBytes = seed.getMappedMemory();\n```\n\n## Building\nThis command creates ready-to-use JAR files and places them into `./build/libs`.\n```shell\n./gradlew build\n```\nExcluding testing:\n```shell\n./gradlew build -x test\n```\n\nThese alternative JAR files are created:\n- Without any dependencies (\"slim JAR\"): `pollianna-\u003cversion\u003e.jar`. \n  This is sufficient if you do not configure OpenTelemetry or if you have the required dependencies for OpenTelemetry on your classpath.\n- With all dependencies included (\"fat JAR\"): `pollianna-\u003cversion\u003e-all.jar`.\n- With all dependencies included and isolated (\"iso JAR\"): `pollianna-\u003cversion\u003e-iso.jar`.\n  Must be used as command line agent.\n  All dependencies will be isolated from the application by a custom class loader with a separate claspath.\n\n## Testing\n```shell\n./gradlew test\n```\nIn addition, this command tests Pollianna with every garbage collector available\nin the JDK that it is running on.\n```shell\nsrc/test/test.sh\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapple%2Fpollianna","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapple%2Fpollianna","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapple%2Fpollianna/lists"}