Use logging.properties with standard Appengine Java 11 - java

I'm trying to do some Logging modification on My Standard AppEngine Java 11 app using a logging.properties file, My app is a Jetty web-server which I run by adding the following entry-point to my app.yaml file
runtime: java11
entrypoint: 'java -cp "*" com.jettymain.Main webapp.war'
Now Google documentation here suggests that in order to use logging.properties. The path to the configuration file must be provided to your application as a system property: -Djava.util.logging.config.file=/path/to/logging.properties
I have tried setting that in the code, first thing in the com.jettymain.Main class which starts the Jetty embedded web-server by doing the following
System.setProperty("java.util.logging.config.file", "WEB-INF/logging.properties")
But that didn't work, modifying the entry-point in app.yaml did make the web-server load those configurations but it was failing to load the Google cloud logging handler class com.google.cloud.logging.LoggingHandler, which I need to write those logs to Google Stackdriver, I have the Google cloud logging dependency added to both my app and the web-server but that didn't help.
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-logging</artifactId>
<version>3.0.1</version>
</dependency>
modified entry-pint
runtime: java11
entrypoint: 'java -cp "*" com.jettymain.Main webapp.war -Djava.util.logging.config.file=WEB-INF/logging.properties'
logging.properties file, it is the sample file which can be found here plus few extra things
# To use this configuration, add to system properties : -Djava.util.logging.config.file="/path/to/file"
.level = INFO
# it is recommended that io.grpc and sun.net logging level is kept at INFO level,
# as both these packages are used by Cloud internals and can result in verbose / initialization problems.
io.grpc.netty.level=INFO
sun.net.level=INFO
handlers=com.google.cloud.logging.LoggingHandler
# default : java.log
com.google.cloud.logging.LoggingHandler.log=custom_log
# default : INFO
com.google.cloud.logging.LoggingHandler.level=FINE
# default : ERROR
com.google.cloud.logging.LoggingHandler.flushLevel=EMERGENCY
# default : auto-detected, fallback "global"
com.google.cloud.logging.LoggingHandler.resourceType=container
# custom formatter
com.google.cloud.logging.LoggingHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%3$s: %5$s%6$s
# Level for all logs coming from GWT client (can't filter by specific classes on client)
com.google.gwt.logging.server.RemoteLoggingServiceUtil.level = WARNING
com.beoui.geocell.level=WARNING

It might be an old question, but this answer still might help to someone having same issue.
I've managed to add custom logging.properties using Gradle for Java 11 Standard Environment:
First of all, you have to add dependency to the Cloud logging as it's no longer provided by the environment:
dependencies {
runtimeOnly("com.google.cloud:google-cloud-logging:3.11.3")
// your other dependencies
}
Then you need to specify a folder containing your logging.properties file to be uploaded by Gradle com.google.cloud.tools.appengine plugin:
configure<AppEngineAppYamlExtension> {
stage {
setArtifact("build/libs/server.jar")
// can be some other folder of your choice where logging.properties is located
setExtraFilesDirectories("src/main/resources")
}
deploy {
version = "GCLOUD_CONFIG"
projectId = "GCLOUD_CONFIG"
}
}
Then specify an entrypoint in app.yaml. The trick here is that properties file can be found in /workspace/ directory of the GAE container:
runtime: java11
entrypoint: 'java -jar -Djava.util.logging.config.file=/workspace/logging.properties server.jar'
Deploy application using
./gradlew appengineDeploy
My logging.properties file:
.level = INFO
# it is recommended that io.grpc and sun.net logging level is kept at INFO level,
# as both these packages are used by Cloud internals and can result in verbose / initialization problems.
io.grpc.netty.level=INFO
sun.net.level=INFO
handlers=com.google.cloud.logging.LoggingHandler
com.google.cloud.logging.LoggingHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%3$s: %5$s%6$s

Get the System.setProperty into any method. It can be the main method also. I think the problem is "the logging.properties must go in WEB-INF/classes directory" as per this link and not WEB-INF/ directory as mentioned in your code.
System.setProperty("java.util.logging.config.file", "WEB-INF/classes/logging.properties")

