2016. november 5., szombat

Perform Day 2016 - Budapest

Október 25-én, Budapesten is megrendezésre került a dynaTrace által támogatott Perform Day, amire meghívtuk a legfontosabb ügyfeleinket, hogy beszéljünk a közös sikereinkről, továbbá néhány szakmai prezentációt is meghallgathattak a résztvevők.

DynaTrace Driven Development és Testing címmel tartottam egy bemutatót arról, hogy miért édemes a dynaTrace-t már a fejlesztés és a tesztelés korai szakaszában használni, valamint a Continuous Integration és a Delivery Pipeline általunk használt gyakorlatát halgathatták meg a résztvevők.



A konferencia egy közös vacsorával záródott, a magas érdeklődésre tekintettel szinte biztos, hogy jövőre is megrendezzük ezt a rendezvényt!

2016. szeptember 1., csütörtök

dynaTrace - Memória szivárgás beazonosítása

Az előző cikk folytatásaként, egy éles rendszerben előfordult memória szivárgáson keresztül fogom megmutatni, hogy hogyan is kell a dynaTrace-szel a gyökér okokig eljutni. Általában minden azzal kezdődik, hogy a dynaTrace-től kapunk egy riasztást, hogy kevés a szabad memória vagy túl sokat GC-zik az appserver, majd a Process Health dashboardon validáljuk, hogy valóban ez a helyzet. Restart után készítettem néhány Memory Consumption Trending dump-ot és beazonosítottam, hogy mely osztályok példány száma növekszik. Esetünkben a BasifTopup osztályból 669.195 darab volt a heap-en.


Ezután a System Profile/Sensors menüpont alatt a BasifTopup osztályra felhelyeztem egy memória szenzort. A dynaTrace hot sensor placement feature segítségével, külön újraindítás nélkül, futásidőben aktiválódott ez a szenzor szabály.


Selective Memory Dump-ok készítésével látható váltak az objektum allokációk, ahonnan pedig továbbfúrtam azokhoz a PurePath-okhoz, ahol ezek az objektum példányok létrejöttek.

A PurePath hívási láncnál megjelent, hogy a BasifTopup példányai, a registerResultInUnitOfWork() metódus hívásnál keletkeznek nagy számban. Innen két kattintással a bytecode visszafejtésével elém tárult a forráskód, ami alapján megtettem a javaslataimat a probléma elhárítása érdekében.


Hát nem egyszerű és nagyszerű? :))


2016. augusztus 6., szombat

dynaTrace - Memória dump típusok

Gyorsan meg akarod találni a memória szivárgás (memory leak) valódi okát? Használj dynaTrace-t! Attól függően, hogy milyen információra van szükséged, 3 féle heap dump típus készítése közül választhatsz:

1. Deep Memory Leak Analysis:

Ez a hagyományos heap dump-nak feleltethető meg, azaz az objektumok kapcsolatai, a referenciák mentén lekövethető. A heap méretétől függően több percbe is telhet a dump létrehozása, mialatt a JVM mással nem foglalkozik, így napközben való készítése, éles környezetben csak indokolt esetben javasolt. Az elkészített dump utófeldolgozását a dynaTrace Analysis szerver fogja elvégezni. Gyakori kérdés, de a dynaTrace-es dump-ot más eszközzel (Eclipse Memory AnalyzerIBM HA) nem tudjuk beolvasni.


2. Memory Consumption Trending:

Ezzel a dump-pal megkapjuk, hogy melyik osztályból hány példány volt a memóriában. Az előnye, hogy néhány másodperc alatt lefut, azaz nem akasztja meg az alkalmazás futását, így éles környezetben, akár napközben is használható. Ha memória fogyást tapasztalunk, készítünk pl. 10 percenként pár dumpot és összehasonlíthatjuk őket, hogy mely osztályok példányszáma növekszik folyamatosan. 


3. Selective Memory Dump:

Miután a Memory Consumption Trending dump-ok készítésével meghatároztuk azokat az osztályokat, amelyek példányszáma növekszik, ezen az osztályokra memória szenzort tehetünk fel, majd a Selective Memory Dump készítésével megtekinthetjük, hogy a PurePath hívási láncban ezek az objketumok melyik metódusnál jönnek létre. Nagyon hasznos feature!


A folytatásban pedig egy esettanulmányt fogok megmutatni, hogy a gyakorlatban hogyan kell egy memory leak gyökér okát beazonosítani a dynaTrace-szel.

