2121import com .sun .net .httpserver .HttpServer ;
2222import java .net .InetSocketAddress ;
2323import java .time .Duration ;
24+ import java .util .Collection ;
2425import java .util .Map ;
26+ import java .util .concurrent .CompletionStage ;
27+ import java .util .concurrent .ConcurrentLinkedQueue ;
2528import java .util .concurrent .TimeUnit ;
2629import java .util .function .Function ;
30+ import java .util .function .Supplier ;
31+ import java .util .stream .Collectors ;
2732import org .astraea .app .argument .DurationField ;
2833import org .astraea .app .argument .IntegerMapField ;
2934import org .astraea .app .argument .NonNegativeIntegerField ;
3035import org .astraea .common .Utils ;
3136import org .astraea .common .admin .Admin ;
37+ import org .astraea .common .admin .NodeInfo ;
38+ import org .astraea .common .metrics .MBeanClient ;
39+ import org .astraea .common .metrics .collector .MetricSensor ;
40+ import org .astraea .common .metrics .collector .MetricStore ;
3241
3342public class WebService implements AutoCloseable {
3443
3544 private final HttpServer server ;
3645 private final Admin admin ;
46+ private final Sensors sensors = new Sensors ();
3747
38- public WebService (Admin admin , int port , Function <Integer , Integer > brokerIdToJmxPort ) {
48+ public WebService (
49+ Admin admin ,
50+ int port ,
51+ Function <Integer , Integer > brokerIdToJmxPort ,
52+ Duration beanExpiration ) {
3953 this .admin = admin ;
54+ Supplier <CompletionStage <Map <Integer , MBeanClient >>> clientSupplier =
55+ () ->
56+ admin
57+ .brokers ()
58+ .thenApply (
59+ brokers ->
60+ brokers .stream ()
61+ .collect (
62+ Collectors .toUnmodifiableMap (
63+ NodeInfo ::id ,
64+ b ->
65+ MBeanClient .jndi (
66+ b .host (), brokerIdToJmxPort .apply (b .id ())))));
67+ var metricStore =
68+ MetricStore .builder ()
69+ .beanExpiration (beanExpiration )
70+ .localReceiver (clientSupplier )
71+ .sensorsSupplier (
72+ () ->
73+ sensors .metricSensors ().stream ()
74+ .distinct ()
75+ .collect (
76+ Collectors .toUnmodifiableMap (
77+ Function .identity (), ignored -> (id , ee ) -> {})))
78+ .build ();
4079 server = Utils .packException (() -> HttpServer .create (new InetSocketAddress (port ), 0 ));
4180 server .createContext ("/topics" , to (new TopicHandler (admin )));
4281 server .createContext ("/groups" , to (new GroupHandler (admin )));
@@ -45,9 +84,10 @@ public WebService(Admin admin, int port, Function<Integer, Integer> brokerIdToJm
4584 server .createContext ("/quotas" , to (new QuotaHandler (admin )));
4685 server .createContext ("/transactions" , to (new TransactionHandler (admin )));
4786 server .createContext ("/beans" , to (new BeanHandler (admin , brokerIdToJmxPort )));
87+ server .createContext ("/sensors" , to (new SensorHandler (sensors )));
4888 server .createContext ("/records" , to (new RecordHandler (admin )));
4989 server .createContext ("/reassignments" , to (new ReassignmentHandler (admin )));
50- server .createContext ("/balancer" , to (new BalancerHandler (admin , brokerIdToJmxPort )));
90+ server .createContext ("/balancer" , to (new BalancerHandler (admin , metricStore )));
5191 server .createContext ("/throttles" , to (new ThrottleHandler (admin )));
5292 server .start ();
5393 }
@@ -64,7 +104,9 @@ public void close() {
64104
65105 public static void main (String [] args ) throws Exception {
66106 var arg = org .astraea .app .argument .Argument .parse (new Argument (), args );
67- try (var service = new WebService (Admin .of (arg .configs ()), arg .port , arg ::jmxPortMapping )) {
107+ try (var service =
108+ new WebService (
109+ Admin .of (arg .configs ()), arg .port , arg ::jmxPortMapping , arg .beanExpiration )) {
68110 if (arg .ttl == null ) {
69111 System .out .println ("enter ctrl + c to terminate web service" );
70112 TimeUnit .MILLISECONDS .sleep (Long .MAX_VALUE );
@@ -118,5 +160,32 @@ int jmxPortMapping(int brokerId) {
118160 validateWith = DurationField .class ,
119161 converter = DurationField .class )
120162 Duration ttl = null ;
163+
164+ @ Parameter (
165+ names = {"--bean.expiration" },
166+ description = "Duration: the life of collected metrics" ,
167+ validateWith = DurationField .class ,
168+ converter = DurationField .class )
169+ Duration beanExpiration = Duration .ofHours (1 );
170+ }
171+
172+ static class Sensors {
173+ private final Collection <MetricSensor > sensors ;
174+
175+ Sensors () {
176+ sensors = new ConcurrentLinkedQueue <>();
177+ }
178+
179+ Collection <MetricSensor > metricSensors () {
180+ return sensors ;
181+ }
182+
183+ void clearSensors () {
184+ sensors .clear ();
185+ }
186+
187+ void addSensors (MetricSensor metricSensor ) {
188+ sensors .add (metricSensor );
189+ }
121190 }
122191}
0 commit comments