Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Content: Observability for java applications #69

Merged
merged 21 commits into from
Sep 30, 2020

Conversation

spinscale
Copy link
Contributor

@spinscale spinscale commented Jul 28, 2020

This document leads through the steps to setup observability from the
angle of a Java developer writing their own web application.

The corresponding code repo is at https://github.com/spinscale/observability-using-the-elastic-stack-java - however the reader should be able to build everything from scratch, not needing that repo, except for taking a short cut.

Note: As we are still figuring out, if this is the right format, let's not get into content corrections first, but make sure that everything is aligned the way we would like it to be :-)

HTML preview

https://observability-docs_69.docs-preview.app.elstc.co/guide/en/observability/master/monitor-java-app.html

Related issue

Closes #57

This document leads through the steps to setup observability from the
angle of a Java developer writing their own web application.
@spinscale spinscale requested a review from EamonnTP July 28, 2020 13:17
@spinscale spinscale marked this pull request as draft July 28, 2020 13:18
@EamonnTP
Copy link
Contributor

EamonnTP commented Jul 29, 2020

Hi @spinscale thanks for doing this!

Before we start looking at the content, in terms of where the content will reside, I suggest the following:

  1. Let's use the docs/en/observability/ folder instead of creating a new java-tutorial one.
  2. Rename your index.asciidoc file to monitor-java-app.asciidoc and move to the docs/en/observability/ folder.
  3. In the docs/en/observability/ folder, create and add a tutorials.asciidoc file.
  4. In the tutorials.asciidoc file, include the monitor-java-app.asciidoc file: include::./monitor-java-app.asciidoc[]
  5. In the Observability index.asciidoc file, include the tutorials.asciidoc file: include::./tutorials.asciidoc[].
  6. For your images, create an images folder within docs/en/observability/.

@spinscale
Copy link
Contributor Author

thx for the hints, done!

@EamonnTP EamonnTP added v7.10.0 v7.10.0 docs Improvements or additions to documentation labels Aug 4, 2020
@EamonnTP
Copy link
Contributor

EamonnTP commented Aug 25, 2020

Hi @spinscale I completed a first-time pass edit on the tutorial. It still requires further edits before we move it from draft, however, you can now preview the doc. I will have a chat with the other Observability writers to ensure this is the structure we want in the final published doc. Thanks!

@elastic elastic deleted a comment from apmmachine Aug 25, 2020
Copy link
Member

@bmorelli25 bmorelli25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick scan of this, and it looks really good. I'm excited to get this in the docs! As we discussed in the docs weekly, I think this format is fine and overlaps with the direction we want the docs to head in.

The corresponding code repo is at https://github.com/spinscale/observability-using-the-elastic-stack-java - however the reader should be able to build everything from scratch, not needing that repo, except for taking a short cut.

@spinscale, how would you feel about adding this project to an elastic repo? Maybe in the observability-docs repo under a new contrib directory? It'd be nice if the project lived here for us to update as necessary. With that being said, I understand if you want to keep it in your own repo.

Let me know when this is ready for a more thorough review, and I'll set aside a chunk of time to go through the entire tutorial.

@apmmachine
Copy link
Contributor

A docs preview will be available soon:
- HTML diff
- Observability guide

@EamonnTP EamonnTP marked this pull request as ready for review September 8, 2020 14:32
@EamonnTP
Copy link
Contributor

EamonnTP commented Sep 8, 2020

@elastic/obs-docs This is now ready for a review. @bmorelli25 I wasn't able to test the APM section, so it would be great if you could have a look at it. Thanks.

@EamonnTP EamonnTP requested a review from a team September 8, 2020 14:34
Copy link
Contributor

@dedemorton dedemorton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is absolutely fantastic! I'm excited to see this level of detail added to the docs. My comments are mostly around usage of attributes to resolve doc paths. If I've made any typos in the paths, the CI will let you know. :-)

Very nicely done.

monitoring. Also, consider this just the beginning as the next step is
to have synthetics that monitor the correct behavior of your
application, for example, to ensure that your checkout process works all
the time.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a "What's next" section that points users to the next great thing they want to do?

Copy link
Member

@bmorelli25 bmorelli25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff!

I'm unable to make it past step 1.8. Please see this comment below. I get a FAILURE: Build failed with an exception. #69 (comment). I tried googling for a couple hours but can't figure out what I'm doing wrong. I followed the tutorial line for line. I think it comes down to me not knowing what Set up a Gradle project means. I tried with gradle init, but perhaps that is not right. If I don't use gradle init, I can't make it to 1.8.

Comment on lines +114 to +115
. Run `./gradlew shadowJar`. This command creates a
`build/libs/javalin-app-all.jar` file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't get past this step. I get the following error:

