Skip to content

Commit b37a830

Browse files
gmarzawelburn
authored andcommitted
Multiple fixes for the query profiler API (elastic#2624)
- Added time_in_nanos to response (closes elastic#2607) - Respose was missing the aggregations portion - Added full API and serialization tests which we were missing
1 parent cae455b commit b37a830

File tree

9 files changed

+227
-2
lines changed

9 files changed

+227
-2
lines changed

src/Nest/Nest.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,8 @@
12711271
<Compile Include="Search\Search\Hits\InnerHitsResult.cs" />
12721272
<Compile Include="Search\Search\Hits\NestedIdentity.cs" />
12731273
<Compile Include="Search\Search\InnerHits\InnerHits.cs" />
1274+
<Compile Include="Search\Search\Profile\AggregationBreakdown.cs" />
1275+
<Compile Include="Search\Search\Profile\AggregationProfile.cs" />
12741276
<Compile Include="Search\Search\Profile\Collector.cs" />
12751277
<Compile Include="Search\Search\Profile\Profile.cs" />
12761278
<Compile Include="Search\Search\Profile\QueryBreakdown.cs" />
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Collections.Generic;
2+
using Newtonsoft.Json;
3+
4+
namespace Nest
5+
{
6+
public class AggregationBreakdown
7+
{
8+
[JsonProperty("reduce")]
9+
public long Reduce { get; internal set; }
10+
11+
[JsonProperty("build_aggregation")]
12+
public long BuildAggregation { get; internal set; }
13+
14+
[JsonProperty("build_aggregation_count")]
15+
public long BuildAggregationCount { get; internal set; }
16+
17+
[JsonProperty("initialize")]
18+
public long Initialize { get; internal set; }
19+
20+
[JsonProperty("intialize_count")]
21+
public long InitializeCount { get; internal set; }
22+
23+
[JsonProperty("reduce_count")]
24+
public long ReduceCount { get; internal set; }
25+
26+
[JsonProperty("collect")]
27+
public long Collect { get; internal set; }
28+
29+
[JsonProperty("collect_count")]
30+
public long CollectCount { get; internal set; }
31+
}
32+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System.Collections.Generic;
2+
using Newtonsoft.Json;
3+
4+
namespace Nest
5+
{
6+
public class AggregationProfile
7+
{
8+
/// <summary>
9+
/// The Elasticsearch aggregation type
10+
/// </summary>
11+
[JsonProperty("type")]
12+
public string Type { get; internal set; }
13+
14+
/// <summary>
15+
/// The user defined name of the aggregation
16+
/// </summary>
17+
[JsonProperty("description")]
18+
public string Description { get; internal set; }
19+
20+
/// <summary>
21+
/// The time this aggregation took
22+
/// </summary>
23+
[JsonProperty("time")]
24+
public Time Time { get; internal set; }
25+
26+
/// <summary>
27+
/// The time this aggregation took, in nanoseconds
28+
/// </summary>
29+
[JsonProperty("time_in_nanos")]
30+
public long TimeInNanoseconds { get; internal set; }
31+
32+
/// <summary>
33+
/// Detailed stats about how the time was spent
34+
/// </summary>
35+
[JsonProperty("breakdown")]
36+
public AggregationBreakdown Breakdown { get; internal set; }
37+
}
38+
}

src/Nest/Search/Search/Profile/Collector.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ public class Collector
1414
[JsonProperty("time")]
1515
public Time Time { get; internal set; }
1616

17-
[JsonProperty("children")]
17+
[JsonProperty("time_in_nanos")]
18+
public long TimeInNanoseconds { get; internal set; }
19+
20+
[JsonProperty("children")]
1821
public IReadOnlyCollection<Collector> Children { get; internal set; } =
1922
EmptyReadOnly<Collector>.Collection;
2023

src/Nest/Search/Search/Profile/QueryProfile.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ public class QueryProfile
2323
[JsonProperty("time")]
2424
public Time Time { get; internal set; }
2525

26+
/// <summary>
27+
/// The time that this query took in nanoseconds
28+
/// </summary>
29+
[JsonProperty("time_in_nanos")]
30+
public long TimeInNanoseconds { get; internal set; }
31+
2632
/// <summary>
2733
/// Detailed stats about how the time was spent
2834
/// </summary>

src/Nest/Search/Search/Profile/ShardProfile.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@ public class ShardProfile
1212
public IReadOnlyCollection<SearchProfile> Searches { get; internal set; } =
1313
EmptyReadOnly<SearchProfile>.Collection;
1414

15+
[JsonProperty("aggregations")]
16+
public IReadOnlyCollection<AggregationProfile> Aggregations { get; internal set; } =
17+
EmptyReadOnly<AggregationProfile>.Collection;
1518
}
1619
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Elasticsearch.Net;
5+
using FluentAssertions;
6+
using Nest;
7+
using Tests.Framework;
8+
using Tests.Framework.Integration;
9+
using Tests.Framework.MockData;
10+
11+
namespace Tests.Search.Search
12+
{
13+
public class SearchProfileApiTests : ApiIntegrationTestBase<ReadOnlyCluster, ISearchResponse<Project>, ISearchRequest,
14+
SearchDescriptor<Project>, SearchRequest<Project>>
15+
{
16+
public SearchProfileApiTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage)
17+
{
18+
}
19+
20+
protected override LazyResponses ClientUsage() => Calls(
21+
fluent: (c, f) => c.Search(f),
22+
fluentAsync: (c, f) => c.SearchAsync(f),
23+
request: (c, r) => c.Search<Project>(r),
24+
requestAsync: (c, r) => c.SearchAsync<Project>(r)
25+
);
26+
27+
protected override int ExpectStatusCode => 200;
28+
protected override bool ExpectIsValid => true;
29+
protected override HttpMethod HttpMethod => HttpMethod.POST;
30+
protected override string UrlPath => $"/project/project/_search";
31+
32+
protected override object ExpectJson => new
33+
{
34+
profile = true,
35+
query = new
36+
{
37+
match_all = new { }
38+
},
39+
aggs = new
40+
{
41+
startDates = new
42+
{
43+
terms = new
44+
{
45+
field = "startedOn"
46+
}
47+
}
48+
}
49+
};
50+
51+
protected override void ExpectResponse(ISearchResponse<Project> response)
52+
{
53+
response.Hits.Count().Should().BeGreaterThan(0);
54+
var profile = response.Profile;
55+
profile.Should().NotBeNull();
56+
var shardProfiles = profile.Shards;
57+
shardProfiles.Should().NotBeNullOrEmpty();
58+
foreach (var shardProfile in shardProfiles)
59+
{
60+
shardProfile.Id.Should().NotBeNullOrEmpty();
61+
var searches = shardProfile.Searches;
62+
searches.Should().NotBeNullOrEmpty();
63+
foreach (var search in searches)
64+
{
65+
var queries = search.Query;
66+
queries.Should().NotBeNullOrEmpty();
67+
foreach (var query in queries)
68+
{
69+
query.Should().NotBeNull();
70+
query.Type.Should().NotBeNullOrEmpty();
71+
query.Description.Should().NotBeNullOrEmpty();
72+
query.Time.Should().NotBeNull();
73+
query.TimeInNanoseconds.Should().BeGreaterThan(0);
74+
query.Breakdown.Should().NotBeNull();
75+
}
76+
search.RewriteTime.Should().BeGreaterThan(0);
77+
var collectors = search.Collector;
78+
foreach (var collector in collectors)
79+
{
80+
collector.Name.Should().NotBeNullOrEmpty();
81+
collector.Reason.Should().NotBeNullOrEmpty();
82+
collector.Time.Should().NotBeNull();
83+
collector.TimeInNanoseconds.Should().BeGreaterThan(0);
84+
var children = collector.Children;
85+
children.Should().NotBeNull();
86+
foreach (var child in children)
87+
{
88+
child.Should().NotBeNull();
89+
child.Name.Should().NotBeNullOrEmpty();
90+
child.Reason.Should().NotBeNullOrEmpty();
91+
child.Time.Should().NotBeNull();
92+
child.TimeInNanoseconds.Should().BeGreaterThan(0);
93+
var grandchildren = child.Children;
94+
grandchildren.Should().NotBeNull();
95+
foreach (var grandchild in grandchildren)
96+
{
97+
grandchild.Name.Should().NotBeNullOrEmpty();
98+
grandchild.Reason.Should().NotBeNullOrEmpty();
99+
grandchild.Time.Should().NotBeNull();
100+
grandchild.TimeInNanoseconds.Should().BeGreaterThan(0);
101+
}
102+
}
103+
}
104+
}
105+
var aggregations = shardProfile.Aggregations;
106+
aggregations.Should().NotBeNull();
107+
foreach (var aggregation in aggregations)
108+
{
109+
aggregation.Should().NotBeNull();
110+
aggregation.Type.Should().NotBeNullOrEmpty();
111+
aggregation.Description.Should().NotBeNullOrEmpty();
112+
aggregation.Time.Should().NotBeNull();
113+
aggregation.TimeInNanoseconds.Should().BeGreaterThan(0);
114+
aggregation.Breakdown.Should().NotBeNull();
115+
}
116+
}
117+
}
118+
119+
protected override Func<SearchDescriptor<Project>, ISearchRequest> Fluent => s => s
120+
.Profile()
121+
.Query(q => q
122+
.MatchAll()
123+
)
124+
.Aggregations(aggs => aggs
125+
.Terms("startDates", t => t
126+
.Field(p => p.StartedOn)
127+
)
128+
);
129+
130+
protected override SearchRequest<Project> Initializer => new SearchRequest<Project>()
131+
{
132+
Profile = true,
133+
Query = new QueryContainer(new MatchAllQuery()),
134+
Aggregations = new TermsAggregation("startDates")
135+
{
136+
Field = "startedOn"
137+
}
138+
};
139+
}
140+
}

src/Tests/Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@
721721
<Compile Include="Search\Scroll\Scroll\SlicedScrollSearchApiTests.cs" />
722722
<Compile Include="Search\Search\InvalidSearchApiTests.cs" />
723723
<Compile Include="Search\Search\Rescoring\RescoreUsageTests.cs" />
724+
<Compile Include="Search\Search\SearchProfileApiTests.cs" />
724725
<Compile Include="Search\Search\SearchProfileTests.cs" />
725726
<Compile Include="Search\Suggesters\SuggestUrlTests.cs" />
726727
<Compile Include="XPack\Security\ClearCachedRealms\ClearCachedRealmsApiTests.cs" />

src/Tests/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
mode: m
33
# the elasticsearch version that should be started
44
# Can be a snapshot version of sonatype or "latest" to get the latest snapshot of sonatype
5-
elasticsearch_version: latest
5+
elasticsearch_version: 5.3.0-SNAPSHOT
66
# cluster filter allows you to only run the integration tests of a particular cluster (cluster suffix not needed)
77
# cluster_filter:
88
# whether we want to forcefully reseed on the node, if you are starting the tests with a node already running

0 commit comments

Comments
 (0)