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

feat(servlet): content length #726

Merged

Conversation

FrankSpitulski
Copy link
Contributor

@linux-foundation-easycla
Copy link

CLA Check

Copy link
Contributor

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

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

Thanks for helping with this!

@@ -19,6 +19,7 @@
public class MoreAttributes {
public static final String HTTP_QUERY = "http.query.string";
public static final String HTTP_FRAGMENT = "http.fragment.string";
public static final String HTTP_RESPONSE_CONTENT_LENGTH = "http.response_content_length";
Copy link
Contributor

Choose a reason for hiding this comment

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

If I recall correctly this was already released in otel 0.6.0, is it not part of SemanticAttributes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did a project wide search for the string before adding it. Is that defined elsewhere?

Copy link
Contributor

Choose a reason for hiding this comment

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

import javax.servlet.http.HttpServletResponseWrapper;

/** HttpServletResponseWrapper since servlet 2.3, not applicable to 2.2 */
public class CountingHttpServletResponse extends HttpServletResponseWrapper {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we may need counting for cases like chunked responses but a huge majority will have a content length header. What do you think about starting with that to get most bang for buck? We could do it in HttpServerTracer I think.

Either way we probably want to avoid adding this wrapper when the response has a content length header. We could use the content length in a future PR instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From my testing the set Content Length method is not invoked by springboot's rest controller. Counting the bytes was the only reliable way to get the size. I also tried to stick it in the http server tracer but the wrapper was introduced in servlet 2.3 and causes issues in the servlet 2.2 instrumentation.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see that sounds like for servlet we'll need to ignore the content length header always, thanks for the background

Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

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

Thanks @FrankSpitulski!

Do we also need to wrap/count for HttpServletResponse.getWriter()?

Check out the CI failures when you have time.

:instrumentation:dropwizard-testing:test is failing because it isn't expecting the new attribute.

There's also a muzzle build failure for :instrumentation:jetty-8.0:muzzle.

To fix the muzzle issues, add:

