Use open telemetry in Spring boot without injecting the jar and using jvm args - spring-boot

I am testing opentelemetry in Spring boot and trying out if it is doable without injecting the jar file to the app and using jvm arguments, so far I tried using the following dependency in my gradle app:
runtimeOnly 'io.opentelemetry.javaagent:opentelemetry-javaagent:1.19.1'
and placed the the following properties in my application.properties file
otel.service.name=your-service-name
otel.traces.exporter=zipkin
but it's not working and traces are not showing in the console logs.

The OpenTelemetry javaagent is not able to extract configuration from the Spring config file; it happens way too late after the agent initialization.
You'll need to pass these settings either as system properties, e.g.:
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=your-service-name \
-Dotel.traces.exporter=zipkin \
-jar my-app.jar
or as environment variables:
export OTEL_SERVICE_NAME=your-service-name
export OTEL_TRACES_EXPORTER=zipkin
java -javaagent:opentelemetry-javaagent.jar -jar my-app.jar

Related

Maven install command with environment variables file

Is there any way to execute the environment variables file .env along with maven commands such as mvn clean install or mvn clean deploy. The main idea behind the concept that I'm looking for similar kind of solution:
mvn clean install -DenvFile=/path/<filename>.env
OR
mvn clean deploy -DenvFile=/path/<filename>.env
OR
mvn clean package -DenvFile=/path/<filename>.env
Note: Not trying to produce the environment specific builds. In dev environment, my intention to run the junit tests with all the
environment variables configured from <filename>.env.
where, the above maven commands should set all the environment variables from <filename>.env and then execute the maven plugins. In IntelliJ, there's a envFile plugin which exactly do the same.
Don't want to have environment specific properties dev|staging|prod.properties in my project because it's messy and hard to manage. I'd rather prefer to have one single environment specific file filename.env which contains all the dynamic/changeable properties.
application.properties
spring:
cloud:
config:
uri: http://config-service:${CONFIG_SERVICE_PORT}
fail-fast: true
password: ${CONFIG_SERVICE_PASSWORD}
username: user
Environment File: .env
CONFIG_SERVICE_PORT=8080
CONFIG_SERVICE_PASSWORD=123
Now when I deploy the application in different environments like AWS, GCP and Azure. All I need to change the environment variables in the .env file and run the application java -DenvFile=/path/<fileName>.env -jar application.jar and it will do the magic.
My problem is related with maven-sure-fire plugin for testing in dev-mode, which require these environments variables for spring context.
Any help would be appreciated.
Ok from your comments it seems like you're looks for two different solutions:
Run the application in different environments with java -DenvFile=/path/<fileName>.env -jar application.jar
Solution for running tests.
These are different issues I'll try to address both
Issue 1
When you run java -jar this means that the artifact is already assembled (with the help of spring boot maven plugin as far as I understand).
This jar is a ready to go spring boot application and maven is basically irrelevant here - maven is a build system, spring is a runtime framework and we're talking about the runtime.
Spring boot has a lot of ways to achieve what you want. A "Native" spring boot way which is close to your situation is running the application with "--spring.config.location=file:// with all the required configurations
It looks like this (see here for complete documentation):
java -jar application.jar --spring.config.location=myprops.properties
Even if you have some properties defined in src/main/resources/application.properties this method allows to override them effectively providing a way to run different configurations in different environments.
This has an advantage over the .env files because it can run in the same way in all the OS-es, even Windows ;) Since Java is OS independent - I believe its the best you can achieve.
Of course you can wrap the java -jar line in some kind of bash script and load / execute a series of export commands before running the jvm, but again, its less "spring-y" way.
Issue 2
Maven runs the tests (unit/integration) in a way that spring boot maven plugin is irrelevant. Its all about surefire/failsafe and spring boot testing framework.
I'll assume you're asking about integration tests because I believe this is all irrelevant for unit tests, since those should not require any environment variables at all and should be run without spring at all (junit/mockito should do the job)
I'll also allow myself to keep the assumption that the way of overriding/configuring the spring boot application via yaml or properties file is better than .env and will provide spring test configuration solution here:
With these assumptions you can create a yaml file in the following path: src/test/resources/application-test.yml
This file can contain configurations relevant for tests and will override anything written in src/main/resources/application.yml. Note, since application-test.yml resides in test sources, spring boot maven plugin won't package it into the application.
Depending on the exact way of doing integration tests you might consider also using #TestPropertySource annotation to provide the custom properties/yaml file that doesn't follow spring boot's default convention. Its especially useful for spring driven tests that do not bootstrap with the spring boot full fledged support (read the tests that use junit's spring runner but don't have annotation #SpringBootTest)
Another possibly useful annotation is #ActiveProfile("myprofile"). This will cause spring boot tests to automatically load file src/test/resources/application-myprofile.yml (or application-myprofile.properties)
Last but not least I'll refer the second comment with "dev/prod/staging/properties" in the source.
When it comes to tests - there should be only one file application-test.yml. However note that when you're using yaml, its possible to define configurations for many spring boot profiles in the same file:
# default value
foo:
bar: 1
---
spring:
profiles: staging
foo:
bar: 2
---
spring:
profiles: prod
foo:
bar: 3
Some relevant SO thread

