From 0e2915465342eebd18bf6430570e03a125cb710b Mon Sep 17 00:00:00 2001 From: cgbautista Date: Wed, 10 Dec 2025 13:15:05 +0100 Subject: [PATCH 1/3] removed volume for glowroot.zip as this causes some issues for the docker container if restarted outside d2-docker kept the port and the startup script so the user can still upload the zip file to the container and allow the port to be listening --- src/d2_docker/commands/start.py | 6 +----- src/d2_docker/docker-compose.yml | 1 - src/d2_docker/glowroot.py | 4 ++-- src/d2_docker/utils.py | 7 ++----- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/d2_docker/commands/start.py b/src/d2_docker/commands/start.py index c59a5b8..bfa72b3 100644 --- a/src/d2_docker/commands/start.py +++ b/src/d2_docker/commands/start.py @@ -42,8 +42,6 @@ def setup(parser): parser.add_argument("--enable-postgres-queries-logging", action="store_true", help="Enable Postgres queries logging") - parser.add_argument("--glowroot", action="store_true", help="Enables glowroot in tomcat in latest version") - parser.add_argument("--glowroot-zip", metavar="FILE", help="ZIP file with glowroot binaries") parser.add_argument("--glowroot-port", metavar="PORT", help="Set glowroot port") @@ -117,9 +115,7 @@ def start(args): java_opts=args.java_opts, postgis_version=args.postgis_version, enable_postgres_queries_logging=args.enable_postgres_queries_logging, - glowroot=args.glowroot, - glowroot_zip=args.glowroot_zip, - glowroot_port=args.glowroot_port, + glowroot_port=args.glowroot_port ) if args.detach: diff --git a/src/d2_docker/docker-compose.yml b/src/d2_docker/docker-compose.yml index 1b8eda2..f0f8d22 100644 --- a/src/d2_docker/docker-compose.yml +++ b/src/d2_docker/docker-compose.yml @@ -5,7 +5,6 @@ services: - "com.eyeseetea.image-name=${DHIS2_DATA_IMAGE}" volumes: - home:/DHIS2_home - - ${GLOWROOT_ZIP}:/opt/glowroot.zip - ${DHIS_CONF}:/config/override/dhis2/dhis.conf - ${ROOT_PATH}/config:/config - data:/data diff --git a/src/d2_docker/glowroot.py b/src/d2_docker/glowroot.py index a5a542f..52b5766 100644 --- a/src/d2_docker/glowroot.py +++ b/src/d2_docker/glowroot.py @@ -42,6 +42,6 @@ def get_glowroot_zip(command, glowroot_zip, glowroot): return utils.get_absfile_for_docker_volume(glowroot_path) -def get_port_glowroot(glowroot_port, glowroot_zip, glowroot): +def get_port_glowroot(glowroot_port): port = glowroot_port if glowroot_port else GLOWROOT_DEFAULT_PORT - return "{}:{}".format(port, GLOWROOT_DEFAULT_PORT) if (glowroot_port or glowroot_zip or glowroot) else None + return "{}:{}".format(port, GLOWROOT_DEFAULT_PORT) if glowroot_port else None diff --git a/src/d2_docker/utils.py b/src/d2_docker/utils.py index bc2bf93..138c372 100644 --- a/src/d2_docker/utils.py +++ b/src/d2_docker/utils.py @@ -15,7 +15,7 @@ from typing import Optional import d2_docker -from d2_docker.glowroot import get_glowroot_zip, get_port_glowroot +from d2_docker.glowroot import get_port_glowroot from .image_name import ImageName PROJECT_NAME_PREFIX = "d2-docker" @@ -262,8 +262,6 @@ def run_docker_compose( tomcat_server=None, postgis_version=None, enable_postgres_queries_logging=False, - glowroot=None, - glowroot_zip=None, glowroot_port=None, **kwargs, ): @@ -301,8 +299,7 @@ def run_docker_compose( # Add ROOT_PATH from environment (required when run inside a docker) ("ROOT_PATH", ROOT_PATH), ("PSQL_ENABLE_QUERY_LOGS", "") if not enable_postgres_queries_logging else None, - ("GLOWROOT_PORT", get_port_glowroot(glowroot_port, glowroot_zip, glowroot)), - ("GLOWROOT_ZIP", get_glowroot_zip(args, glowroot_zip, glowroot)), + ("GLOWROOT_PORT", get_port_glowroot(glowroot_port)) ] env = dict((k, v) for (k, v) in [pair for pair in env_pairs if pair] if v is not None) From 767fa25f9e2999ae9fbeae954cb4959b17c3c4f2 Mon Sep 17 00:00:00 2001 From: cgbautista Date: Fri, 12 Dec 2025 14:18:36 +0100 Subject: [PATCH 2/3] Added default config.json for glowrooot --- src/d2_docker/config/dhis2-core-entrypoint.sh | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/d2_docker/config/dhis2-core-entrypoint.sh b/src/d2_docker/config/dhis2-core-entrypoint.sh index ffc3a3f..6756169 100755 --- a/src/d2_docker/config/dhis2-core-entrypoint.sh +++ b/src/d2_docker/config/dhis2-core-entrypoint.sh @@ -57,6 +57,33 @@ setup_glowroot() { fi if [ -d $GLOWROOT_DIR ] ; then echo '{ "web": { "bindAddress": "0.0.0.0", "port": "4000" }}' > $GLOWROOT_DIR/admin.json + echo '{"transactions":{"slowThresholdMillis":2000,"profilingIntervalMillis":1000,"captureThreadStats":true}, + "jvm":{"maskSystemProperties":["*password*","*token*","*access*","*secret*"],"maskMBeanAttributes":["*password*","*token*","*access*","*secret*"]}, + "uiDefaults":{"defaultTransactionType":"Web","defaultPercentiles":[50,95,99],"defaultGaugeNames":["java.lang:type=Memory:HeapMemoryUsage.used"]}, + "advanced":{"immediatePartialStoreThresholdSeconds":60,"maxTransactionAggregates":500,"maxQueryAggregates":500,"maxServiceCallAggregates":500, + "maxTraceEntriesPerTransaction":2000,"maxProfileSamplesPerTransaction":50000,"mbeanGaugeNotFoundDelaySeconds":60},"gauges":[{"mbeanObjectName":"java.lang:type=Memory", + "mbeanAttributes":[{"name":"HeapMemoryUsage.used"}]},{"mbeanObjectName":"java.lang:type=GarbageCollector,name=*","mbeanAttributes":[{"name":"CollectionCount","counter":true}, + {"name":"CollectionTime","counter":true}]},{"mbeanObjectName":"java.lang:type=MemoryPool,name=*","mbeanAttributes":[{"name":"Usage.used"}]}, + {"mbeanObjectName":"java.lang:type=OperatingSystem","mbeanAttributes":[{"name":"FreePhysicalMemorySize"},{"name":"ProcessCpuLoad"},{"name":"SystemCpuLoad"}]}], + "plugins":[{"properties":{"stackTraceThresholdMillis":1000},"id":"cassandra"},{"properties":{"stackTraceThresholdMillis":1000},"id":"elasticsearch"}, + {"properties":{"sessionUserAttribute":"","captureSessionAttributes":[],"captureRequestParameters":["*"],"maskRequestParameters":["*password*","*token*","*access*","*secret*"], + "captureRequestHeaders":[],"captureResponseHeaders":[],"traceErrorOn4xxResponseCode":false,"captureRequestRemoteAddr":false,"captureRequestRemoteHostname":false, + "captureRequestRemotePort":false,"captureRequestLocalAddr":false,"captureRequestLocalHostname":false,"captureRequestLocalPort":false,"captureRequestServerHostname":false, + "captureRequestServerPort":false},"id":"jakartaservlet"},{"properties":{"captureRequestHeaders":[],"maskRequestHeaders":["Authorization"],"captureRequestRemoteAddr":false, + "captureRequestRemoteHost":false,"captureResponseHeaders":[],"traceErrorOn4xxResponseCode":false},"id":"java-http-server"},{"properties":{"useAltTransactionNaming":false}, + "id":"jaxrs"},{"properties":{"captureBindParametersIncludes":[".*"],"captureBindParametersExcludes":[],"captureResultSetNavigate":true,"captureResultSetGet":false, + "captureConnectionPoolLeaks":false,"captureConnectionPoolLeakDetails":false,"captureGetConnection":true,"captureConnectionClose":false,"capturePreparedStatementCreation":false, + "captureStatementClose":false,"captureTransactionLifecycleTraceEntries":false,"captureConnectionLifecycleTraceEntries":false,"stackTraceThresholdMillis":1000},"id":"jdbc"}, + {"properties":{"traceErrorOnErrorWithThrowable":true,"traceErrorOnErrorWithoutThrowable":false,"traceErrorOnWarningWithThrowable":false,"traceErrorOnWarningWithoutThrowable":false}, + "id":"logger"},{"properties":{"stackTraceThresholdMillis":1000},"id":"mongodb"},{"properties":{"useAltTransactionNaming":false},"id":"play"},{"properties":{"sessionUserAttribute":"", + "captureSessionAttributes":[],"captureRequestParameters":["*"],"maskRequestParameters":["*password*","*token*","*access*","*secret*"],"captureRequestHeaders":[], + "captureResponseHeaders":[],"traceErrorOn4xxResponseCode":false,"captureRequestRemoteAddr":false,"captureRequestRemoteHostname":false,"captureRequestRemotePort":false, + "captureRequestLocalAddr":false,"captureRequestLocalHostname":false,"captureRequestLocalPort":false,"captureRequestServerHostname":false,"captureRequestServerPort":false}, + "id":"servlet"},{"properties":{"useAltTransactionNaming":false},"id":"spring"}],"instrumentation":[{"className":"org.hisp.dhis.webapi.controller.event.TrackedEntityInstanceController", + "methodName":"getTrackedEntityInstances","methodParameterTypes":[".."],"order":0,"captureKind":"other","transactionType":"Web","transactionNameTemplate":"/api/trackedEntityInstances: GET"}, + {"className":"org.hisp.dhis.tracker.report.DefaultTrackerImportService","methodName":"importTracker","methodParameterTypes":[".."],"order":0,"captureKind":"transaction", + "transactionType":"Web","transactionNameTemplate":"/api/tracker: import","alreadyInTransactionBehavior":"capture-new-transaction","traceEntryMessageTemplate":"{{0}}", + "traceEntryStackThresholdMillis":300,"traceEntryCaptureSelfNested":true,"timerName":"Timer"}]}' > $GLOWROOT_DIR/config.json chown -R tomcat:tomcat $GLOWROOT_DIR chmod -R u=rwX,g=rX,o-rwx $GLOWROOT_DIR echo 'export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/glowroot/glowroot.jar"' > /usr/local/tomcat/bin/setenv.sh From 7413dda3fb14d3fe0a1472f3ffad53c35c57134e Mon Sep 17 00:00:00 2001 From: cgbautista Date: Tue, 30 Dec 2025 09:53:00 +0100 Subject: [PATCH 3/3] Changed README.md to adapt documentation on how to enable glowroot. --- README.md | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d6cd1cd..99f1d52 100644 --- a/README.md +++ b/README.md @@ -383,14 +383,42 @@ $ curl -sS 'http://localhost:5000/harbor/https://docker.eyeseetea.com/api/v2.0/q ## Glowroot Glowroot is an open-source Java APM (Application Performance Monitoring) tool. It can help detect and diagnose application performance problems, tracing slow requests, errors, response time breakdowns, SQL capture and more. -When starting a container, there are two options to enable glowroot on the Tomcat process: -- Use option `--glowroot` to use the latest version of glowroot in the Tomcat process. This requires internet access to be able to retrieve the file. -- Use option `--glowroot-zip=FILE` to specify the zip file with the version of glowroot to run in the Tomcat process. This takes precedence over the other option. -When enabling glowroot, it will start listening on port 4000/tcp so you can connect via browser to its interface. You may override this port with: -- `--glowroot-port=PORT` to specify the APM glowroot port. +The startup script in the core container expects a `/opt/glowroot.zip` file; if it exists, it will decompress that file and enable a default configuration for glowroot in the tomcat process. +The only needed parameter to use glowroot is the `--glowroot-port`, as the metrics are exposes through its own http connection, so the port must be opened in the container. +To use glowroot: -### Run d2-docker with glowroot enabled in the default port at the latest version available +- start d2-docker with `--glowroot-port=` (default port for glowroot is 4000, but any available port can be used) +- download the latest version of glowroot to the host machine: ``` -$ d2-docker start docker.eyeseetea.com/eyeseetea/dhis2-data:2.37.9-sierra --glowroot +lastversion=$(wget -q -O - https://api.github.com/repos/glowroot/glowroot/releases/latest | jq '.tag_name' | sed 's_"__g') +wget -q https://github.com/glowroot/glowroot/releases/download/$lastversion/glowroot-${lastversion#v}-dist.zip ``` + +- determine the core instance name (note that as there might be several d2-docker instances running, you must pick the one you want manually from the list) + +``` +docker ps | awk '/core.1/ {print $NF}' +``` + +- copy the zip file to the core container with the filename `/opt/glowroot.zip`: + +``` +docker cp glowroot-0.14.4-dist.zip ${core_instance_name}:/opt/glowroot.zip +``` + +- restart the core container: + +``` +docker restart ${core_instance_name} +``` + +Glowroot is configured to store its data for several days, so the size of its folder should be limited to some extent. This size may be further reduced editing the configuration via WebUI, but might require a restart of the container. Configuration (and glowroot historical data) will be kept unless the `/opt/glowroot` folder is deleted from the container and restarted. + +To remove glowroot from a container you must: + +- connect to the core container (`docker exec -it ${core_instance_name} bash`) +- inside the core container, remove the `/opt/glowroot.zip` file +- inside the core container, remove the `/opt/glowroot` folder +- inside the core container, remove the `/usr/local/tomcat/bin/setenv.sh` file. (This is not extrictly necessary as the jar file will no longer exist and won't be able to start, but if it is not removed, some warnings/errors may be generated upon tomcat start) +- exit the core container and restart it (`docker restart ${core_instance_name}`)