1
1
package org .lognet .springboot .grpc ;
2
2
3
+ import static io .grpc .MethodDescriptor .MethodType .BIDI_STREAMING ;
4
+ import static org .hamcrest .MatcherAssert .assertThat ;
5
+ import static org .hamcrest .Matchers .containsString ;
6
+ import static org .hamcrest .Matchers .greaterThan ;
7
+ import static org .hamcrest .Matchers .is ;
8
+ import static org .hamcrest .Matchers .notNullValue ;
9
+ import static org .springframework .boot .test .context .SpringBootTest .WebEnvironment .NONE ;
10
+
11
+ import java .time .Duration ;
12
+ import java .util .Arrays ;
13
+ import java .util .Collections ;
14
+ import java .util .Objects ;
15
+ import java .util .concurrent .TimeUnit ;
16
+
3
17
import io .grpc .Attributes ;
4
18
import io .grpc .MethodDescriptor ;
5
19
import io .grpc .Status ;
6
20
import io .grpc .examples .GreeterGrpc ;
7
21
import io .grpc .examples .GreeterOuterClass ;
22
+ import io .grpc .examples .GreeterOuterClass .HelloRequest ;
23
+ import io .grpc .stub .StreamObserver ;
8
24
import io .micrometer .core .instrument .MeterRegistry ;
9
25
import io .micrometer .core .instrument .Tag ;
26
+ import io .micrometer .core .instrument .Tags ;
10
27
import io .micrometer .core .instrument .Timer ;
11
- import io .micrometer .core .instrument .simple . SimpleConfig ;
28
+ import io .micrometer .core .instrument .search . MeterNotFoundException ;
12
29
import io .micrometer .prometheus .PrometheusConfig ;
13
30
import org .awaitility .Awaitility ;
14
31
import org .junit .Before ;
32
+ import org .junit .Test ;
15
33
import org .junit .runner .RunWith ;
16
34
import org .lognet .springboot .grpc .autoconfigure .metrics .RequestAwareGRpcMetricsTagsContributor ;
17
35
import org .lognet .springboot .grpc .context .LocalRunningGrpcPort ;
26
44
import org .springframework .test .context .ActiveProfiles ;
27
45
import org .springframework .test .context .junit4 .SpringRunner ;
28
46
29
- import java .time .Duration ;
30
- import java .util .Collections ;
31
- import java .util .concurrent .TimeUnit ;
32
-
33
- import static org .hamcrest .MatcherAssert .assertThat ;
34
- import static org .hamcrest .Matchers .containsString ;
35
- import static org .hamcrest .Matchers .greaterThan ;
36
- import static org .hamcrest .Matchers .is ;
37
- import static org .hamcrest .Matchers .notNullValue ;
38
- import static org .springframework .boot .test .context .SpringBootTest .WebEnvironment .NONE ;
39
-
40
47
@ RunWith (SpringRunner .class )
41
48
@ SpringBootTest (classes = {DemoApp .class }, webEnvironment = NONE , properties = {"grpc.port=0" })
42
49
@ ActiveProfiles ("measure" )
43
50
@ Import (GrpcMeterTest .Config .class )
44
51
public class GrpcMeterTest extends GrpcServerTestBase {
45
52
@ TestConfiguration
46
- static class Config {
53
+ static class Config {
47
54
@ Bean
48
- public RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass . HelloRequest > helloContributor (){
49
- return new RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass . HelloRequest >(GreeterOuterClass . HelloRequest .class ) {
55
+ public RequestAwareGRpcMetricsTagsContributor <HelloRequest > helloContributor () {
56
+ return new RequestAwareGRpcMetricsTagsContributor <HelloRequest >(HelloRequest .class ) {
50
57
@ Override
51
- public Iterable <Tag > getTags (GreeterOuterClass . HelloRequest request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
52
- return Collections .singletonList (Tag .of ("hello" ,request .getName ()));
58
+ public Iterable <Tag > getTags (HelloRequest request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
59
+ return Collections .singletonList (Tag .of ("hello" , request .getName ()));
53
60
}
54
61
55
62
@ Override
56
63
public Iterable <Tag > getTags (Status status , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
57
- return Collections .singletonList (Tag .of ("customTagName" ,status .getCode ().name ()));
64
+ return Collections .singletonList (Tag .of ("customTagName" , status .getCode ().name ()));
58
65
}
59
66
};
60
67
}
68
+
61
69
@ Bean
62
- public RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .Person > shouldNotBeInvoked (){
70
+ public RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .Person > shouldNotBeInvoked () {
63
71
return new RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .Person >(GreeterOuterClass .Person .class ) {
64
72
@ Override
65
- public Iterable <Tag > getTags (GreeterOuterClass .Person request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
73
+ public Iterable <Tag > getTags (
74
+ GreeterOuterClass .Person request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes
75
+ ) {
66
76
return Collections .emptyList ();
67
77
}
68
78
@@ -72,6 +82,28 @@ public Iterable<Tag> getTags(Status status, MethodDescriptor<?, ?> methodDescrip
72
82
}
73
83
};
74
84
}
85
+
86
+ @ Bean
87
+ public RequestAwareGRpcMetricsTagsContributor <HelloRequest > multiHelloContributor () {
88
+ return new RequestAwareGRpcMetricsTagsContributor <HelloRequest >(HelloRequest .class , BIDI_STREAMING ) {
89
+ @ Override
90
+ public Tags getTags (
91
+ HelloRequest request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes , Tags existingTags
92
+ ) {
93
+ String existingTag = existingTags .stream ()
94
+ .filter (tag -> tag .getKey ().equals ("many-hellos" ))
95
+ .findAny ()
96
+ .map (Tag ::getValue )
97
+ .orElse ("" );
98
+ return Tags .of ("many-hellos" , existingTag .isEmpty () ? request .getName () : existingTag + ", " + request .getName ());
99
+ }
100
+
101
+ @ Override
102
+ public Iterable <Tag > getTags (Status status , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
103
+ return Collections .singletonList (Tag .of ("endTag" , status .getCode ().name ()));
104
+ }
105
+ };
106
+ }
75
107
}
76
108
77
109
@ SpyBean
@@ -87,54 +119,84 @@ public Iterable<Tag> getTags(Status status, MethodDescriptor<?, ?> methodDescrip
87
119
private PrometheusConfig registryConfig ;
88
120
89
121
@ Before
90
- public void setUp () {
122
+ public void setUp () {
91
123
registry .clear ();
92
124
}
93
125
94
126
@ Override
95
- protected void afterGreeting () {
96
-
97
-
127
+ protected void afterGreeting () {
98
128
final Timer timer = registry .find ("grpc.server.calls" ).timer ();
99
- assertThat (timer ,notNullValue (Timer .class ));
129
+ assertThat (timer , notNullValue (Timer .class ));
100
130
101
131
Awaitility
102
- .waitAtMost (Duration .ofMillis (registryConfig .step ().toMillis () * 2 ))
103
- .until (timer ::count ,greaterThan (0L ));
132
+ .waitAtMost (Duration .ofMillis (registryConfig .step ().toMillis () * 2 ))
133
+ .until (timer ::count , greaterThan (0L ));
104
134
105
- assertThat (timer .max (TimeUnit .MILLISECONDS ),greaterThan (0d ));
106
- assertThat (timer .mean (TimeUnit .MILLISECONDS ),greaterThan (0d ));
107
- assertThat (timer .totalTime (TimeUnit .MILLISECONDS ),greaterThan (0d ));
135
+ assertThat (timer .max (TimeUnit .MILLISECONDS ), greaterThan (0d ));
136
+ assertThat (timer .mean (TimeUnit .MILLISECONDS ), greaterThan (0d ));
137
+ assertThat (timer .totalTime (TimeUnit .MILLISECONDS ), greaterThan (0d ));
108
138
109
139
110
140
final String addressTag = timer .getId ().getTag ("address" );
111
- assertThat (addressTag ,notNullValue ());
112
- assertThat (addressTag ,containsString (String .valueOf (port )));
141
+ assertThat (addressTag , notNullValue ());
142
+ assertThat (addressTag , containsString (String .valueOf (port )));
113
143
114
144
final String methodTag = timer .getId ().getTag ("method" );
115
- assertThat (methodTag ,notNullValue ());
116
- assertThat (methodTag ,is (GreeterGrpc .getSayHelloMethod ().getFullMethodName ()));
145
+ assertThat (methodTag , notNullValue ());
146
+ assertThat (methodTag , is (GreeterGrpc .getSayHelloMethod ().getFullMethodName ()));
117
147
118
148
final String resultTag = timer .getId ().getTag ("result" );
119
- assertThat (resultTag ,notNullValue ());
120
- assertThat (resultTag ,is (Status .OK .getCode ().name ()));
149
+ assertThat (resultTag , notNullValue ());
150
+ assertThat (resultTag , is (Status .OK .getCode ().name ()));
121
151
122
152
//from contributor
123
153
124
154
final String helloTag = timer .getId ().getTag ("hello" );
125
- assertThat (helloTag ,notNullValue ());
126
- assertThat (helloTag ,is (name ));
155
+ assertThat (helloTag , notNullValue ());
156
+ assertThat (helloTag , is (name ));
127
157
128
158
final String customTag = timer .getId ().getTag ("customTagName" );
129
- assertThat (customTag ,notNullValue ());
130
- assertThat (customTag ,is (Status .OK .getCode ().name ()));
131
-
132
- Mockito .verify (shouldNotBeInvoked ,Mockito .times (1 )).getTags (Mockito .any (Status .class ),Mockito .any (),Mockito .any ());
133
- Mockito .verify (shouldNotBeInvoked ,Mockito .never ()).getTags (Mockito .any (GreeterOuterClass .Person .class ),Mockito .any (),Mockito .any ());
134
-
135
-
159
+ assertThat (customTag , notNullValue ());
160
+ assertThat (customTag , is (Status .OK .getCode ().name ()));
161
+
162
+ Mockito .verify (shouldNotBeInvoked , Mockito .times (1 )).getTags (Mockito .any (Status .class ), Mockito .any (), Mockito .any ());
163
+ Mockito .verify (shouldNotBeInvoked , Mockito .never ())
164
+ .getTags (Mockito .any (GreeterOuterClass .Person .class ), Mockito .any (), Mockito .any ());
165
+ Mockito .verify (shouldNotBeInvoked , Mockito .never ())
166
+ .getTags (Mockito .any (GreeterOuterClass .Person .class ), Mockito .any (), Mockito .any (), Mockito .any ());
167
+ }
136
168
169
+ @ Test
170
+ public void tagsForStream () {
171
+ final GreeterGrpc .GreeterStub greeterFutureStub = GreeterGrpc .newStub (selectedChanel );
172
+ io .grpc .stub .StreamObserver <HelloRequest > helloInput =
173
+ greeterFutureStub .sayManyHellos (new StreamObserver <GreeterOuterClass .HelloReply >() {
174
+ @ Override
175
+ public void onNext (GreeterOuterClass .HelloReply value ) {}
137
176
177
+ @ Override
178
+ public void onError (Throwable t ) {}
138
179
180
+ @ Override
181
+ public void onCompleted () {}
182
+ });
183
+ Arrays .asList ("a" , "b" , "c" , "d" ).stream ()
184
+ .map (name -> HelloRequest .newBuilder ().setName (name ).build ())
185
+ .forEach (helloInput ::onNext );
186
+ helloInput .onCompleted ();
187
+
188
+ final Timer timer = Awaitility
189
+ .waitAtMost (Duration .ofMillis (registryConfig .step ().toMillis () * 2 ))
190
+ .ignoreExceptionsInstanceOf (MeterNotFoundException .class )
191
+ .until (
192
+ () -> registry .get ("grpc.server.calls" )
193
+ .tags ("method" , "Greeter/SayManyHellos" )
194
+ .timer (),
195
+ Objects ::nonNull
196
+ );
197
+
198
+ assertThat (timer .totalTime (TimeUnit .MILLISECONDS ), greaterThan (0d ));
199
+ assertThat (timer .getId ().getTag ("many-hellos" ), is ("a, b, c, d" ));
200
+ assertThat (timer .getId ().getTag ("endTag" ), is ("OK" ));
139
201
}
140
202
}
0 commit comments