Skip to content

Commit

Permalink
ProfileResult and CollectorResult should print machine readable timin…
Browse files Browse the repository at this point in the history
…g information

Currently both ProfileResult and CollectorResult print the timing field in a
human readable string format (e.g. "time": "55.20315000ms"). When trying to
parse this back to a long value, for example to use in the planned high level
java rest client, we can lose precision because of conversion and rounding
issues. This change introduces the additional field `time_in_nanos` that prints
the raw timing value in nanoseconds.
  • Loading branch information
cbuescher committed Jan 16, 2017
1 parent e6978ae commit 1ba2692
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public final class ProfileResult implements Writeable, ToXContent {
private static final ParseField TYPE = new ParseField("type");
private static final ParseField DESCRIPTION = new ParseField("description");
private static final ParseField NODE_TIME = new ParseField("time");
private static final ParseField NODE_TIME_NANOS = new ParseField("time_in_nanos");
private static final ParseField CHILDREN = new ParseField("children");
private static final ParseField BREAKDOWN = new ParseField("breakdown");

Expand Down Expand Up @@ -147,6 +148,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
.field(TYPE.getPreferredName(), type)
.field(DESCRIPTION.getPreferredName(), description)
.field(NODE_TIME.getPreferredName(), String.format(Locale.US, "%.10gms", getTime() / 1000000.0))
.field(NODE_TIME_NANOS.getPreferredName(), getTime())
.field(BREAKDOWN.getPreferredName(), timings);

if (!children.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class CollectorResult implements ToXContent, Writeable {
private static final ParseField NAME = new ParseField("name");
private static final ParseField REASON = new ParseField("reason");
private static final ParseField TIME = new ParseField("time");
private static final ParseField TIME_NANOS = new ParseField("time_in_nanos");
private static final ParseField CHILDREN = new ParseField("children");

/**
Expand Down Expand Up @@ -140,7 +141,8 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par
builder = builder.startObject()
.field(NAME.getPreferredName(), getName())
.field(REASON.getPreferredName(), getReason())
.field(TIME.getPreferredName(), String.format(Locale.US, "%.10gms", (double) (getTime() / 1000000.0)));
.field(TIME.getPreferredName(), String.format(Locale.US, "%.10gms", getTime() / 1000000.0))
.field(TIME_NANOS.getPreferredName(), getTime());

if (!children.isEmpty()) {
builder = builder.startArray(CHILDREN.getPreferredName());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.search.profile;

import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.test.ESTestCase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ProfileResultTests extends ESTestCase {

public void testToXContent() throws IOException {
List<ProfileResult> children = new ArrayList<>();
children.add(new ProfileResult("child1", "desc1", Collections.emptyMap(), Collections.emptyList(), 100L));
children.add(new ProfileResult("child2", "desc2", Collections.emptyMap(), Collections.emptyList(), 123356L));
Map<String, Long> timings = new HashMap<>();
timings.put("key1", 12345L);
timings.put("key2", 6789L);
ProfileResult result = new ProfileResult("someType", "some description", timings, children, 123456L);
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
result.toXContent(builder, ToXContent.EMPTY_PARAMS);
assertEquals("{\n" +
" \"type\" : \"someType\",\n" +
" \"description\" : \"some description\",\n" +
" \"time\" : \"0.1234560000ms\",\n" +
" \"time_in_nanos\" : 123456,\n" +
" \"breakdown\" : {\n" +
" \"key1\" : 12345,\n" +
" \"key2\" : 6789\n" +
" },\n" +
" \"children\" : [\n" +
" {\n" +
" \"type\" : \"child1\",\n" +
" \"description\" : \"desc1\",\n" +
" \"time\" : \"0.0001000000000ms\",\n" +
" \"time_in_nanos\" : 100,\n" +
" \"breakdown\" : { }\n" +
" },\n" +
" {\n" +
" \"type\" : \"child2\",\n" +
" \"description\" : \"desc2\",\n" +
" \"time\" : \"0.1233560000ms\",\n" +
" \"time_in_nanos\" : 123356,\n" +
" \"breakdown\" : { }\n" +
" }\n" +
" ]\n" +
"}", builder.string());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.search.profile.query;

import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.test.ESTestCase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectorResultTests extends ESTestCase {

public void testToXContent() throws IOException {
List<CollectorResult> children = new ArrayList<>();
children.add(new CollectorResult("child1", "reason1", 100L, Collections.emptyList()));
children.add(new CollectorResult("child2", "reason1", 123356L, Collections.emptyList()));
CollectorResult result = new CollectorResult("collectorName", "some reason", 123456L, children);
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
result.toXContent(builder, ToXContent.EMPTY_PARAMS);
assertEquals("{\n" +
" \"name\" : \"collectorName\",\n" +
" \"reason\" : \"some reason\",\n" +
" \"time\" : \"0.1234560000ms\",\n" +
" \"time_in_nanos\" : 123456,\n" +
" \"children\" : [\n" +
" {\n" +
" \"name\" : \"child1\",\n" +
" \"reason\" : \"reason1\",\n" +
" \"time\" : \"0.0001000000000ms\",\n" +
" \"time_in_nanos\" : 100\n" +
" },\n" +
" {\n" +
" \"name\" : \"child2\",\n" +
" \"reason\" : \"reason1\",\n" +
" \"time\" : \"0.1233560000ms\",\n" +
" \"time_in_nanos\" : 123356\n" +
" }\n" +
" ]\n" +
"}", builder.string());
}
}
Loading

0 comments on commit 1ba2692

Please sign in to comment.