2016. július 24., vasárnap

EMA and Plumbr - Memory leak hunting

Hogy ne mindig csak a dynaTrace-ről legyen szó, most az Eclipse Memory Analyzer-rel és a Plumbr eszközökkel mutatom meg, hogyan lehet megoldni egy memória szivárgást. Egy web-alkalmazásnál tapasztaltam azt a jelenséget, hogy néhány undeploy-deploy művelet hatására java.lang.OutOfMemoryError: PermGen space hiba keletkezett. A szokásostól eltérően, most nem a dynaTrace-t vettem elő (mert az adott szerveren nem volt DT licence) hanem más alternatívákat.

Az OutOfMemory hatására készült egy heap dump, amit betöltöttem az EMA eszközbe. Itt van egy jó tutorial az EMA-val való ClassLoading leak megtaláláshoz. A megoldáshoz nem kellett sokat keresgélni, mert már a beépített Leak Suspect Report is kimutatta, hogy hol lesz a probléma, mindenesetre azért kicsit magam is megnézegettem a dumpot, ahol bebizonyosodott, hogy az oracle jdbc driver miatt, az osztálybetöltő nem tudott felszabadulni.


Már rég kiakartam próbálni a java agnet alapú Plumbr free verzióját, ezért ez a memory leak pont kapóra jött nekem. A Plumbr nem az utólag elkészített heap dump-ot analizálja, hanem real-time figyeli az alkalmazásunkat és ha egy anomáliát talál, azonnal kijelzi a probléma okát és még megoldási javaslatokkal is ellát minket. Ezt már nevezem!


Itt, itt meg itt találtam néhány leírást ami pontosan illeszkedett erre a problémára, röviden tehát a leak-et az okozta, hogy az adatbázis driver nem került sohasem felszabadításra egy WildFly bug miatt, amit az osztálybetöltési policy módosításával sem sikerült orvosolni. Végül, más megoldás hiányában - egy nem szép - de működő programozott megoldást próbáltam ki amivel megoldódott a hibajelenség.


Jut eszembe, a Java 8-ban már nincs is perm gen space helyette van metaspace. :)

2016. július 15., péntek

Arduino Uno - Szenzor projekt

A Raspberry Pi mini számítógépem mellé vettem pár hónapja egy Arduino-t és néhány szenzort is az elektronikai kísérletezéshez. Az Aliexpressz-ről rendeltem meg a cuccokat, így kb. 4000Ft-ért kaptam egy Arduino UNO klónt USB kábellel, egy PIR mozgásérzékelőt, egy DHT-22 nagy pontosságú hőmérséklet és páraszenzort valamint egy HCR-SR04 ultrahangos távolságmérőt. A célom az volt, hogy a szenzorok által begyűjtött mérési eredmények a fejlesztő eszköz konzolján megjelenjenek.


Az alábbi programot készítettem el, majd feltöltöttem az Arduino-ra. A kódban definiáltam a szenzorok lábait, amelyekről a mérési eredmények beolvashatók, majd a Serial.print() hívással egyszerűen kiírattam ezeket a konzolra.
#include "DHT.h"

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
 
int triggerPin = 11;    
int echoPin = 12;   
long durationMicroSec,cm;

int pir=4;

void setup() {
  Serial.begin (9600);
  
  //HCSR04
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  //DHT22
  dht.begin(); 
    
  //PIR
  pinMode(pir, INPUT); 
}
 
void loop()
{  
  //HCSR04
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(5);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);

  durationMicroSec = pulseIn(echoPin, HIGH);
  cm = (durationMicroSec*0.000001*34300)/2.0; //s=v*t

  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
    
  //DHT22
  delay(2000);
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.print(" *C ");
  Serial.println();
  
  //PIR
  if(digitalRead(pir)){      
      Serial.print("There is motion");
  }
  else{
      Serial.print("There is no motion");
  }
  Serial.println();  
}
Az Ardunio használatával, pár ezer forintból akár egy komplex otthoni biztonsági rendszert is kialakíthatunk. Ha lecsupaszítjuk az Ardunino-t a felesleges elektronikai részektől, akkor egy akkumulátorról akár több hónapig is képes a működésre. A mért jellemzőket pl. rádió frekvenciás csatornán (szintén pár 100Ft-os áramkör) egy Raspberry Pi-nek is továbbíthatjuk, amivel feldolgozhatjuk és eltárolhatjuk a mért adatokat. A lehetőségeknek nem a pénztárcánk, hanem csak a képzeletünk szabhat határt! :)

