Skip to content
JeffersonLabPublic

About

EPICS CA Web Gateway

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

18 stars

Watchers

6 watching

Forks

Repository files navigation

epics2web Java CI with Gradle Docker

A gateway server and accompanying JavaScript client API to monitor EPICS Channel Access over the web.

MonitorTest



Overview

The epics2web application allows users to monitor EPICS PVs from the web using Web Sockets and a REST web service endpoint. The application leverages the Java JCA library and is designed to run on Apache Tomcat.

Quick Start with Compose

  1. Grab project
git clone https://github.com/JeffersonLab/epics2web
cd epics2web
  1. Launch Compose
docker compose up
  1. Monitor test PV via web browser

http://localhost:8080/epics2web/test-camonitor

PV name: HELLO

See: Docker Compose Strategy

Install

  1. Download Java 21
  2. Download Apache Tomcat 11
  3. Download epics2web.war and drop it into the Tomcat webapps directory
  4. Start Tomcat and navigate your web browser to localhost:8080/epics2web

Note: epics2web also works and was tested with GlassFish, and presumably works with WildFly or any other Java web application server that supports Web Sockets.

Note: The dependency jars are included in the war file that is generated by the build. You can copy the dependency jar files downloaded by Gradle to the Tomcat lib directory and change the build.gradle script to use providedCompile instead of implementation if you'd prefer to include the dependencies that way.

API

API Reference

Configure

This application uses the Java Channel Access library. It requires a working EPICS channel access environment with the environment variable EPICS_CA_ADDR_LIST set. See Also: Advanced Configuration.

Context Prefix

When proxying epics2web it is sometimes useful to have multiple instances accessible via the same host via separate context paths. In order to return correct links to resources an instance proxied with a namespacing prefix needs to be aware of the prefix. The environment variable CONTEXT_PREFIX does this. For example at Jefferson Lab we use a single proxy server for multiple departments each with their own instance of epics2web, and each configured with a prefix such as "/fel", "/chl", "/itf", and "/srf" ("/ops" uses default/empty prefix).

WebSocket Ping

The server sends each WebSocket client a ping every WEBSOCKET_PING_INTERVAL_SECONDS (default 30), and closes any session that has sent no message or pong for WEBSOCKET_TIMEOUT_SECONDS (default 60). Browsers answer pings automatically, so this closes sessions whose clients have gone away without closing them. The timeout should be longer than the ping interval.

A client that stops reading makes writes to it block once the network buffers fill. When a write blocks for WEBSOCKET_SEND_TIMEOUT_SECONDS (default 20, Tomcat's own default), Tomcat closes the session. This setting applies only on Tomcat.

Healthcheck

/healthcheck returns a JSON array of monitored PVs that haven't been connected for longer than HEALTHCHECK_GRACE_SECONDS (default 30), counted from when they disconnected, or from when monitoring began for a PV that never connected. Each entry has the PV's name, its state (DISCONNECTED, or CONNECTING if it never connected), and disconnected_minutes.

By default the response is 200 whenever the server is up, which suits load balancers: an IOC being down affects every instance alike. With ?strict=true the response is 503 when a PV that was connected has disconnected, which suits monitoring that should alert on that, such as Nagios. PVs that never connected are listed but don't fail strict mode, since they may simply not exist.

Frozen PVs

A PV is frozen when its monitor has stopped working while the IOC still serves it, so restarting epics2web would be expected to fix it. epics2web looks for them every FROZEN_CHECK_SECONDS (default 10) by giving suspicious PVs a short-lived subscription in a second, independent CA context with its own connections: PVs disconnected for longer than the grace period, and PVs that used to update but have been quiet for 6 check intervals. A PV is frozen if its monitor stays disconnected while the independent subscription connects, or if the independent subscription receives a change the monitor doesn't. An IOC that's down doesn't make its PVs frozen. Through a gateway, both contexts reach the PV through the gateway, so this finds problems between epics2web and the gateway, not inside it.

Frozen PVs are logged as warnings and listed by /healthcheck with frozen, frozen_minutes and frozen_reason. They don't change the default or strict response; with ?frozen=true the response is 503 when a PV is frozen, for automation that restarts epics2web. FROZEN_PV_CHECK=false turns detection off.

Disconnected PVs report

/disconnected-pvs, linked from the overview page, is a report for people, such as IOC maintainers, of the PVs /healthcheck lists. It shows each PV with the clients that monitor it, and groups the PVs by client and by IOC. Clients name themselves with the clientName parameter, and the JavaScript client sends its page's address by default, so a WEDM screen is shown by its EDL file and linked to the screen. Via is the server epics2web last reached the PV through: a CA gateway, if there is one, since CA can no longer say once the PV is disconnected.

The IOC comes from the MYA archiver through myquery's channel search, so it's missing for PVs that aren't archived. The browser makes the requests, to MYQUERY_URL (default /myquery, myquery on the same host), in the MYA deployment MYQUERY_DEPLOYMENT (default ops). A myquery on another host must allow the report's origin (CORS). An empty MYQUERY_URL turns the lookup off.

Logging

This app is designed to run on Tomcat so Tomcat logging configuration applies. We use the built-in JVM logging library, which Tomcat uses with some slight modifications to support separate classloaders. In the past we bundled an application logging.properites inside the epics2web.war file. We no longer do that because it then appears to require repackaging/rebuilding a new version of the app to modify the logging config as the app bundled config overrides the global Tomcat config at conf/logging.properties. The recommend logging strategy is to now make configuration in the global Tomcat config so as to make it easy to modify logging levels. An app specific handler can be created. The global configuration location is generally set by the Tomcat default start script via JVM system properties. The system properties should look something like:

  • -Djava.util.logging.config.file=/usr/share/tomcat/conf/logging.properties
  • -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

The contents of the logging.properties should be modfied to look something like:

handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, 5epics2web.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

5epics2web.org.apache.juli.FileHandler.level = FINEST
5epics2web.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
5epics2web.org.apache.juli.FileHandler.prefix = epics2web.

org.jlab.epics2web.handlers = 5epics2web.org.apache.juli.FileHandler
org.jlab.epics2web.level = ALL

Note: This example is for older versions of Tomcat as newer version use an AsyncFileHandler. Refer to your logging configuration guide for your version of Tomcat.

Build

This project is built with Java 21 (compiled to Java 21 bytecode), and uses the Gradle 9 build tool to automatically download dependencies and build the project from source:

git clone https://github.com/JeffersonLab/epics2web
cd epics2web
gradlew build

Note: If you do not already have Gradle installed, it will be installed automatically by the wrapper script included in the source

Note for JLab On-Site Users: Jefferson Lab has an intercepting proxy

See: Docker Development Quick Reference

Test

Unit tests run with gradlew build. Integration tests need the test IOC and epics2web containers, which build.yaml configures with short ping, timeout and send timeout settings so the ping and stalled client tests run in seconds:

docker compose -f build.yaml up --wait

Then:

gradlew integrationTest

Note: Outside JLab, build the image without the JLab CA certificate first: docker compose -f build.yaml build --build-arg CUSTOM_CRT_URL=

CI runs both on every pull request.

Release

  1. Bump the version number in the VERSION file and commit and push to GitHub (using Semantic Versioning).
  2. The CD GitHub Action should run automatically invoking:
    • The Create release GitHub Action to tag the source and create release notes summarizing any pull requests. Edit the release notes to add any missing details. A war file artifact is attached to the release.
    • The Publish docker image GitHub Action to create a new demo Docker image.

Deploy

At JLab this app is found at epicsweb.jlab.org/epics2web, plus other fiefdom specific subpaths, and internally at epicswebtest.acc.jlab.org/epics2web. However, the epicsweb server is a proxy for department/fiefdom backend servers, with the primary ops fiefdom load balanced with httpd. The ops fiefdom uses backends: epicswebops9.acc.jlab.org and epicswebops99.acc.jlab.org. The test backends are epicswebopstest9 and epicswebopstest99. The other fiefdoms don't have test backends, but production ones are: epicswebchl9.acc.jlab.org, epicsweblerf9.acc.jlab.org, epicswebsrf9.acc.jlab.org and epicswebuitf9.acc.jlab.org. Additionally, the context root for each is adjusted with a prefix such that all servers can be reached from a single namespace. The context root prefixes are /, /ops2, /chl, /fel, /srf, and /itf respectively. Tomcat interprets context roots from war file name unless overridden elsewhere. Therefore each war must be prefixed with <prefix>#. Use wget or the like to grab the release war file. Don't download directly into webapps dir as file scanner may attempt to deploy before fully downloaded. Be careful of previous war file as by default wget won't overrwite. The war file should be attached to each release, so right click it and copy location (or just update version in path provided in the example below).

A script is provided to automate the deployment. As root run:

cd /root/setup
./deploy.sh epics2web {version}

Or manually execute (CHL fiefdom shown):

cd /tmp
rm epics2web.war
wget https://github.com/JeffersonLab/wmenu/releases/download/v1.2.3/epics2web.war
mv epics2web.war chl#epics2web.war
mv  chl#epics2web.war /opt/tomcat/current/webapps

See Also

About

EPICS CA Web Gateway

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

18 stars

Watchers

6 watching

Forks

Releases

Used by

Contributors

Languages