io.undertow.attribute.ResponseTimeAttribute Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.undertow.attribute;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.AttachmentKey;
import java.util.concurrent.TimeUnit;
/**
* The response time
*
* This will only work if {@link io.undertow.UndertowOptions#RECORD_REQUEST_START_TIME} has been set
*/
public class ResponseTimeAttribute implements ExchangeAttribute {
private static final AttachmentKey FIRST_RESPONSE_TIME_NANOS = AttachmentKey.create(Long.class);
public static final String RESPONSE_TIME_MILLIS_SHORT = "%D";
public static final String RESPONSE_TIME_SECONDS_SHORT = "%T";
public static final String RESPONSE_TIME_MILLIS = "%{RESPONSE_TIME}";
public static final String RESPONSE_TIME_MICROS = "%{RESPONSE_TIME_MICROS}";
public static final String RESPONSE_TIME_NANOS = "%{RESPONSE_TIME_NANOS}";
private final TimeUnit timeUnit;
public ResponseTimeAttribute(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
@Override
public String readAttribute(HttpServerExchange exchange) {
long requestStartTime = exchange.getRequestStartTime();
if(requestStartTime == -1) {
return null;
}
final long nanos;
Long first = exchange.getAttachment(FIRST_RESPONSE_TIME_NANOS);
if(first != null) {
nanos = first;
} else {
nanos = System.nanoTime() - requestStartTime;
if(exchange.isResponseComplete()) {
//save the response time so it is consistent
exchange.putAttachment(FIRST_RESPONSE_TIME_NANOS, nanos);
}
}
if(timeUnit == TimeUnit.SECONDS) {
StringBuilder buf = new StringBuilder();
long milis = TimeUnit.MILLISECONDS.convert(nanos, TimeUnit.NANOSECONDS);
buf.append(Long.toString(milis / 1000));
buf.append('.');
int remains = (int) (milis % 1000);
buf.append(Long.toString(remains / 100));
remains = remains % 100;
buf.append(Long.toString(remains / 10));
buf.append(Long.toString(remains % 10));
return buf.toString();
} else {
return String.valueOf(timeUnit.convert(nanos, TimeUnit.NANOSECONDS));
}
}
@Override
public void writeAttribute(HttpServerExchange exchange, String newValue) throws ReadOnlyAttributeException {
throw new ReadOnlyAttributeException("Response Time", newValue);
}
@Override
public String toString() {
if (timeUnit.equals(TimeUnit.MILLISECONDS)) {
return RESPONSE_TIME_MILLIS;
}
if (timeUnit.equals(TimeUnit.SECONDS)) {
return RESPONSE_TIME_SECONDS_SHORT;
}
if(timeUnit.equals(TimeUnit.MICROSECONDS)) {
return RESPONSE_TIME_MICROS;
}
if(timeUnit.equals(TimeUnit.NANOSECONDS)) {
return RESPONSE_TIME_NANOS;
}
return "ResponseTimeAttribute";
}
public static final class Builder implements ExchangeAttributeBuilder {
@Override
public String name() {
return "Response Time";
}
@Override
public ExchangeAttribute build(String token) {
if (token.equals(RESPONSE_TIME_MILLIS) || token.equals(RESPONSE_TIME_MILLIS_SHORT)) {
return new ResponseTimeAttribute(TimeUnit.MILLISECONDS);
}
if (token.equals(RESPONSE_TIME_SECONDS_SHORT)) {
return new ResponseTimeAttribute(TimeUnit.SECONDS);
}
if(token.equals(RESPONSE_TIME_MICROS)) {
return new ResponseTimeAttribute(TimeUnit.MICROSECONDS);
}
if(token.equals(RESPONSE_TIME_NANOS)) {
return new ResponseTimeAttribute(TimeUnit.NANOSECONDS);
}
return null;
}
@Override
public int priority() {
return 0;
}
}
}