2016. július 1., péntek

Raspberry PI - UFO keresés a szabad CPU időben

A Bionic program használatával a szabad CPU idődben valamilyen értelmes tudományos projektben vehetsz részt. Például űrlények vagy aszteroidák után kutathatsz :), pulzárok felfedezéséhez járulhatsz hozzá vagy különféle betegségek gyógyításában segíthetsz. Az elérhető projektekről itt van egy lista. Mivel van egy folyamatosan működő Raspberry Pi mini számítógépem, amit torrent kliensnek, web-szervernek valamint SSL Socks proxy-nak használok, a szabad CPU idejét ráállítottam az UFO kutatásra a Seti@Home projekttel, ami a rádióteleszkópok adatait tölti le majd elemzi ki az otthoni RPI-n.

Az UFO kutatás megkezdéséhez nincs más dolgunk, mint beregisztrálni magunkat a SETI@Home oldalára az alábbi linken és a Raspberry Pi-n feltelepíteni és bekonfigurálni a bionic ill. Seti programokat ezen leírás alapján az alábbi parancsokkal:

apt-get install boinc 
cd /var/lib/boinc-client
wget https://github.com/dcarrion87/boinc-rpi/raw/master/bin/setiathomev7-armv6l.tar.gz
tar xfz setiathomev7-armv6l.tar.gz
chown -R boinc:boinc projects/
Add "ENABLED = 1" to /etc/init.d/boinc-client if you want to run as a service.
boinccmd --lookup_account http://setiathome.berkeley.edu <your_email> <your_password>
boinccmd --project_attach http://setiathome.berkeley.edu <your_account_key>

Az aktuálisan futó taszkot a boinccmd --get_tasks paranccsal tudjuk lekérdezni, valamint a webes felületen is megtekinthetjük a szerzett kreditek számát.

2016. június 4., szombat

dynaTrace 2016 Partner Summit

Május 9 és 11 között került megrendezésre az idei évi dynaTrace EMEA Partner Summit, amit Portugália egyik legszebb városában, Vilamoura-ban rendeztek meg. A szokásos marketing jellegű prezentációk mellett, halhattam technikai előadásokat is a dynaTrace legfontosabb újításairól, a roadmap-ról és az új stratégiai irányvonalakról. Számomra az egyik legérdekesebb téma a dynaTrace kutatási laborjában fejlesztett Ruxit technológia bemutatása volt. A Ruxit-ot egyértelműen a dynaTrace kiegészítéseként ajánlják sok szerveres és mikrokonténeres környezetben. Hamarosan blogolni is fogok erről a témáról, ugyanis hamarosan Magyarországon is megkezdjük a Ruxit támogatását.


A konferencia mellett azért maradt időnk város nézésre és túrázásra is a környéken. Szép tájak és finom ételek, ez Portugália. :)





2016. május 19., csütörtök

IIR - Szoftvertesztelés 2016

Az idei évben is meghívást kaptam az IIR szoftvertesztelési konferenciájára, ami május 24-25-én kerül megrendezésre a Park Inn Radisson hotelben. A két évvel ezelőtti Agilis tesztkörnyezeti teljesítménymenedzsment témakör után most az Agilis monitorozásról fogok egy fél órás prezentációt tartani az alábbi témakörökkel:

  • CI Delivery Pipeline a gyakorlatban
  • Az automatizált monitorozás új aspektusai
  • Statikus és dinamikus jellemzők mérése (SonarQube és Dynatrace)
  • DEVOPS, ahogyan tényleg működik


A prezentáció ezen a linken letölthető. 

2016. április 5., kedd

Raspberry Pi - Non-stop torrent kliens

Korábban már olvashattad a blogon, hogy havi 200 Ft-os áramköltség mellett, egy folyamatosan működő otthoni web-szervert üzemeltethetsz a RaspberryPi miniszámítógépeden, de ezzel párhuzamosan más is futhat rajta, pl. egy torrent kliens vagy a szabad CPU idő hasznosításához valamilyen tudományos projekt.

Torrentezéshez a Transmission démon szolgáltatást ajánlom, amit a sudo apt-get install transmission-daemon paranccsal telepíthetsz fel. A konfiguráláshoz állítsuk be a következőket az /etc/transmission-daemon/settings.json fájlban.

