25
25
import io .swagger .annotations .ApiParam ;
26
26
import io .swagger .annotations .ApiResponse ;
27
27
import io .swagger .annotations .ApiResponses ;
28
+ import java .io .IOException ;
28
29
import java .util .List ;
29
30
import java .util .Map ;
30
31
import java .util .Optional ;
31
32
import java .util .Set ;
33
+ import javax .servlet .AsyncContext ;
34
+ import javax .servlet .ServletOutputStream ;
35
+ import javax .servlet .WriteListener ;
36
+ import javax .servlet .http .HttpServletRequest ;
32
37
import javax .ws .rs .DELETE ;
33
38
import javax .ws .rs .DefaultValue ;
34
39
import javax .ws .rs .Encoded ;
42
47
import javax .ws .rs .WebApplicationException ;
43
48
import javax .ws .rs .container .AsyncResponse ;
44
49
import javax .ws .rs .container .Suspended ;
50
+ import javax .ws .rs .core .Context ;
45
51
import javax .ws .rs .core .MediaType ;
46
52
import javax .ws .rs .core .Response ;
47
53
import org .apache .bookkeeper .mledger .Position ;
83
89
import org .apache .pulsar .common .policies .data .stats .PartitionedTopicStatsImpl ;
84
90
import org .apache .pulsar .common .util .Codec ;
85
91
import org .apache .pulsar .common .util .FutureUtil ;
92
+ import org .apache .pulsar .common .util .ObjectMapperFactory ;
86
93
import org .apache .pulsar .metadata .api .MetadataStoreException ;
87
94
import org .slf4j .Logger ;
88
95
import org .slf4j .LoggerFactory ;
@@ -1215,6 +1222,8 @@ public void getStats(
1215
1222
});
1216
1223
}
1217
1224
1225
+ @ Context HttpServletRequest servletRequest ;
1226
+
1218
1227
@ GET
1219
1228
@ Path ("{tenant}/{namespace}/{topic}/internalStats" )
1220
1229
@ ApiOperation (value = "Get the internal stats for the topic." , response = PersistentTopicInternalStats .class )
@@ -1239,7 +1248,46 @@ public void getInternalStats(
1239
1248
@ QueryParam ("metadata" ) @ DefaultValue ("false" ) boolean metadata ) {
1240
1249
validateTopicName (tenant , namespace , encodedTopic );
1241
1250
internalGetInternalStatsAsync (authoritative , metadata )
1242
- .thenAccept (asyncResponse ::resume )
1251
+ .thenAccept (stats -> {
1252
+ final AsyncContext asyncContext = servletRequest .getAsyncContext ();
1253
+ final ServletOutputStream s ;
1254
+ try {
1255
+ s = asyncContext .getResponse ().getOutputStream ();
1256
+ } catch (IOException e ) {
1257
+ log .error ("Cannot get the outputstream to write the response" , e );
1258
+ resumeAsyncResponseExceptionally (asyncResponse , e );
1259
+ return ;
1260
+ }
1261
+ s .setWriteListener (new WriteListener () {
1262
+
1263
+ public void onWritePossible () throws IOException {
1264
+ log .info ("Serializing internal stats for topic {} to outputstream" , topicName );
1265
+ if (!s .isReady ()) {
1266
+ return ;
1267
+ }
1268
+ byte [] asArray = ObjectMapperFactory .getMapper ().getObjectMapper ().writeValueAsBytes (stats );
1269
+ s .write (asArray );
1270
+ if (!s .isReady ()) {
1271
+ return ;
1272
+ }
1273
+ s .close ();
1274
+ if (!s .isReady ()) {
1275
+ return ;
1276
+ }
1277
+ asyncContext .complete ();
1278
+ log .info ("Finished writing internal stats for topic {} to outputstream" , topicName );
1279
+
1280
+ }
1281
+
1282
+ @ Override
1283
+ public void onError (Throwable ex ) {
1284
+ if (isNot307And404Exception (ex )) {
1285
+ log .error ("[{}] Failed to server internal stats for topic {}" ,
1286
+ clientAppId (), topicName , ex );
1287
+ }
1288
+ }
1289
+ });
1290
+ })
1243
1291
.exceptionally (ex -> {
1244
1292
if (isNot307And404Exception (ex )) {
1245
1293
log .error ("[{}] Failed to get internal stats for topic {}" , clientAppId (), topicName , ex );
0 commit comments