Related

How can I export traces generated by the OpenTelemetry Java agent to Google Cloud Trace?

I've got a Spring Boot application that'd I'd like to automatically generate traces for using the OpenTelemetry Java agent, and subsequently upload those traces to Google Cloud Trace.
I've added the following code to the entry point of my application for sending traces:
OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(
SimpleSpanProcessor.create(TraceExporter.createWithDefaultConfiguration())
)
.build()
)
.buildAndRegisterGlobal();
...and I'm running my application with the following system properties:
-javaagent:path/to/opentelemetry-javaagent-all.jar \
-jar myapp.jar
...but I don't know how to connect the two.
Is there some agent configuration I can apply? Something like:
-Dotel.traces.exporter=google_cloud_trace
I ended up resolving this as follows:
Clone the GoogleCloudPlatform /
opentelemetry-operations-java repo
git clone
git#github.com:GoogleCloudPlatform/opentelemetry-operations-java.git
Build the exporter-auto project
./gradlew clean :exporter-auto:shadowJar
Copy the jar produced in exporter-auto/build/libs to my target project
Run the application with the following arguments:
-javaagent:path/to/opentelemetry-javaagent-all.jar
-Dotel.javaagent.experimental.extensions=[artifact-from-step-3].jar
-Dotel.traces.exporter=google_cloud_trace
-Dotel.metrics.exporter=none
-jar myapp.jar
Note: This setup does not require any explicit code changes in the target code base.

using tinylog to write loggings into tomcat's log-folder

I want to write logging-messages to a defined file into the tomcat's log-folder, using eclipse, maven, tinylog.
Problem: There is no webapp.log as soon as I run the app in tomcat.
In eclipse everything works fine.
What I did:
add Maven-dependency tinylog-1.2.jar
set configuration-parameter in Run Configuration (Main-Tab) so the tinylog-properties can be found for the build-process:
name: -Dtinylog.configuration
value: C:\Program
Files\Tomcat\apache-tomcat-9.0.0.M13\webapps\folder\subfolder\tinylog.properties
in Java-Class:
import org.pmw.tinylog.Logger;
...
Logger.info(message);
tinylog.properties looks like:
tinylog.writer = file
tinylog.writer.filename = webapp.log
tinylog.writer.buffered = true
tinylog.writer.append = true
tinylog.level = info
I also tried different file-references but none of them worked:
tinylog.writer.file = C:\Program Files\Tomcat\apache-tomcat-9.0.0.M13\logs\webapp.log
tinylog.writer.file= "C:\Program Files\Tomcat\apache-tomcat-9.0.0.M13\logs\webapp.log"
Does anybody know how to write the logs into the named path-file?
Thanks for any valuable hint.
I propose to use the tinylog-jul artifact instead of the usual tinylog artifact. tinylog-jul provides the tinylog API, but uses the Tomcat logging back end. So, you don't need to configure tinylog. All log entries will be automatically output as you are used to with other logging APIs on Tomcat.

How do I bundle a Custom C Shared Library with Java Application in Cloud Foundry?