"download-dir": "/opt/pendrive/torrents/completed",
"incomplete-dir": "/opt/pendrive/torrents/Incomplete",
"incomplete-dir-enabled": true,
"watch-dir": "/opt/pendrive/torrents/Watch",
"watch-dir-enabled": true,

Amikor egy torrent fájlt bemásolsz a watch-dir könyvtárba, a transmission ezt észreveszi, majd a download-dir könyvtárba letölti a fájlt. Azért, hogy más peer-ek is tudjanak hozzád kapcsolódni, meg kell határozni egy portot amin figyelsz a bejövő peer kapcsolatokra. Ezt a settings.json fájlban a peer-port:51413 értékkel tudod megadni, majd a router port-forwarding beállításoknál is engedélyezned kell:



transmission-remote-cli parancs kiadásával pedig megtekintheted a torrenteket egy konzolos kliens felületről.

2016. március 6., vasárnap

Románia, Raiffeisen Bank - dynaTrace support

Ezen a héten Bukarestben dolgoztam, ahol a helyi kollégákkal üzleti dashboard-ok kialakítása volt a feladatom. Az ütemezés elég szorosra sikerült és a napi bemutatók során is jöttek újabb igények, melyeket belevettünk az implementációba. Közel 80 üzleti tranzakciót és ezekre épülő dashboardot alakítottunk ki a tesztkörnyezetben, majd migráltunk az éles rendszerbe.


A hét lezárásaként egy negyedórás live demón keresztül néhány éles környezeti hibára ill. performancia problémára is rámutattam, bereklámozva a céges performance booster programunkat. 

2016. február 3., szerda

UBIK Load Pack - GWT alkalmazások tesztelése JMeterrel

Azt a feladatot kaptam, hogy terheléses tesztet készítsek egy GWT alapú web-alkalmazáshoz. A felvett JMeter teszteseteknél a GWT-RPC protokoll miatt a request és a response paraméterek nem olvashatók ki a szokásos módon, amire viszont szükség volt a paraméterek szkriptelt aktualizálásánál. Paraméterek használata nélkül csak olyan terheléses teszt készíthető, ahol nincsenek futásidőben változó paraméterek, mint például a menükön való végig kattintgatás szimulálása.

Azért, hogy a GWT RPC során használt objektumokat a JMeter segítségével felhasználhassuk, az UBIK Load Pack kiegészítői közül, a JMeter-GWT alkalmazása mellett döntöttem, ami visszafejti és cserélhetővé teszi a paramétereket. A dekódolás végrehajtása után XML-t kapunk, így XPATH kifejezésekkel már könnyen beazonosíthatunk egy node-ot és annak az értékét a JMeter teszteseteknél.

A dekódolás előtti request:


A dekódolt request:


A dekódolt response:


A plugin bekonfigurálását elég körülményesnek mondanám, valamint szükséges hozzá a telepíthető alkalmazás is (WAR, EAR) és ehhez hozzájön még, hogy a konfigurációs lépéseket új alkalmazás verziók esetén ismételten el kell végezni. Szintén fekete pont, hogy a plugin fizetős, pl. egy 100VU-s licence ára 1100EUR (~ 340.000Ft) - 3 hónapos frissítési támogatással. Mindezek ellenére tökéletesen működik és jól integrálódik a JMeter-hez, a használata egyszerű.

Ti milyen eszközt használtok a GWT-s web-alkalmazások terheléses tesztelésénél?

2016. január 4., hétfő

Selenium - RemoteWebDriver + Jenkins

Egy folyamatos integrációs környezetben általában nem azon a gépen futtatjuk a felületi teszteket ahol a Jenkins is dolgozik, ezért felhúzunk egy külön Windows-os gépet ahova feltelepítünk Internet Explorer-t, Firefox-ot meg egy Chrome-ot mivel azt szeretnénk, hogy a Jenkins indította klikkelő robot már itt kattintgasson majd az eredményeket juttassa vissza a Jenkins számára.