Brandons-MacBook-Pro-4 elastic-obs-java-app $ ./gradlew shadowJar

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/brandonmorelli/Documents/GitHub/elastic-obs-java-app/build.gradle' line: 17

* What went wrong:
A problem occurred evaluating root project 'javalin-app'.
> Could not find method application() for arguments [build_954lfwy4urhht8sn6t17frb29$_run_closure3@71d3bfa7] on root project 'javalin-app' of type org.gradle.api.Project.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you run ./gradlew --version and paste the results here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the results when I run ./gradlew --version


Gradle 6.5.1

Build time: 2020-06-30 06:32:47 UTC
Revision: 66bc713f7169626a7f0134bf452abde51550ea0a

Kotlin: 1.3.72
Groovy: 2.5.11
Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM: 14.0.2 (Oracle Corporation 14.0.2+12-46)
OS: Mac OS X 10.14.5 x86_64

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

------------------------------------------------------------
Gradle 6.5.1
------------------------------------------------------------

Build time:   2020-06-30 06:32:47 UTC
Revision:     66bc713f7169626a7f0134bf452abde51550ea0a

Kotlin:       1.3.72
Groovy:       2.5.11
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          14.0.2 (Oracle Corporation 14.0.2+12-46)
OS:           Mac OS X 10.15.6 x86_64

Looks to be the same as Eamonn

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks good. Can you share your project somewhere so I can take a look?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I copy your build.gradle file from https://github.com/spinscale/observability-using-the-elastic-stack-java/blob/main/build.gradle, I'm able to run ./gradlew shadowJar successfully. I think there is something missing from build.gradle at this step, but I'm not sure what it is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, here's what it looks like when following the tutorial (this fails)

plugins {
  id 'com.github.johnrengelman.shadow' version '6.0.0'
  id 'java'
}

repositories {
  jcenter()
}