I have previously been deploying a java application successfully in Cloud Foundry. However, now the developers have added a shared library compiled from C. I have added the .so to the .zip file (I'm using universal packager and deploying to Cloud Foundry by zip file) and ensured the .so is executable. However, when I deploy I get an error:
2016-12-23T14:39:01.013+00:00 [STG/0] [OUT] -----> Java Buildpack Version: eba4df6 | git://github.com/cloudfoundry/java-buildpack.git#eba4df6
2016-12-23T14:39:01.017+00:00 [STG/0] [ERR] [Buildpack] ERROR Compile failed with exception #<RuntimeError: No container can run this application. Please ensure that you’ve pushed a valid JVM artifact or artifacts using the -p command line argument or path manifest entry. Information about valid JVM artifacts can be found at https://github.com/cloudfoundry/java-buildpack#additional-documentation.
2016-12-23T14:39:01.017+00:00 [STG/0] [ERR] No container can run this application. Please ensure that you’ve pushed a valid JVM artifact or artifacts using the -p command line argument or path manifest entry. Information about valid JVM artifacts can be found at https://github.com/cloudfoundry/java-buildpack#additional-documentation.
2016-12-23T14:39:01.022+00:00 [STG/0] [ERR] Failed to compile droplet
2016-12-23T14:39:01.024+00:00 [STG/0] [OUT] Exit status 223
So my understanding is that I need to created a Custom Buildpack from the Java Buildpack. However, I am getting stuck with the code at this point:
https://github.com/ONSdigital/java-buildpack/blob/master/bin/compile#L28
# Adding crf tagger library
status "Adding crf tagger support"
cp $bp_dir/parsers/src/main/resources/libbackend.so $build_dir/vendor/
# update the PATH
status "Building runtime environment"
mkdir -p $build_dir/.profile.d
echo "export PATH=\"$HOME/bin:\$HOME/vendor/:\$PATH\";" > $build_dir/.profile.d/crftagger.sh
echo "export LD_LIBRARY_PATH=\"\$HOME/vendor/\";" >> $build_dir/.profile.d/crftagger.sh
From what I can gather I only need to modify the compile stage. What do I need to do to copy over the .so and have the Buildpack run successfully.
Please take a look to this https://docs.cloudfoundry.org/devguide/deploy-apps/deploy-app.html#profile
Pre-Runtime Hooks that's you need. I can't give you more details because you haven't provided enough information (project structure, do you have .profile in you root and etc.).
If you need to add shared libs try to use attr_reader :additional_libraries https://github.com/cloudfoundry/java-buildpack/blob/master/docs/extending-droplet.md

Play Framework deploy failed: "the application secret has not been set, and we are in prod mode. Your application is not secure"

I'm deploying on Heroku a web application developed with Play Framework.
The deploy fails returning this error:
[error] p.a.l.c.CryptoConfigParser - The application secret has not been set, and we are in prod mode. Your application is not secure.
What does it means that "we are in prod mode"? Where do I set the mode? I have to change this because it's not a production environment.
Thanks
Put this into your conf/application.conf
Play 2.5
play.crypto.secret="changethissosomethingsecret"
Play 2.6+
play.http.secret.key="changethissosomethingsecret"
You can also start your application with a source with a secret key as a parameter.
you need to add an application secret in your conf file.
play.http.secret.key="changethissosomethingsecret"
You need to set up different keys based on the Play version that your application is using.
What version of play are you using?
Either look at com.typesafe.play:sbt-plugin version inside your project's plugins.sbt or if you have a GNU compatible shell, execute the following command:
find . -name "plugins.sbt" -exec grep -PHin --color=always 'com.typesafe.play.*sbt-plugin.*%\s*"\K.*?(?=")' {} \;
Proceed to the next step, once you know the version number of play used by your app.
What is the key to use in application.conf based on play version?
Play 2.3.x: application.secret (defaults to changeme)
Play 2.4.x: play.crypto.secret (defaults to changeme)
Play 2.5.x: play.crypto.secret (defaults to changeme)
Play 2.6.x: play.http.secret.key (defaults to changeme)
As you can see it is not consistent, but what is consistent is:
In the above versions you can override the secret using APPLICATION_SECRET environment variable/property (so, something like APPLICAITION_SECRET="changed" sbt "runProd 9001")
The default value in each case is changeme
The next two options were tested on Play v2.6.x, but according to the documentation, should work with the same commands for v2.4.x and v2.5.x.
The only exception is v2.3.x which uses play-generate-secret and play-update-secret respectively
How do I get sbt to generate a key for me?
Run the following command from within the directory of your play application (tested with sbt v1.1.6 and play v2.6.x):
$ sbt playGenerateSecret | grep -i 'generated'
[info] Generated new secret: ^7UubY[rFXzkN:v6TB9WL/lfGsP61/vzAHA9tdZNZ#nALH=TEztKAlTC>xz;VUXw
You can manually copy the above as the value for the key (based on play framework version as noted before) OR, you can use the suggestion below.
How do I get sbt to update existing key in application.conf automatically?
Same as above, run the following command from the root directory of your play framework app:
$ sbt playUpdateSecret | grep -i "secret"
[info] Generated new secret: Kz?fHm_I[wt^Onp[#cr<:`ttrQi]KMsdDs>22hEF?RhkoanQ7gA6NAjL33EV2^Xt
[info] Updating application secret in /Users/blah/someplayapp/conf/application.conf
[warn] Did not find application secret in /Users/blah/someplayapp/conf/application.conf
[warn] Adding application secret to start of file
Couple of things to note about this command:
playUpdateSecret will update the existing secret or add a secret to application.conf if it is not present.
This commands looks for the key and/or adds/updates it in application.conf only. This is important if you are following the Best Practice.
This best practice refers to creating a separate production.conf that overrides this key from application.conf:
include "application"
play.http.secret.key="somesecretkey"
and then run your app like so:
/path/to/yourapp/bin/yourapp -Dconfig.file=/path/to/production.conf
As you can see, if you are using playUpdateSecret to generate a new secret then it is going to have no effect since it is being overridden by the secret specified in production.conf.
Before you run your application in production mode, you need to generate an application secret
You need generate token for application in production mode, using activator playGenerateSecret
Configuration Application Secret
Link documentation

Application specific log in tomcat 7 using JULI?

I'm using java system logging in tomcat 7, but no logging statements get written to the log. I've added this file to my WEB-INF/classes. The log file "new-xyz-test" gets created (so I have at least some of the config right) but its empty - no log statements get printed to it.
handlers=java.util.logging.ConsoleHandler, org.apache.juli.FileHandler
org.apache.juli.FileHandler.level=ALL
org.apache.juli.FileHandler.directory=${catalina.base}/logs
org.apache.juli.FileHandler.prefix=new-xyz-test-
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
com.xyz.level=ALL
com.xyz.handlers=org.apache.juli.FileHandler
To configure JULI in the web applications you need have a logging.properties file in the WEB-INF/classes directory. If you use the default handlers, you may lose messages. You need to specify a prefix for the handler in your file.
handlers=1FILE.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
.handlers=java.util.logging.ConsoleHandler
1FILE.org.apache.juli.FileHandler.level=FINEST
1FILE.org.apache.juli.FileHandler.directory=/app-logs
1FILE.org.apache.juli.FileHandler.prefix=file-1
java.util.logging.ConsoleHandler.level=FINE
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
com.xyz.level=INFO
com.xyz.handlers=1FILE.org.apache.juli.FileHandler
com.abc.level=INFO
com.abc.handlers=java.util.logging.ConsoleHandler
A
handler prefix (e.g. 1FILE.) starts with a number, then has an arbitrary string, and ends with a period (.).
See more in Logging in Tomcat
Arguments in the JVM
If you are not running the Tomcat from the startup.sh or startup.bat, you need to specify:
The location of the general logging.properties for Tomcat (in the conf directory of Tomcat)
The manager org.apache.juli.ClassLoaderLogManager. This is important because allows you to configure
for each web application different loggin options. By default, a JVM process can only have a single configuration file.) ,
Similar to the next (I'm using eclipse):
-Djava.util.logging.config.file="C:\Users\Paul\workspaces\utils\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\conf\logging.properties" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
By default, java.util.logging read the file that is included in the JDK or JRE, e.g.:
"C:\Software\jdk1.7.0_17\jre\lib\logging.properties"
Setting Tomcat Heap Size (JVM Heap) in Eclipse, for how to add arguments in the VM
are you sure that you write to the correct logger , i.e. Logger.getLogger("com.xyz")?
I think that you may got wrong when you wrote in logging.properties:com.xyz.level=ALL com.xyz.handlers=org.apache.juli.FileHandler in the case that you actually write to the logger Logger.getLogger(com.xyz.YourClass.class), that because in the logging properties file you should write the logger name which is in your case com.xyz.YourClass

Categories