Ez a működés a Selenium RemoteWebDriver segítségével egyszerűen megoldható. Először is rögzítsük a felületi tesztesetet a Selenium IDE Firefox plugin segítségével, majd exportáljuk Java forrásként és módosítsuk az alábbi mintakód alapján, ahol is a baseURL az alkalmazás kezdő URL-e, a távoli Windows-os gép a remoteSeleniumServer URL-en figyel, a browser pedig az a böngésző típus amivel a tesztet futtatni fogjuk. Látható, hogy ebben a minta kódban be vannak égetve az alapértelmezett értékek, de a Jenkins-ből ezeket majd felülírhatjuk.

import static org.junit.Assert.fail;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import com.thoughtworks.selenium.webdriven.WebDriverBackedSelenium;


public class NLRTest {
 private String baseURL = "https://webapphost:8113/";
 private String remoteSeleniumServer = "http://rsh:4444/wd/hub";
 private String browser="chrome";//firefox,internet explorer,chrome
 
 private WebDriverBackedSelenium selenium;
 private RemoteWebDriver remoteWD = null;

 @Before
 public void setUp() throws Exception {
  
  
  if(!StringUtils.isBlank(System.getProperty("baseURL")))
   baseURL=System.getProperty("baseURL");
  
  if(!StringUtils.isBlank(System.getProperty("remoteSeleniumServer")))
         remoteSeleniumServer=System.getProperty("remoteSeleniumServer");
  if(!StringUtils.isBlank(System.getProperty("browser")))
         browser=System.getProperty("browser");
   

  DesiredCapabilities capabilities = new DesiredCapabilities();
  capabilities.setJavascriptEnabled(true);
  capabilities.setBrowserName(browser);
  try {
   remoteWD = new RemoteWebDriver(new URL(remoteSeleniumServer),capabilities);
   

  } catch (MalformedURLException e) {
   e.printStackTrace();
  }

  selenium = new WebDriverBackedSelenium(remoteWD, baseURL);

 }

 @SuppressWarnings("deprecation")
 @Test
 public void testNLR1() throws Exception {

  selenium.open("/NLR/login");
  
  //IE certification ok button
  if(browser.equals("internet explorer"))
   remoteWD.navigate().to("javascript:document.getElementById('overridelink').click()");
  
  
  selenium.type("id=fnev", "myuser");
  selenium.type("id=password", "mypass");
  for (int second = 0;; second++) {
   if (second >= 60)
    fail("timeout");
   try {
    if ("felhasználónév:".equals(selenium
      .getText("css=td.left_label")))
     break;
   } catch (Exception e) {
   }
   Thread.sleep(1000);
  }

  selenium.click("css=button[type=\"button\"]");
  selenium.waitForPageToLoad("30000");
  for (int second = 0;; second++) {
   if (second >= 60)
    fail("timeout");
   try {
    if ("Munkamenet".equals(selenium.getText("link=Munkamenet")))
     break;
   } catch (Exception e) {
   }
   Thread.sleep(1000);
  }

  selenium.click("link=Munkamenet");
  ...
  selenium.click("link=Előzmények keresése");
  selenium.waitForPageToLoad("30000");
  selenium.click("link=Kilépés");
  selenium.waitForPageToLoad("30000");

 }

 @After
 public void tearDown() throws Exception {
  selenium.stop();
 }

}

A klikkelő robotnak létrehozott távoli Windows-os hosztra, ahol feltelepítettük az IE, Firefox és Chrome böngészőket, másoljuk fel a selenium-server-standalone.jar, a chromedriver.exe és IEDriverServer.exe fájlokat. A firefox driver-t nem kell külön letölteni, mert azt a selenium-server-standalone.jar már tartalmazza. Ezután ezen a dedikált Windows-os gépen indítsuk el a Selenium-ot az alábbi paranccsal, felparaméterezve a driverek elérési útvonalával. Innentől kezdve a Jenkins már képes elindítani a klikkelő robotot ezen a gépen.

java -Dwebdriver.chrome.driver="c:\\chromedriver.exe" -Dwebdriver.ie.driver = "c:\IEDriverServer.exe" -jar c:\selenium-server-standalone-2.47.1.jar 

Itt olvasható, hogy a Selenium-ot hogyan illeszthetjük be a maven-es projektünkbe, a Jenkins felületén pedig a Goals and options résznél állíthatjuk be a megfelelő paramétereket:

test -Dbuild.number=${PIPELINE_VERSION} -Dtest=hu.bakai.selenium.* -DbaseURL = "https://172.22.22.22:8113" -DrempoteSeleniumServer = "http://10.128.11.11:4444/wd/hub"  -Dbrowser = "internet explorer"