A tavaszi REST API mutatói

REST felső

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

Ebben az oktatóanyagban integrálunk alapmutatók a Spring REST API-ba.

A metrikus funkcionalitást először egyszerű Servlet szűrőkkel, majd egy rugós indító működtetővel építjük ki.

2. A web.xml

Kezdjük egy szűrő regisztrálásával -MetricFilter" - ba,-be web.xml az alkalmazásunk:

 metricFilter org.baeldung.web.metric.MetricFilter metricFilter / * 

Vegye figyelembe, hogyan térképezzük fel a szűrőt az összes beérkező kérelem lefedésére - “/*” - ami természetesen teljesen konfigurálható.

3. A Servlet szűrő

Most - hozzuk létre az egyéni szűrőnket:

public class MetricFilter implementálja a Filter {private MetricService metricService; A @Orride public void init (FilterConfig config) ServletException dobja {metricService = (MetricService) WebApplicationContextUtils .getRequiredWebApplicationContext (config.getServletContext ()) .getBean ("metricService"); } @Orride public void doFilter (ServletRequest kérés, ServletResponse válasz, FilterChain lánc) dobja a java.io.IOException, ServletException {HttpServletRequest httpRequest = ((HttpServletRequest) kérelmet); Karakterlánc req = httpRequest.getMethod () + "" + httpRequest.getRequestURI (); chain.doFilter (kérés, válasz); int állapot = ((HttpServletResponse) válasz) .getStatus (); metricService.increaseCount (igény, állapot); }}

Mivel a szűrő nem szabványos bab, nem fogjuk beadni a szűrőt metricService hanem ehelyett manuálisan töltse le - a ServletContext.

Vegye figyelembe azt is, hogy a. Hívásával folytatjuk a szűrőlánc végrehajtását doFilter API itt.

4. Metrikus - Állapotkódszámok

Következő - vessünk egy pillantást egyszerű MetricService:

@Service public class MetricService {private ConcurrentMap statusMetric; public MetricService () {statusMetric = new ConcurrentHashMap (); } public void growthCount (String kérés, int állapot) {Integer statusCount = statusMetric.get (status); if (statusCount == null) {statusMetric.put (status, 1); } else {statusMetric.put (status, statusCount + 1); }} public térkép getStatusMetric () {return statusMetric; }}

Egy memóriát használunk ConcurrentMap hogy tartsa a HTTP állapotkód-típusok számát.

Most - ennek az alapvető mutatónak a megjelenítéséhez - feltérképezzük a Vezérlő módszer:

@RequestMapping (value = "/ status-metric", method = RequestMethod.GET) @ResponseBody public Map getStatusMetric () {return metricService.getStatusMetric (); }

És itt van egy minta válasz:

{ "404":1, "200":6, "409":1 }

5. Metrikus - állapotkódok kérés szerint

Következő - rögzítsük a kérelmek szerinti számlálások mutatóit:

@Service nyilvános osztály MetricService {private ConcurrentMap metricMap; public void growthCount (String kérés, int állapot) {ConcurrentHashMap statusMap = metricMap.get (kérés); if (statusMap == null) {statusMap = új ConcurrentHashMap (); } Egész szám = statusMap.get (status); if (count == null) {count = 1; } else {count ++; } statusMap.put (status, count); metricMap.put (kérés, statusMap); } public térkép getFullMetric () {return metricMap; }}

A mutató eredményeit az API-n keresztül jelenítjük meg:

@RequestMapping (value = "/ metric", method = RequestMethod.GET) @ResponseBody public Map getMetric () {return metricService.getFullMetric (); }

Így néznek ki ezek a mutatók:

{"GET / felhasználók": {"200": 6, "409": 1}, "GET / felhasználók / 1": {"404": 1}}

A fenti példa szerint az API-nak a következő tevékenysége volt:

  • „7” kéri a „GET / felhasználók
  • Közülük „6” „200” állapotkód-választ adott, és csak egy a „409” állapotkódot

6. Metrikus - idősoros adatok

Az összesítés némileg hasznos egy alkalmazásban, de ha a rendszer jelentős ideig működik - nehéz megmondani, hogy ezek a mutatók valójában mit jelentenek.

Szüksége van az idő kontextusára, hogy az adatok értelmesek és könnyen értelmezhetők legyenek.

Készítsünk most egy egyszerű időalapú mutatót; nyilvántartást vezetünk az állapotkód percenkénti számáról - az alábbiak szerint:

@Service nyilvános osztály MetricService {private ConcurrentMap timeMap; privát statikus SimpleDateFormat dateFormat = új SimpleDateFormat ("éééé-hh-nn HH: mm"); public void growthCount (String kérés, int állapot) {String time = dateFormat.format (új Date ()); ConcurrentHashMap statusMap = timeMap.get (idő); if (statusMap == null) {statusMap = új ConcurrentHashMap (); } Egész szám = statusMap.get (status); if (count == null) {count = 1; } else {count ++; } statusMap.put (status, count); timeMap.put (idő, statusMap); }}

És a getGraphData ():

public Object [] [] getGraphData () {int colCount = statusMetric.keySet (). size () + 1; Set allStatus = statusMetric.keySet (); int rowCount = timeMap.keySet (). size () + 1; Object [] [] eredmény = new Object [rowCount] [colCount]; eredmény [0] [0] = "Idő"; int j = 1; for (int állapot: allStatus) {eredmény [0] [j] = állapot; j ++; } int i = 1; ConcurrentMap tempMap; a (Belépés bejegyzés: timeMap.entrySet ()) {eredmény [i] [0] = bejegyzés.getKey (); tempMap = entry.getValue (); for (j = 1; j <colCount; j ++) {eredmény [i] [j] = tempMap.get (eredmény [0] [j]); if (eredmény [i] [j] == null) {eredmény [i] [j] = 0; }} i ++; } visszatérési eredmény; }

Ezt most az API-hoz fogjuk feltérképezni:

@RequestMapping (érték = "/ metric-graph-data", módszer = RequestMethod.GET) @ResponseBody nyilvános objektum [] [] getMetricData () {return metricService.getGraphData (); }

És végül - ki fogjuk adni a Google Charts segítségével:

  Metrikus grafikon google.load ("vizualizáció", "1", {csomagok: ["corechart"]}); function drawChart () {$ .get ("/ metric-graph-data", function (mydata) {var data = google.visualization.arrayToDataTable (mydata); var options = {title: 'Webhely metrika', hAxis: {title : 'Time', titleTextStyle: {color: '# 333'}}, vAxis: {minValue: 0}}; var chart = new google.visualization.AreaChart (document.getElementById ('chart_div')); chart.draw ( adatok, opciók);}); } 

7. A Spring Boot 1.x aktor használata

A következő szakaszokban bekapcsolódunk a Spring Boot Actuator funkcióiba, hogy bemutassuk mutatóinkat.

Először - hozzá kell adnunk a működtető függőségét a sajátunkhoz pom.xml:

 org.springframework.boot spring-boot-starter-actuator 

7.1. A MetricFilter

Következő - megfordíthatjuk MetricFilter - tényleges tavaszi babba:

@Component public class MetricFilter implement {Filter {@Autowired private MetricService metricService; @Override public void doFilter (ServletRequest kérés, ServletResponse válasz, FilterChain lánc) dobja a java.io.IOException, ServletException {chain.doFilter (kérés, válasz); int állapot = ((HttpServletResponse) válasz) .getStatus (); metricService.increaseCount (állapot); }}

Ez természetesen egy kisebb egyszerűsítés - de ezt érdemes megtenni, hogy megszabaduljon a függőségek korábban manuálisan bekötött vezetékeitől.

7.2. Használata CounterService

Most használjuk a CounterService az egyes állapotkódok előfordulásainak számlálása:

@Service public class MetricService {@Autowired private CounterService counter; private List statusList; public void growthCount (int állapot) {számláló.növekedés ("állapot." + állapot); if (! statusList.contains ("számláló.állapot." + állapot)) {statusList.add ("számláló.állapot." + állapot); }}}

7.3. Mutatók exportálása MetricRepository

Ezután - exportálnunk kell a mutatókat - a MetricRepository:

@Service public class MetricService {@Autowired private MetricRepository repo; privát lista statusMetric; private List statusList; @Scheduled (fixedDelay = 60000) private void exportMetrics () {Metrikus metrika; ArrayList statusCount = new ArrayList (); for (String status: statusList) {metric = repo.findOne (status); if (metrika! = null) {statusCount.add (metric.getValue (). intValue ()); repo.reset (állapot); } else {statusCount.add (0); }} statusMetric.add (statusCount); }}

Ne feledje, hogy számokat tárolunk állapotkódok percenként.

7.4. Tavaszi csizma PublicMetrics

Használhatjuk a Spring Boot-ot is PublicMetrics a metrikák exportálásához saját szűrők használata helyett - az alábbiak szerint:

Először is megvan az ütemezett feladatunk exportmutatók percenként:

@Autowired private MetricReaderPublicMetrics publicMetrics; privát lista statusMetricsByMinute; private List statusList; privát statikus végleges SimpleDateFormat dateFormat = új SimpleDateFormat ("éééé-hh-nn ÓÓ: mm"); @Scheduled (fixedDelay = 60000) private void exportMetrics () {ArrayList lastMinuteStatuses = initializeStatuses (statusList.size ()); for (Metric counterMetric: publicMetrics.metrics ()) {updateMetrics (counterMetric, lastMinuteStatuses); } statusMetricsByMinute.add (lastMinuteStatuses); }

Természetesen inicializálnunk kell a HTTP állapotkódok listáját:

privát ArrayList initizeStatuses (int méret) {ArrayList counterList = új ArrayList (); for (int i = 0; i <méret; i ++) {counterList.add (0); } return counterList; }

És akkor valóban frissíteni fogjuk a mutatókat állapotkódszám:

private void updateMetrics (Metric counterMetric, ArrayList statusCount) {String status = ""; int index = -1; int oldCount = 0; if (counterMetric.getName (). tartalmazza ("counter.status.")) {status = counterMetric.getName (). szubsztring (15, 18); // 404. példa, 200 appendStatusIfNotExist (status, statusCount); index = statusList.indexOf (állapot); oldCount = statusCount.get (index) == null? 0: statusCount.get (index); statusCount.set (index, counterMetric.getValue (). intValue () + oldCount); }} private void appendStatusIfNotExist (String status, ArrayList statusCount) {if (! statusList.contains (status)) {statusList.add (status); statusCount.add (0); }}

Vegye figyelembe, hogy:

  • PublicMetics státuszszámláló neve kezdődikszámláló.állapot" például "számláló.állapot.200.gyökér
  • A jegyzékünkben percenként nyilvántartjuk az állapotszámlálást statusMetricsByMinute

Exportálhatjuk összegyűjtött adatainkat, hogy grafikonba rajzoljuk őket - alábbiak szerint:

public Object [] [] getGraphData () {Date current = new Date (); int colCount = statusList.size () + 1; int rowCount = statusMetricsByMinute.size () + 1; Object [] [] eredmény = new Object [rowCount] [colCount]; eredmény [0] [0] = "Idő"; int j = 1; for (String status: statusList) {eredmény [0] [j] = állapot; j ++; } for (int i = 1; i <rowCount; i ++) {result [i] [0] = dateFormat.format (new Date (current.getTime () - (60000 * (rowCount - i)))); } List minuteOfStatuses; Lista utolsó = új ArrayList (); for (int i = 1; i <rowCount; i ++) {minuteOfStatuses = statusMetricsByMinute.get (i - 1); mert (j = 1; j = j? last.get (j - 1): 0); } while (j <colCount) {eredmény [i] [j] = 0; j ++; } last = minuteOfStatuses; } visszatérési eredmény; }

7.5. Rajzoljon grafikont a metrikák segítségével

Végül - ábrázoljuk ezeket a mutatókat egy 2 dimenziós tömbön keresztül -, hogy aztán ábrázolhassuk őket:

public Object [] [] getGraphData () {Date current = new Date (); int colCount = statusList.size () + 1; int rowCount = statusMetric.size () + 1; Object [] [] eredmény = new Object [rowCount] [colCount]; eredmény [0] [0] = "Idő"; int j = 1; for (String status: statusList) {eredmény [0] [j] = állapot; j ++; } ArrayList temp; for (int i = 1; i <rowCount; i ++) {temp = statusMetric.get (i - 1); eredmény [i] [0] = dateFormat.format (új Date (current.getTime () - (60000 * (rowCount - i)))); for (j = 1; j <= temp.size (); j ++) {eredmény [i] [j] = temp.get (j - 1); } while (j <colCount) {eredmény [i] [j] = 0; j ++; }} visszatérési eredmény; }

És itt van a Controller módszerünk getMetricData ():

@RequestMapping (érték = "/ metric-graph-data", módszer = RequestMethod.GET) @ResponseBody nyilvános objektum [] [] getMetricData () {return metricService.getGraphData (); }

És itt van egy minta válasz:

[["Idő", "számláló.állapot.302", "számláló.állapot.200", "számláló.állapot.304"], ["2015-03-26 19:59", 3,12,7], ["2015-03-26 20:00", 0,4,1]]

8. A Spring Boot 2.x aktor használata

A Spring Boot 2-ben a Spring Actuator API-jai nagy változásnak voltak tanúi. Spring saját mutatóit felváltotta a Mikrométer. Tehát írjuk ugyanazt a metrikát a fenti példával Mikrométer.

8.1. Csere CounterService Val vel MeterRegistry

Mivel a Spring Boot alkalmazásunk már az Actuator indítójától függ, a Micrometer már automatikusan konfigurálva van. Beadhatunk injekciót MeterRegistry ahelyett CounterService. Különböző típusokat használhatunk Méter metrikák rögzítésére. A Számláló a mérők egyike:

@Autowired private MeterRegistry nyilvántartás; private List statusList; @Orride public void growthCount (final int status) {String counterName = "counter.status." + állapot; nyilvántartás.számláló (számlálóNév) .növekedés (1); if (! statusList.contains (counterName)) {statusList.add (counterName); }}

8.2. Számlák exportálása a következővel: MeterRegistry

A mikrométerben exportálhatjuk a Számláló értékek felhasználásával MeterRegistry:

@Scheduled (fixedDelay = 60000) private void exportMetrics () {ArrayList statusCount = new ArrayList (); for (String status: statusList) {Search search = register.find (status); if (keresés! = null) {Számláló számláló = keresés.számláló (); statusCount.add (számláló! = null? ((int) számláló.szám ()): 0); register.remove (számláló); } else {statusCount.add (0); }} statusMetricsByMinute.add (statusCount); }

8.3. Metrikák közzététele Mérők

Most a Metrics segítségével is közzétehetjük MeterRegistry mérői:

@Scheduled (fixedDelay = 60000) private void exportMetrics () {ArrayList lastMinuteStatuses = initializeStatuses (statusList.size ()); for (Meter counterMetric: publicMetrics.getMeters ()) {updateMetrics (counterMetric, lastMinuteStatuses); } statusMetricsByMinute.add (lastMinuteStatuses); } private void updateMetrics (végső Meter counterMetric, végső ArrayList statusCount) {String status = ""; int index = -1; int oldCount = 0; if (counterMetric.getId (). getName (). tartalmazza ("counter.status.")) {status = counterMetric.getId (). getName (). szubsztring (15, 18); // 404. példa, 200 appendStatusIfNotExist (status, statusCount); index = statusList.indexOf (állapot); oldCount = statusCount.get (index) == null? 0: statusCount.get (index); statusCount.set (index, (int) ((Counter) counterMetric) .count () + oldCount); }}

9. Következtetés

Ebben a cikkben néhány egyszerű módszert tártunk fel, amellyel néhány alapvető mérési képesség beépíthető egy Spring webalkalmazásba.

Vegye figyelembe, hogy a számlálók nem biztonságos szálak - így nem biztos, hogy pontosak, ha nem használnak atomszámokat. Ez csak azért volt szándékos, mert a deltának kicsinek kell lennie, és nem a 100% -os pontosság a cél - inkább a korai trendek észlelése.

Természetesen vannak kiforrottabb módszerek a HTTP-mutatók rögzítésére egy alkalmazásban, de ez egyszerű, könnyű és szuperhasznos módszer a teljes értékű eszköz extra bonyolultsága nélkül.

A cikk teljes megvalósítása megtalálható a GitHub projektben.

REST alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

$config[zx-auto] not found$config[zx-overlay] not found