Spring boot 2.0.4 application properties not being overridden by command line json

I am using spring boot 2.0.4 and creating an executable jar.
I have below properties defined in my application.properties
configserviceendpoint=devendpoint
I am following spring docs to pass the properties as .json and tried running the application using below commands
java -Dspring.application.json='{"configserviceendpoint":"prod end point"}' -jar myapp.jar
java -jar myapp.jar --spring.application.json='{"configserviceendpoint":"prod end point"}'
While trying to access the property in my code it still shows the value defined in application.properties and not the one which is being passed in command as .json
Thanks.
Please try to run it as following:
java -jar myapp.jar --configserviceendpoint="prod/endpoint"

How to generate executable scripts using spring boot maven plugin

Using spring boot maven plugin we are able to generate executable jars. And we can execute the jar using java -jar ...
In spring boot there is another option for installation . This generates the jar which can be added in init.d.
But is it possible to generate a sh|cmd file which can be used to start|stop|restart spring boot applications?
The executable true flag to create a 'fully executable’ jar actually pre-pends a shell script into the beginning of the jar.
It works outside init.d too. Try this:
./myapp.jar start

how to tune jvm when using spring boot application as unix service

i'm using the new spring-boot 1.3.0 feature to run tomcat embedded spring-boot application jar as a unix service.
All is working fine but i don't know how to tune jvm (with -Xms and -Xmx parameters for example)
I've searched in spring documentation and around the web without success.
It's missing from the documentation (I've opened an issue to correct that), but you should be able to use the JAVA_OPTS environment variable.
You can configure it in a .conf file that's situated next to the jar. For example, if you jar file is /var/myapp/myapp.jar, the file /var/myapp/myapp.conf will be sourced by the launch script.
There is one more option to achieve the same , if you are running jar with mvn you can do something like this
mvn spring-boot:run -Drun.jvmArguments="-Xmx512m"
And If you are running with java -jar ,you can try something like this
java -Xmx1G -jar myapp.jar

Spring Boot with Groovy and External Libraries

I'm working on building what is effectively a throwaway Spring Boot application. Using the CLI, I can get a basic page up and working (see https://spring.io/guides/gs/spring-boot/). What I haven't figured out how to do, however, is how I can add external dependencies (ie. third-party JAR files) to the compile or runtime classpath when I use either the "spring run" or "spring jar" commands. Note that these external dependencies are local to my computer and are not stored in an artifact repository. Is there a simple way to do this?
If the jars aren't in an artifact repository, the easiest way to add them to the classpath is to use -cp when running your app or creating its jar.
For example:
spring run -cp foo.jar app.groovy
Or:
spring jar -cp foo.jar app.jar app.groovy
In the spring jar case, anything that's added to the classpath using -cp will be packaged inside the resulting jar (app.jar in this case) ensuring that it's self-contained.
you can use groovy's #Grab notation (there is also spring grab call). E.g.
#Grab('joda-time:joda-time:2.5')
#RestController
class ThisWillActuallyRun {
#RequestMapping("/")
String home() {
return new org.joda.time.DateTime().toString()
}
}

Resources