dependencies {
  implementation 'io.javalin:javalin:3.9.1'

  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

application {
  mainClassName = 'de.spinscale.javalin.App'
}

test {
  useJUnitPlatform()
}

And here's what it looks like after copying from your repo (this builds successfully)

plugins {
  id 'com.github.johnrengelman.shadow' version '6.0.0'
  id 'java'
  // this helps identifying new versions with a single gradle call
  id "com.github.ben-manes.versions" version '0.31.0'
}

repositories {
  jcenter()
}

jar {
  manifest {
    attributes 'Main-Class': 'de.spinscale.javalin.App'
  }
}

dependencies {
  implementation 'io.javalin:javalin:3.10.0'
  implementation 'org.apache.logging.log4j:log4j-slf4j18-impl:2.13.3'
  implementation 'co.elastic.logging:log4j2-ecs-layout:0.5.0'
  // metrics via micrometer
  implementation 'io.micrometer:micrometer-core:1.5.4'
  implementation 'io.micrometer:micrometer-registry-prometheus:1.5.4'
  implementation 'org.apache.commons:commons-lang3:3.11'
  // apm agent to implement custom transactions and spans
  implementation 'co.elastic.apm:apm-agent-attach:1.17.0'
  implementation "co.elastic.apm:apm-agent-api:1.17.0"
  // http client
  implementation 'org.apache.httpcomponents:fluent-hc:4.5.12'

  testImplementation 'org.mockito:mockito-core:3.5.10'
  testImplementation 'org.assertj:assertj-core:3.17.1'
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

test {
  useJUnitPlatform()
}

// ensure the EcsLayout setting still functions properly
shadowJar {
  transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some trial and error, it's this part that causes my error:

application {
  mainClassName = 'de.spinscale.javalin.App'
}

If I remove this from the tutorial's build.gradle, it builds successfully:

plugins {
  id 'com.github.johnrengelman.shadow' version '6.0.0'
  id 'java'
}

repositories {
  jcenter()
}

dependencies {
  implementation 'io.javalin:javalin:3.9.1'

  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

test {
  useJUnitPlatform()
}

Can we remove these lines from the tutorial?

Copy link
Member

@bmorelli25 bmorelli25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spinscale Most of these comments/errors/suggestions are directed at you. It's getting late here, so I'm taking a break for now. I completed everything through Step 3 (Ingest Logs), and I'll pick up with metrics tomorrow.

Comment on lines +114 to +115
. Run `./gradlew shadowJar`. This command creates a
`build/libs/javalin-app-all.jar` file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I copy your build.gradle file from https://github.com/spinscale/observability-using-the-elastic-stack-java/blob/main/build.gradle, I'm able to run ./gradlew shadowJar successfully. I think there is something missing from build.gradle at this step, but I'm not sure what it is.

Comment on lines +114 to +115
. Run `./gradlew shadowJar`. This command creates a
`build/libs/javalin-app-all.jar` file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, here's what it looks like when following the tutorial (this fails)

plugins {
  id 'com.github.johnrengelman.shadow' version '6.0.0'
  id 'java'
}

repositories {
  jcenter()
}

dependencies {
  implementation 'io.javalin:javalin:3.9.1'

  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

application {
  mainClassName = 'de.spinscale.javalin.App'
}

test {
  useJUnitPlatform()
}

And here's what it looks like after copying from your repo (this builds successfully)

plugins {
  id 'com.github.johnrengelman.shadow' version '6.0.0'
  id 'java'
  // this helps identifying new versions with a single gradle call
  id "com.github.ben-manes.versions" version '0.31.0'
}

repositories {
  jcenter()
}

jar {
  manifest {
    attributes 'Main-Class': 'de.spinscale.javalin.App'
  }
}

dependencies {
  implementation 'io.javalin:javalin:3.10.0'
  implementation 'org.apache.logging.log4j:log4j-slf4j18-impl:2.13.3'
  implementation 'co.elastic.logging:log4j2-ecs-layout:0.5.0'
  // metrics via micrometer
  implementation 'io.micrometer:micrometer-core:1.5.4'
  implementation 'io.micrometer:micrometer-registry-prometheus:1.5.4'
  implementation 'org.apache.commons:commons-lang3:3.11'
  // apm agent to implement custom transactions and spans
  implementation 'co.elastic.apm:apm-agent-attach:1.17.0'
  implementation "co.elastic.apm:apm-agent-api:1.17.0"
  // http client
  implementation 'org.apache.httpcomponents:fluent-hc:4.5.12'

  testImplementation 'org.mockito:mockito-core:3.5.10'
  testImplementation 'org.assertj:assertj-core:3.17.1'
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

test {
  useJUnitPlatform()
}

// ensure the EcsLayout setting still functions properly
shadowJar {
  transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer)
}

Comment on lines +114 to +115
. Run `./gradlew shadowJar`. This command creates a
`build/libs/javalin-app-all.jar` file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some trial and error, it's this part that causes my error:

application {
  mainClassName = 'de.spinscale.javalin.App'
}

If I remove this from the tutorial's build.gradle, it builds successfully:

plugins {
  id 'com.github.johnrengelman.shadow' version '6.0.0'
  id 'java'
}

repositories {
  jcenter()
}

dependencies {
  implementation 'io.javalin:javalin:3.9.1'

  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

test {
  useJUnitPlatform()
}

Can we remove these lines from the tutorial?

+
[source,bash]
----
java -jar build/libs/javalin-app-all.jar
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this step I got the following error:

Brandons-MacBook-Pro-4 elastic-obs-java-app $ java -jar build/libs/javalin-app-all.jar
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
-------------------------------------------------------------------

-------------------------------------------------------------------
Missing dependency 'Slf4j simple'. Add the dependency.

pom.xml:
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.30</version>
</dependency>

build.gradle:
compile "org.slf4j:slf4j-simple:1.7.30"

Find the latest version here:
https://search.maven.org/search?q=g%3Aorg.slf4j+AND+a%3Aslf4j-simple

I was able to add compile 'org.slf4j:slf4j-simple:1.7.30' to the dependencies section of build.gradle, rerun ./gradlew shadowJar, and then successfully run java -jar build/libs/javalin-app-all.jar.

Do we need to mention this, or is my situation unique?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not need to do this after adding the org.apache.logging.log4j:log4j-slf4j18-impl:2.13.3 dependency. Did you do that?

Regarding your above comment, I fixed this by adding another line to the build.gradle file.

Comment on lines +532 to +539
Javalin app = Javalin.create(config -> {
config.requestLogger((ctx, executionTimeMs) -> {
String userAgent = ctx.userAgent() != null ? ctx.userAgent() : "-";
logger.info("{} {} {} {} \"{}\" {}",
ctx.method(), ctx.req.getPathInfo(), ctx.res.getStatus(),
ctx.req.getRemoteHost(), userAgent, executionTimeMs.longValue());
});
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code does not fix my "null" problem. I still see this:

2020-09-10T22:30:25,436-07:00 [INFO ] de.spinscale.javalin.App This is an informative logging message, user agent [null]

Copy link
Member

@bmorelli25 bmorelli25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more comments for you, @spinscale! Got to the Custom transactions section this time. I'll finish up next week. This is looking great!

To improve security, add the username and the
password to the keystore and refer it here as well.
+
. Start {metricbeat} and verify that the Prometheus events are flowing into
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EamonnTP We should add the start widget here

+
We did not configure any endpoint or API tokens yet. While the
https://www.elastic.co/guide/en/apm/agent/java/current/setup-attach-api.html#setup-attach-api-configuration[documentation]
recommends using the `src/main/resources/elasticapm.properties` file, I
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a tutorial, I agree.

@spinscale
Copy link
Contributor Author

I did another pass over this with many small fixes. One major change is to also add all the required imports in code snippets, to make it easier for others to understand those.

Copy link
Member

@bmorelli25 bmorelli25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this took so long to review. I'm stoked to finally get this merged!

@spinscale
Copy link
Contributor Author

One last thing regarding the accompanying code repository. I'm more than happy to move this under the elastic umbrella - I suppose it is better to have another observability-docs-examples-java repo that contains that code? Alternatively we have an examples github repo under the elastic umbrella, but I am unsure who owns that.

@bmorelli25
Copy link
Member

My vote would be for something like an observability-examples or observability-contrib repo (perhaps similar to https://github.com/elastic/apm-contrib). This is tutorial number one of many, and I think it'd be great if code from all of our tutorials could live together so that they're easily searchable/scannable by our users.

@dedemorton
Copy link
Contributor

+1 to having a place for providing examples that support our tutorials. I also plan to provide some example data for the Kubernetes monitoring docs we'll be writing soon. I'm not sure if we should require users to have a GitHub account, though. I wonder how other doc teams are handling this question? I'd think a simple download link might be easier for some users.

@spinscale
Copy link
Contributor Author

@dedemorton as that will become a public github repo, there is no need for an dedicated github account in order to clone it and play around with it

I like the observability-contrib idea similar to APM. Unless I get a veto within 24h, I'd just go ahead and create it (or file an infra issue, not sure if everyone can create repos nowadays).

@dedemorton
Copy link
Contributor

dedemorton commented Sep 23, 2020

there is no need for an dedicated github account in order to clone it and play around with it

That's a good point, but wouldn't this still require users to set up the git client on their machine? For the Java tutorial, there's a pretty good chance that the target audience will know about git. But for some of the tutorials coming down the road (for example, tutorials targeted at analysts), I don't think we should expect them to clone repos or interact with git.

I'm happy to shelve the conversation for now so you can get this thing done, but I think we need to revisit the question as a group and come up with an approach that works for other use cases that will require sample data or applications.

EDITED: We should look at how other teams do this. I know the Logstash getting started docs provide a link to an archive that users can download: https://download.elastic.co/demos/logstash/gettingstarted/logstash-tutorial.log.gz.

@bmorelli25
Copy link
Member

Sorry I missed the obs-docs sync this morning -- I imagine this was a topic of discussion. I think it's fine to treat tutorials targeted at analysts differently, for example, by hosting a download link with sample data. But for these kinds of tutorials, I think GitHub is the ideal choice. Some users wont want to download the entire sample app, but they may want to glance at certain source files as they build the project. GitHub repos also have the added benefit of showing up in Google and GitHub searches.

@bmorelli25
Copy link
Member

I think the apm-contrib repo is a great example of how well a GitHub repo can work in this context. I don't want to post the traffic data publicly, but take a look (or I can share on slack if you don't have access).

@dedemorton
Copy link
Contributor

@bmorelli25 That's a good point; tailoring our delivery of sample code/applications to specific audiences makes sense. You've convinced me!

@spinscale
Copy link
Contributor Author

@dedemorton your point regarding git, requiring it for non developers makes a lot of sense. Just to keep in mind: There is an option (with an always working link) to download the git repo as a zip file anytime under the Code section

Screenshot 2020-09-24 at 00 01 16

This would allow users to always have the most recent download link of all your samples, while still enjoying the advantages of a versioned repo for all the folks creating the projects. Hope that helps!

@spinscale
Copy link
Contributor Author

I just created the github repository at including the app at https://github.com/elastic/observability-contrib/tree/main/monitor-java-app and added the repo into the document.

If you think this is ready from the docs team side, please go ahead and merge, as I have no idea in what branches I would need to do anything.

Thank you @dedemorton, @EamonnTP and @bmorelli25 for all your help and edits, much appreciated!

@EamonnTP
Copy link
Contributor

@spinscale Thank you for a great tutorial!

@EamonnTP EamonnTP merged commit f940931 into elastic:master Sep 30, 2020
@EamonnTP EamonnTP deleted the java-tutorial branch September 30, 2020 08:28
EamonnTP pushed a commit that referenced this pull request Sep 30, 2020
* Add Content: Observability for java applications

This document leads through the steps to setup observability from the
angle of a Java developer writing their own web application.

* Renaming according to review comments

* First pass edit

* Minor edits

* Minor edits

* First phase of review edits

* Fixes based on review comments

* review comments

* update javalin version

* review comments

* improve snippets

* minor overhaul

* add transaction name setting to request logger

* Improve setting transaction name

* Add tab widgest

* Minor edits

* Add start widgets

* Add mention of newly created github repository

Co-authored-by: EamonnTP <Eamonn.Smith@elastic.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to documentation v7.10.0 v7.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Elastic Observability how-to guide to the docs
5 participants