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

Issue #4954 - ByteCount API proposal #4955

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -365,6 +365,11 @@ public long getContentRead()
return _contentPosition;
}

public long getHeaderLength()
{
return _headerBytes;
}

/**
* Set if a HEAD response is expected
*
Expand Down
@@ -0,0 +1,51 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//

package org.eclipse.jetty.server;

public interface ByteCountEvent
{
Request getRequest();

Response getResponse();

boolean hasFailure();

Throwable getRequestFailure();

Throwable getResponseFailure();

// TODO: do we care about upgraded connections?
// TODO: what about the TLS bytes? (SSLConnection bytesIn / bytesOut?)
// TODO: what about HTTP/2 ? (what about non-stream frames? settings, window-updates, reset, etc)

interface HttpByteCount
{
long getHeaderCount();

long getBodyCount();

long getStreamAPICount();

long getTrailerCount();
}

HttpByteCount getRequestCount();

HttpByteCount getResponseCount();
}
@@ -0,0 +1,205 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//

package org.eclipse.jetty.server;

public class ByteCountEventAdaptor implements ByteCountEvent
{
private final Request request;

public ByteCountEventAdaptor(Request request)
{
this.request = request;
this.requestCounts = new HttpByteCountAdaptor();
this.responseCounts = new HttpByteCountAdaptor();
}

public void onComplete(long bytesIn, long bytesOut)
{
requestCounts.connectionCount = bytesIn;
responseCounts.connectionCount = bytesOut;
}

class HttpByteCountAdaptor implements HttpByteCount
{
// The connectionCount
private long connectionCount;
// The failure condition / cause
private Throwable failure;
// The location when the failure occurred in connectionCount
private long failureLoc = -1;
// Start of headers in connectionCount;
private long headerStart;
// End of headers in connectionCount;
private long headerEnd = -1;
// Start of body in connectionCount;
private long bodyStart;
// End of body in connectionCount;
private long bodyEnd = -1;
// Start of trailer in connectionCount;
private long trailerStart;
// End of trailer in connectionCount;
private long trailerEnd = -1;
// Reported Streaming API bytes used via Servlet API
private long apiCount = -1;

@Override
public long getHeaderCount()
{
if (headerEnd >= headerStart)
return headerEnd - headerStart;
else
return -1;
}

@Override
public long getBodyCount()
{
if (bodyEnd >= bodyStart)
return bodyEnd - bodyStart;
else
return -1;
}

@Override
public long getStreamAPICount()
{
return apiCount;
}

@Override
public long getTrailerCount()
{
if (trailerEnd >= trailerStart)
return trailerEnd = trailerStart;
else
return -1;
}

void onHeadersStart(long connectionCount)
{
this.connectionCount = connectionCount;
this.headerStart = connectionCount;
}

void onHeadersEnd(long connectionCount)
{
this.connectionCount = connectionCount;
this.headerEnd = connectionCount;
}

void onBodyStart(long connectionCount)
{
this.connectionCount = connectionCount;
this.bodyStart = connectionCount;
}

void onBodyEnd(long connectionCount, long byteCountAPI)
{
this.connectionCount = connectionCount;
this.bodyEnd = connectionCount;
this.apiCount = byteCountAPI;
this.trailerStart = connectionCount;
}

public void onTrailerStart(long connectionCount)
{
this.trailerStart = connectionCount;
}

void onTrailerEnd(long connectionCount)
{
this.trailerEnd = connectionCount;
}

public void onFailure(long connectionCount, Throwable failure)
{
this.connectionCount = connectionCount;
this.failure = failure;
}

@Override
public String toString()
{
final StringBuilder sb = new StringBuilder("HttpByteCount[");
sb.append("connectionCount=").append(connectionCount);
sb.append(", failure=").append(failure);
sb.append(", failureLoc=").append(failureLoc);
sb.append(", headerStart=").append(headerStart);
sb.append(", headerEnd=").append(headerEnd);
sb.append(", bodyStart=").append(bodyStart);
sb.append(", bodyEnd=").append(bodyEnd);
sb.append(", trailerStart=").append(trailerStart);
sb.append(", trailerEnd=").append(trailerEnd);
sb.append(", apiCount=").append(apiCount);
sb.append(']');
return sb.toString();
}
}

/**
* Request Counts. (including HttpConnection.bytesIn)
*/
private HttpByteCountAdaptor requestCounts;
/**
* Response Counts. (including HttpConnection.bytesOut)
*/
private HttpByteCountAdaptor responseCounts;

@Override
public Request getRequest()
{
return request;
}

@Override
public HttpByteCountAdaptor getRequestCount()
{
return requestCounts;
}

@Override
public HttpByteCountAdaptor getResponseCount()
{
return responseCounts;
}

@Override
public Response getResponse()
{
return request.getResponse();
}

@Override
public boolean hasFailure()
{
return (requestCounts.failure != null) || (responseCounts.failure != null);
}

@Override
public Throwable getRequestFailure()
{
return requestCounts.failure;
}

@Override
public Throwable getResponseFailure()
{
return responseCounts.failure;
}
}