diff --git a/Dockerfile b/Dockerfile
index 5ca26703e..2c6a71c8a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,11 +30,27 @@ RUN mkdir /download && \
tar xzf apache-tomcat-*tar.gz && \
mv apache-tomcat-9.0.112 /usr/local/tomcat/ && \
cd / && \
- rm -rf /download && \
rm -rf /usr/local/tomcat/webapps/* && \
mkdir /usr/local/tomcat/webapps/ROOT && \
printf "<%% response.sendRedirect(\"/cwms-data/\"); %%>\n" > /usr/local/tomcat/webapps/ROOT/index.jsp && \
- printf "User-agent: *\nAllow: /cwms-data/\nDisallow: /cwms-data/auth/\nDisallow: /cwms-data/catalog/\nDisallow: /cwms-data/timeseries/\nDisallow: /cwms-data/swagger-docs\nDisallow: /auth/\nSitemap: https://cwms-data.usace.army.mil/sitemap.xml\n" > /usr/local/tomcat/webapps/ROOT/robots.txt
+ printf "User-agent: *\nAllow: /cwms-data/\nDisallow: /cwms-data/auth/\nDisallow: /cwms-data/catalog/\nDisallow: /cwms-data/timeseries/\nDisallow: /cwms-data/swagger-docs\nDisallow: /auth/\nSitemap: https://cwms-data.usace.army.mil/sitemap.xml\n" > /usr/local/tomcat/webapps/ROOT/robots.txt && \
+ mkdir -p /usr/local/tomcat/conf/Catalina/localhost
+# Now replace the Tomcat logging with logback
+# NOTE: I have reviewed this jar in jd-gui and do not see anything malicious, packages are isolated to avoid issues
+# with other code.
+# Additionally, when we are not also accounting for some legacy systems, we will likely shift to
+# Jetty, or Embedded Tomcat, to simplify the deployment process, making this subtitution unnecessary.
+RUN cd /download && \
+ wget https://repo1.maven.org/maven2/com/github/tomcat-slf4j-logback/tomcat9-slf4j-logback/9.0.115/tomcat9-slf4j-logback-9.0.115.jar && \
+ echo "cb463fb246fbb326d91b04a7280474f2b722b11cc9d3d7f6c3dbbefcff2c07e055f479d436ab785668d6fa90d0bfd325c86c4fa3a9ad9521159a2a3114916d91 *tomcat9-slf4j-logback-9.0.115.jar" > checksum.logback.txt && \
+ sha512sum -c checksum.logback.txt
+RUN cd /download && \
+ cp tomcat9-slf4j-logback-9.0.115.jar /usr/local/tomcat/bin/tomcat-juli.jar && \
+ rm /usr/local/tomcat/conf/logging.properties && \
+ rm -rf /download
+
+
+
CMD ["/usr/local/tomcat/bin/catalina.sh","run"]
FROM tomcat_base AS api
@@ -45,6 +61,9 @@ COPY --from=builder /builddir/cwms-data-api/build/docker/context.xml /usr/local/
COPY --from=builder /builddir/cwms-data-api/build/docker/server.xml /usr/local/tomcat/conf
COPY --from=builder /builddir/cwms-data-api/build/docker/setenv.sh /usr/local/tomcat/bin
COPY --from=builder /builddir/cwms-data-api/build/docker/libs/ /usr/local/tomcat/lib
+COPY --from=builder /builddir/cwms-data-api/build/docker/logback.xml /logback.xml
+COPY --from=builder /builddir/cwms-data-api/build/docker/logback-juli.xml /logback-juli.xml
+COPY --from=builder /builddir/cwms-data-api/build/docker/app-context.xml /usr/local/tomcat/conf/Catalina/localhost/cwms-data.xml
ENV CDA_JDBC_DRIVER="oracle.jdbc.driver.OracleDriver"
ENV CDA_JDBC_URL=""
diff --git a/cda-gui/package-lock.json b/cda-gui/package-lock.json
index 8f53de641..79b131866 100644
--- a/cda-gui/package-lock.json
+++ b/cda-gui/package-lock.json
@@ -102,6 +102,7 @@
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
@@ -1524,6 +1525,7 @@
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.64.1.tgz",
"integrity": "sha512-vW5ggHpIO2Yjj44b4sB+Fd3cdnlMJppXRBJkEHvld6FXh3j5dwWJoQo7mGtKI2RbSFyiyu/PhGAy0+Vv5ev9Eg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@tanstack/query-core": "5.64.1"
},
@@ -1677,6 +1679,7 @@
"resolved": "https://registry.npmjs.org/@usace/groundwork/-/groundwork-3.14.18.tgz",
"integrity": "sha512-wGMhnLvCPO8G4JTyW3EIPNeK4M9AWN6tyht46Fw0CNPpSpO5Fxy8cMfW5UtBS0VXxl6qPAcJdg7EnxY1/heSag==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@headlessui/react": "^2.2.0",
"@tailwindcss/forms": "^0.5.9",
@@ -1718,6 +1721,7 @@
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2064,6 +2068,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -2745,6 +2750,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -4880,6 +4886,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -5120,6 +5127,7 @@
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -5131,6 +5139,7 @@
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
@@ -5225,7 +5234,8 @@
"version": "28.1.0",
"resolved": "https://registry.npmjs.org/redux-bundler/-/redux-bundler-28.1.0.tgz",
"integrity": "sha512-dbq0J0Sm0ctK9ZUh73JR/6J937qzNvkKEHXtHv7p2Hl/9sS+xyRQReWjuju8LHopYFiG+U0Lg9XZM1hPp1WkHg==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/redux-bundler-hook": {
"version": "1.0.3",
@@ -5872,6 +5882,7 @@
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
"integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
+ "peer": true,
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@@ -5986,6 +5997,7 @@
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -6191,6 +6203,7 @@
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -6284,6 +6297,7 @@
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
diff --git a/cwms-data-api/build.gradle b/cwms-data-api/build.gradle
index ac38b5518..68bc7e84b 100644
--- a/cwms-data-api/build.gradle
+++ b/cwms-data-api/build.gradle
@@ -29,6 +29,7 @@ configurations.all {
exclude group: 'org.apache.xmlbeans'
exclude group: 'org.apache.poi'
exclude group: 'org.bouncycastle'
+ exclude group: 'org.apache.tomcat', module: 'tomcat-juli'
}
dependencies {
@@ -37,7 +38,7 @@ dependencies {
implementation(libs.jaxb.api)
implementation(libs.jaxb.core)
implementation(libs.jaxb.impl)
- implementation(libs.cwms.db.jooq.codegen) {
+ implementation(libs.cwms.db.jooq.codegen) {
exclude group: "com.oracle", module: "*"
exclude group: "com.oracle.database.jdbc", module: "*"
exclude group: "org.jooq.pro", module: "*"
@@ -64,7 +65,7 @@ dependencies {
}
implementation(files("$buildDir/libs/${project.name}-${project.version}-codegen-shadow.jar"))
- implementation(libs.slf4j)
+ compileOnly(libs.slf4j)
implementation(libs.monolith) {
//exclude group: "org.python", module: "jython-standalone"
@@ -75,14 +76,15 @@ dependencies {
implementation(libs.google.flogger.api)
implementation(libs.google.findbugs)
implementation(libs.google.errorProne)
- runtimeOnly(libs.google.flogger.backend)
+ implementation(project(":flogger-cda-context"))
+ runtimeOnly(libs.google.flogger.system.backend)
implementation(libs.nucleus.data) {
exclude group: "org.jdom"
}
implementation(libs.nucleus.metadata)
implementation(libs.cwms.ratings.core) {
-
+
//exclude group: "mil.army.usace.hec.swingx"
exclude group: "*"
}
@@ -153,8 +155,16 @@ dependencies {
tomcatLibs(libs.bundles.tomcat.embedded)
tomcatLibs(libs.bundles.tomcat.support)
+
+ implementation(libs.slf4j)
+ testImplementation(libs.slf4j.jul)
tomcatLibs(libs.google.flogger.api)
- tomcatLibs(libs.google.flogger.backend)
+ tomcatLibs(libs.google.flogger.system.backend)
+ baseLibs(libs.google.flogger.slf4j.backend) {
+ exclude group: "org.slf4j"
+ }
+
+ baseLibs(libs.ch.qos.logback)
testImplementation(libs.bundles.testcontainers)
@@ -162,8 +172,6 @@ dependencies {
testImplementation(libs.cwms.tomcat.auth)
testImplementation(libs.apache.freemarker)
- testRuntimeOnly("org.slf4j:slf4j-jdk14:2.0.16")
-
webjars(project(":cda-gui"))
@@ -256,6 +264,7 @@ task run(type: JavaExec) {
args "$buildDir/tomcat", "$buildDir/libs/${project.name}-${project.version}.war", context
jvmArgs += "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties"
+ jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback.xml"
jvmArgs += "-DTOMCAT_RESOURCES=$buildDir/tomcat/conf/context.xml"
jvmArgs += "-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource"
jvmArgs += "-Dcatalina.base=$buildDir/tomcat"
@@ -285,6 +294,7 @@ task integrationTests(type: Test) {
jvmArgs += "-DwarContext=/cwms-data"
jvmArgs += "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties"
+ jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback.xml"
jvmArgs += "-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource"
jvmArgs += "-Dcwms.dataapi.access.provider=MultipleAccessManager"
jvmArgs += "-Dcwms.dataapi.access.providers=KeyAccessManager,CwmsAccessManager"
@@ -302,6 +312,7 @@ task prepareDockerBuild(type: Copy, dependsOn: war) {
from(configurations.baseLibs) {
into "libs"
+ //exclude "**/logback*"
}
from(sourceSets.test.resources) {
diff --git a/cwms-data-api/logback.xml b/cwms-data-api/logback.xml
new file mode 100644
index 000000000..2a5e724e7
--- /dev/null
+++ b/cwms-data-api/logback.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ CWMS-Data-API
+
+
+ System.err
+
+
+
+
+ false
+ true
+ build/cda.jsonl
+
+
+
+
+
+ %d [%thread] %-5level - %X{traceId:-none} - %logger - %msg %ex %n
+
+ false
+ true
+ build/cda-plain.log
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cwms-data-api/src/docker/app-context.xml b/cwms-data-api/src/docker/app-context.xml
new file mode 100644
index 000000000..79c880dbc
--- /dev/null
+++ b/cwms-data-api/src/docker/app-context.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/cwms-data-api/src/docker/logback-juli.xml b/cwms-data-api/src/docker/logback-juli.xml
new file mode 100644
index 000000000..813d4a25c
--- /dev/null
+++ b/cwms-data-api/src/docker/logback-juli.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+ CWMS-Data-API
+
+
+ System.err
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cwms-data-api/src/docker/logback.xml b/cwms-data-api/src/docker/logback.xml
new file mode 100644
index 000000000..6578bb5e4
--- /dev/null
+++ b/cwms-data-api/src/docker/logback.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+ CWMS-Data-API
+
+
+ System.err
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cwms-data-api/src/docker/setenv.sh b/cwms-data-api/src/docker/setenv.sh
index 62aa549f5..62e747ae1 100755
--- a/cwms-data-api/src/docker/setenv.sh
+++ b/cwms-data-api/src/docker/setenv.sh
@@ -1 +1,5 @@
-export CATALINA_OPTS="$CATALINA_OPTS -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource"
+CATALINA_OPTS="$CATALINA_OPTS -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource"
+CATALINA_OPTS="$CATALINA_OPTS -Djuli-logback.configurationFile=/logback-juli.xml -Djuli-logback.ContextSelector=JNDI"
+CATALINA_OPTS="$CATALINA_OPTS -Dlogback.configurationFile=/logback.xml -Dlogback.ContextSelector=JNDI"
+
+export CATALINA_OPTS
\ No newline at end of file
diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java
index 8695b6cd5..a27fb26a8 100644
--- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java
+++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java
@@ -39,6 +39,7 @@
import static io.javalin.apibuilder.ApiBuilder.prefixPath;
import static io.javalin.apibuilder.ApiBuilder.staticInstance;
import static java.lang.String.format;
+import static cwms.cda.logging.TraceIdFilter.HEADER_TRACE_ID;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
@@ -355,7 +356,8 @@ public void init() {
ctx.header("X-XSS-Protection", "1; mode=block");
})
.exception(ApplicationException.class, (e, ctx) -> {
- CdaError re = new CdaError(e.getCdaErrorMessage(), e.getSource(), e.getDetails());
+ final String incidentId = ctx.attribute(HEADER_TRACE_ID);
+ CdaError re = new CdaError(e.getCdaErrorMessage(), e.getSource(), e.getDetails(), incidentId);
if (e.getLoggerLevel().isPresent()) {
logger.at(e.getLoggerLevel().get()).withCause(e).log(re.toString());
}
@@ -368,18 +370,21 @@ public void init() {
ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(re);
})
.exception(BadRequestResponse.class, (e, ctx) -> {
+ final String incidentId = ctx.attribute(HEADER_TRACE_ID);
CdaError re = new CdaError("Bad Request",
- "User Input", new HashMap<>(e.getDetails()));
+ "User Input", new HashMap<>(e.getDetails()), incidentId);
logger.atInfo().withCause(e).log(re.toString());
ctx.status(e.getStatus()).json(re);
})
.exception(IllegalArgumentException.class, (e, ctx) -> {
- CdaError re = new CdaError("Bad Request");
+ final String incidentId = ctx.attribute(HEADER_TRACE_ID);
+ CdaError re = new CdaError("Bad Request", incidentId);
logger.atInfo().withCause(e).log(re.toString());
ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re);
})
.exception(DateTimeException.class, (e, ctx) -> {
- CdaError re = new CdaError(e.getMessage());
+ final String incidentId = ctx.attribute(HEADER_TRACE_ID);
+ CdaError re = new CdaError(e.getMessage(), incidentId);
ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re);
})
.exception(DataAccessException.class, (e, ctx) -> {
@@ -393,7 +398,8 @@ public void init() {
// CdaError does not include the Oracle exception message b/c this block catches
// all unhandled DataAccessExceptions and we don't know what is in the message
// it is unknown if the message would be safe/appropriate for users to see.
- CdaError errResponse = new CdaError("Database Error");
+ final String incidentId = ctx.attribute(HEADER_TRACE_ID);
+ CdaError errResponse = new CdaError("Database Error", incidentId);
logger.atWarning().withCause(e).log("error on request[%s]: %s",
errResponse.getIncidentIdentifier(), ctx.req.getRequestURI());
ctx.status(500);
@@ -401,7 +407,8 @@ public void init() {
ctx.json(errResponse);
})
.exception(Exception.class, (e, ctx) -> {
- CdaError errResponse = new CdaError("System Error");
+ final String incidentId = ctx.attribute(HEADER_TRACE_ID);
+ CdaError errResponse = new CdaError("System Error", incidentId);
logger.atWarning().withCause(e).log("error on request[%s]: %s",
errResponse.getIncidentIdentifier(), ctx.req.getRequestURI());
ctx.status(500);
diff --git a/cwms-data-api/src/main/java/cwms/cda/api/errors/CdaError.java b/cwms-data-api/src/main/java/cwms/cda/api/errors/CdaError.java
index 22d24c535..d364a2661 100644
--- a/cwms-data-api/src/main/java/cwms/cda/api/errors/CdaError.java
+++ b/cwms-data-api/src/main/java/cwms/cda/api/errors/CdaError.java
@@ -51,10 +51,11 @@ public String getSource() {
* @param message the error message
*/
public CdaError(String message) {
- this.incidentIdentifier = UUID.randomUUID().toString();
- this.message = message;
- this.details = Collections.unmodifiableMap(new HashMap<>());
- this.source = UNKNOWN_SOURCE;
+ this(message, (String)null);
+ }
+
+ public CdaError(String message, String incidentIdentifier) {
+ this(message, UNKNOWN_SOURCE, Collections.unmodifiableMap(new HashMap<>()), incidentIdentifier, false);
}
/**
@@ -63,11 +64,8 @@ public CdaError(String message) {
* @param map additional details about the error
*/
public CdaError(String message, Map map) {
- Objects.requireNonNull(map);
- this.incidentIdentifier = UUID.randomUUID().toString();
- this.message = message;
- this.details = Collections.unmodifiableMap(map);
- this.source = UNKNOWN_SOURCE;
+
+ this(message, map, false);
}
/**
@@ -78,14 +76,7 @@ public CdaError(String message, Map map) {
*/
public CdaError(String message, Map details,
boolean suppressIncidentId) {
- if (suppressIncidentId) {
- this.incidentIdentifier = "user input error";
- } else {
- this.incidentIdentifier = UUID.randomUUID().toString();
- }
- this.message = message;
- this.details = Collections.unmodifiableMap(details);
- this.source = UNKNOWN_SOURCE;
+ this(message, UNKNOWN_SOURCE, details, null, suppressIncidentId);
}
/**
@@ -98,16 +89,37 @@ public CdaError(String message, boolean suppressIncidentId) {
}
/**
- * Full constructor.
* @param message the error message
* @param source the source of the error
* @param details additional details about the error
*/
public CdaError(String message, String source, Map details) {
- this.incidentIdentifier = UUID.randomUUID().toString();
+ this(message, source, details, null, false);
+ }
+
+ /**
+ * @param message the error message
+ * @param source the source of the error
+ * @param details additional details about the error
+ */
+ public CdaError(String message, String source, Map details,
+ String incidentIdentifier) {
+ this(message, source, details, incidentIdentifier, false);
+ }
+
+ /**
+ * Full constructor.
+ * @param message the error message
+ * @param source the source of the error
+ * @param details additional details about the error
+ */
+ public CdaError(String message, String source, Map details,
+ String incidentIdentifier, boolean suppressIncidentIdentfier) {
+ this.details = Collections.unmodifiableMap(Objects.requireNonNull(details));
+ this.incidentIdentifier = suppressIncidentIdentfier ? "user input error" :
+ (incidentIdentifier != null ? incidentIdentifier : UUID.randomUUID().toString());
this.message = message;
this.source = source;
- this.details = Collections.unmodifiableMap(details);
}
@Override
diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingMetadataDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingMetadataDao.java
index fe4a62236..72d798b5e 100644
--- a/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingMetadataDao.java
+++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/RatingMetadataDao.java
@@ -63,6 +63,8 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.google.common.flogger.FluentLogger;
+import com.google.common.flogger.context.ScopedLoggingContexts;
+
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -190,9 +192,12 @@ public Map> getRatingsForIds(
boolean useParallel = true;
Stream