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 .stub .StreamObserver ;
8
23
import io .micrometer .core .instrument .MeterRegistry ;
9
24
import io .micrometer .core .instrument .Tag ;
25
+ import io .micrometer .core .instrument .Tags ;
10
26
import io .micrometer .core .instrument .Timer ;
11
- import io .micrometer .core .instrument .simple . SimpleConfig ;
27
+ import io .micrometer .core .instrument .search . MeterNotFoundException ;
12
28
import io .micrometer .prometheus .PrometheusConfig ;
13
29
import org .awaitility .Awaitility ;
14
30
import org .junit .Before ;
31
+ import org .junit .Test ;
15
32
import org .junit .runner .RunWith ;
16
33
import org .lognet .springboot .grpc .autoconfigure .metrics .RequestAwareGRpcMetricsTagsContributor ;
17
34
import org .lognet .springboot .grpc .context .LocalRunningGrpcPort ;
26
43
import org .springframework .test .context .ActiveProfiles ;
27
44
import org .springframework .test .context .junit4 .SpringRunner ;
28
45
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
46
@ RunWith (SpringRunner .class )
41
47
@ SpringBootTest (classes = {DemoApp .class }, webEnvironment = NONE , properties = {"grpc.port=0" })
42
48
@ ActiveProfiles ("measure" )
@@ -48,7 +54,7 @@ static class Config{
48
54
public RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .HelloRequest > helloContributor (){
49
55
return new RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .HelloRequest >(GreeterOuterClass .HelloRequest .class ) {
50
56
@ Override
51
- public Iterable <Tag > getTags (GreeterOuterClass .HelloRequest request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
57
+ public Iterable <Tag > addTags (GreeterOuterClass .HelloRequest request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes , Tags tags ) {
52
58
return Collections .singletonList (Tag .of ("hello" ,request .getName ()));
53
59
}
54
60
@@ -62,7 +68,7 @@ public Iterable<Tag> getTags(Status status, MethodDescriptor<?, ?> methodDescrip
62
68
public RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .Person > shouldNotBeInvoked (){
63
69
return new RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .Person >(GreeterOuterClass .Person .class ) {
64
70
@ Override
65
- public Iterable <Tag > getTags (GreeterOuterClass .Person request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
71
+ public Iterable <Tag > addTags (GreeterOuterClass .Person request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes , Tags tags ) {
66
72
return Collections .emptyList ();
67
73
}
68
74
@@ -72,6 +78,26 @@ public Iterable<Tag> getTags(Status status, MethodDescriptor<?, ?> methodDescrip
72
78
}
73
79
};
74
80
}
81
+
82
+ @ Bean
83
+ public RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .HelloRequest > multiHelloContributor () {
84
+ return new RequestAwareGRpcMetricsTagsContributor <GreeterOuterClass .HelloRequest >(GreeterOuterClass .HelloRequest .class , BIDI_STREAMING ) {
85
+ @ Override
86
+ public Tags addTags (GreeterOuterClass .HelloRequest request , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes , Tags existingTags ) {
87
+ String existingTag = existingTags .stream ()
88
+ .filter (tag -> tag .getKey ().equals ("many-hellos" ))
89
+ .findAny ()
90
+ .map (Tag ::getValue )
91
+ .orElse ("" );
92
+ return Tags .of ("many-hellos" , existingTag .isEmpty () ? request .getName () : existingTag + ", " + request .getName ());
93
+ }
94
+
95
+ @ Override
96
+ public Iterable <Tag > getTags (Status status , MethodDescriptor <?, ?> methodDescriptor , Attributes attributes ) {
97
+ return Collections .singletonList (Tag .of ("endTag" , status .getCode ().name ()));
98
+ }
99
+ };
100
+ }
75
101
}
76
102
77
103
@ SpyBean
@@ -131,10 +157,41 @@ protected void afterGreeting() {
131
157
132
158
Mockito .verify (shouldNotBeInvoked ,Mockito .times (1 )).getTags (Mockito .any (Status .class ),Mockito .any (),Mockito .any ());
133
159
Mockito .verify (shouldNotBeInvoked ,Mockito .never ()).getTags (Mockito .any (GreeterOuterClass .Person .class ),Mockito .any (),Mockito .any ());
160
+ Mockito .verify (shouldNotBeInvoked , Mockito .never ())
161
+ .addTags (Mockito .any (GreeterOuterClass .Person .class ), Mockito .any (), Mockito .any (), Mockito .any ());
162
+ }
134
163
164
+ @ Test
165
+ public void tagsForStream () {
166
+ final GreeterGrpc .GreeterStub greeterFutureStub = GreeterGrpc .newStub (selectedChanel );
167
+ io .grpc .stub .StreamObserver <GreeterOuterClass .HelloRequest > helloInput =
168
+ greeterFutureStub .sayManyHellos (new StreamObserver <GreeterOuterClass .HelloReply >() {
169
+ @ Override
170
+ public void onNext (GreeterOuterClass .HelloReply value ) {}
135
171
172
+ @ Override
173
+ public void onError (Throwable t ) {}
136
174
137
-
138
-
175
+ @ Override
176
+ public void onCompleted () {}
177
+ });
178
+ Arrays .asList ("a" , "b" , "c" , "d" ).stream ()
179
+ .map (name -> GreeterOuterClass .HelloRequest .newBuilder ().setName (name ).build ())
180
+ .forEach (helloInput ::onNext );
181
+ helloInput .onCompleted ();
182
+
183
+ final Timer timer = Awaitility
184
+ .waitAtMost (Duration .ofMillis (registryConfig .step ().toMillis () * 2 ))
185
+ .ignoreExceptionsInstanceOf (MeterNotFoundException .class )
186
+ .until (
187
+ () -> registry .get ("grpc.server.calls" )
188
+ .tags ("method" , "Greeter/SayManyHellos" )
189
+ .timer (),
190
+ Objects ::nonNull
191
+ );
192
+
193
+ assertThat (timer .totalTime (TimeUnit .MILLISECONDS ), greaterThan (0d ));
194
+ assertThat (timer .getId ().getTag ("many-hellos" ), is ("a, b, c, d" ));
195
+ assertThat (timer .getId ().getTag ("endTag" ), is ("OK" ));
139
196
}
140
197
}
0 commit comments