      "io.opentelemetry.auto.instrumentation.servlet.v3_0.CountingHttpServletResponse",
      "io.opentelemetry.auto.instrumentation.servlet.v3_0.CountingHttpServletResponse$CountingServletOutputStream",

to JettyHandlerInstrumentation.helperClassNames() (same as you already did in Servlet3Instrumentation).

Don't hesitate to reach out if muzzle gives you any more issues. It's mysterious and undocumented currently (#536).

@Override
public void write(byte[] b, int off, int len) throws IOException {
delegate.write(b, off, len);
counter += len - off;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
counter += len - off;
counter += len;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch

@FrankSpitulski
Copy link
Contributor Author

For completeness we should wrap getWriter, but in practice I don't think it is used on the httpservletresponse. The httpservletresponse overrides the outputstream and the use of the writer vs the output stream is mutually exclusive according to the docs. I can add a wrapper for it but I don't have a real world test case that uses it to verify.

@trask
Copy link
Member

trask commented Jul 19, 2020

I don't have a real world test case that uses it to verify.

I think the jsp-2.3 module tests (which also test the servlet-3.0 instrumentation) should use getWriter(), which would give us test coverage

@@ -50,6 +50,9 @@ public AsyncContextInstrumentation() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
"io.opentelemetry.auto.instrumentation.servlet.v3_0.CountingHttpServletResponse",
Copy link
Contributor

Choose a reason for hiding this comment

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

Use packageName as below

@@ -54,6 +54,9 @@ public Servlet3Instrumentation() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
"io.opentelemetry.auto.instrumentation.servlet.v3_0.CountingHttpServletResponse",
Copy link
Contributor

Choose a reason for hiding this comment

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

Use packageName as below

@@ -88,6 +88,8 @@ abstract class AbstractServlet3Test<SERVER, CONTEXT> extends HttpServerTest<SERV
"${SemanticAttributes.HTTP_URL.key()}" { it == "${endpoint.resolve(address)}" || it == "${endpoint.resolveWithoutFragment(address)}" }
"${SemanticAttributes.HTTP_METHOD.key()}" method
"${SemanticAttributes.HTTP_STATUS_CODE.key()}" endpoint.status
"${SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH.key()}" { it == null || it == getContentLength(endpoint) }
Copy link
Member

Choose a reason for hiding this comment

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

curious under what conditions is response content length not captured? (why we need it == null)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@trask There are quite a few where response length is not captured in the tests.
image

I haven't figured out how to track down why that is happening yet. The groovy tests are a lot less straightforward than junit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All of the sync tests are happy, maybe my async implementation is bad.

Copy link
Contributor Author

@FrankSpitulski FrankSpitulski Jul 21, 2020

Choose a reason for hiding this comment

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

checking the actual okhttp response body length in the test fixed the async tests. there is only one special case that ignores the content length, exceptions. Those don't hit the httpservletresponse as far as I can tell so I'm not sure where to count them.

gradlew.bat Outdated
@@ -1,104 +1,104 @@
@rem
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I cannot get git to leave this file alone. It changes it to have CRLF but according to the .gitattributes that should already be the case.

Copy link
Member

Choose a reason for hiding this comment

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

yeah, we just changed the .gitattributes file.

can you try:

rm .gitattributes
git checkout -- .gitattributes

Copy link
Member

Choose a reason for hiding this comment

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

oh i just got stuck in this again now too, will debug, really not understanding this either

Copy link
Member

@trask trask Jul 21, 2020

Choose a reason for hiding this comment

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

this seems to make the problem go away at least temporarily:

sed -i '/.bat/d' .gitattributes && git status > /dev/null && git checkout -- .gitattributes

Copy link
Member

Choose a reason for hiding this comment

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

i think i found permanent fix #743, sorry for the confusion 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@FrankSpitulski
Copy link
Contributor Author

all tests good now

@FrankSpitulski
Copy link
Contributor Author

I think the ci is having some interment failures. I'll squash a commit to trigger it again.

@trask
Copy link
Member

trask commented Jul 21, 2020

I think the ci is having some interment failures. I'll squash a commit to trigger it again.

Yeah, we have several sporadic failures currently: https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues?q=is%3Aissue+is%3Aopen+label%3A%22sporadic+test+failure%22

We'll watch the build and hit retry if it fails again.

Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

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

Thanks @FrankSpitulski, this is a great addition!

A couple of suggestions/comments below.

FrankSpitulski and others added 2 commits July 21, 2020 14:36
…etry/auto/instrumentation/servlet/v3_0/CountingHttpServletResponse.java

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
…etry/auto/instrumentation/servlet/v3_0/CountingHttpServletResponse.java

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

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

👍

@FrankSpitulski
Copy link
Contributor Author

FrankSpitulski commented Jul 21, 2020

@trask not sure what's going on with that failed test

groovy.lang.MissingMethodException: No signature of method: FinatraServer.started() is applicable for argument types: () values: []
Possible solutions: start(), stage(), trace(scala.Function0), trace(org.slf4j.Marker, scala.Function0), trace(scala.Function0, java.lang.Throwable), trace(org.slf4j.Marker, scala.Function0, java.lang.Throwable)
	at FinatraServerTest.startServer(FinatraServerTest.groovy:57)

started is an implicit injected function from the twitter scala inject-app library. The IDE seems to find it fine and I don't think I changed anything that would cause it to fail.

@trask
Copy link
Member

trask commented Jul 21, 2020

yeah, the test_latest build runs the tests against latest dependencies (in this case the latest finatra dependency) available in maven central, so sometimes it fails when there's a new version released, and i can see there was a new finatra version released just today

https://search.maven.org/search?q=g:com.twitter%20a:finatra-http_2.11

so that maybe the issue, i'll check it out and get back to you

@trask
Copy link
Member

trask commented Jul 21, 2020

Yeah, that's the problem. I submitted #747 to fix. And then I think I can merge master into your PR to get clean build, or if not I will ping you to merge master into your branch. thx for your patience as we go through growing pains 😅

@trask trask merged commit d6e39f8 into open-telemetry:master Jul 22, 2020
@trask
Copy link
Member

trask commented Jul 22, 2020

Thanks again @FrankSpitulski 🎉

@FrankSpitulski FrankSpitulski deleted the feat/servlet/content-length branch July 29, 2020 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants