ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [nGrinder]Instrumentation
    서버 2016. 5. 21. 12:10

    Instrumentation이란?


    그라인더는 스크립트가 record되어야 하는 스크립트 코드의 부분에 표시하는 것을 허용합니다. 이를 instrumentation이라 합니다. 코드는 Test 함수를 위해 instrumented됩니다. instrumented code가 호출될 때, 테스트의 통계는 업데이트 됩니다. 표준 통계는 에러의 수, call의 횟수, 호출된 시간을 기록합니다. 향상된 스크립트는 앞에서 기록한 통계를 추가할 수 있습니다. 사용자는 객체의 자바 바이트 코드를 수정하기 위해 Test 함수를 사용해 객체를 instrument할 수 있습니다.

    from net.grinder.script import Test
    from net.grinder.script.Grinder import grinder
      
    test1 = Test(1, "Log method")
      
    # Instrument the info() method with our Test.
    test1.record(grinder.logger.info)
      
    class TestRunner:
        def __call__(self):
            log("Hello World")

    매번 "Hello World"는 로그파일에 쓰여지고 쓰여진 시간은 그라인더에 의해 record 됩니다.

    Instrumentation은 중첩 될 수 있습니다. 예를 들어, 사용자는 Test 1을 가진 함수를 instrument할 수 있고 함수의 코드는 Test 2와 Test 3을 가진 instrument 된 HTTPRequest 호출 할 수도 있습니다. Test 2와 3에 의해서 instrument된 코드는 Test 1 코드 안에 중첩될 수 있습니다. Test 1에 record된 시간은 Test2와 3에 record된 시간의 합보다 커야 합니다. 예를 들어, grinder.sleep()을 호출한 것과 같이 함수 자체에 소요된 시간을 포함합니다.

    Instrumentation 쉬운 예제


    def Hello() 
        ... 

    Test(1, "Hello Test").record(Hello) 

    라고 기재하게 되면 Hello 가 한번 실행될때 마다 트랜잭션이 올라갑니다. 

    자동 생성된 스크립트를 보면.. 

    test1 = Test(1, "Test1") 
    request1 = HTTPRequest() 

    # Make any method call on request1 increase TPS 
    test1.record(request1) 

    와 같은 코드가 있는데.. 

    request1 이라는 객체의 어떤 메소드라도 호출되면, 이를 트랜잭션으로 치겠다는 겁니다. 

    result = request1.GET("http://www.google.com") 

    와 같이 GET 이 호출되어 성공하면 트랜잭션이 올라갑니다. 

    이런 기술을 Instrumentation 이라고 합니다. 

    Selective instrumentation


    그라인더 3.7 버젼은 선택적으로 target 객체가 instrument할 수 있도록 허용하는 record의 오버로드 된 버젼을 추가합니다. 

    Selective instrumentation은 일반적으로 테스트 통계에 영향을 주는 것 없이 호출이 필요한 보조 함수를 가지는 HTTPRequest 클래스의 instrument 인스턴스에 유용합니다. 아래는 selective instrumentation을 사용하는 예제입니다.

    from net.grinder.script import Test
    from net.grinder.plugin.http import HTTPRequest
      
    test = Test(1, "my test")
      
    class GetAndPostFilter(Test.InstrumentationFilter):
      def matches(self, method):
        return method.name in ["GET", "POST"]
      
    request = HTTPRequest(url="http://grinder.sourceforge.net")
    test.record(request, GetAndPostFilter())
      
    class TestRunner:
        def __call__(self):
            # GET() is instrumented, so call statistics are reported.
            request.GET()
      
            # getUrl() is not instrumented, no call statistics are reported.
            print "Called %s" % request.url

    Selective instrumentation 쉬운 예제


    public static GTest test 
    @BeforeProcess 
       test = new GTest(1, "Test1") 
       request = new HTTPRequest() 
       test.record(request) 
    
    정의후에 
      
    @Test 함수에서 
    request.setUrl() 
    request.setsetHeaders() 
    request.setData() 
    request.POST(uri) 

    request 객체의 어떤 함수라도 실행이 되면 TPS에 영향을 미치는 것 같아 GET이나 POST 호출일 때만 업데이트 되기를 원함 이 것을 Selective instrumentation으로 어떻게 변경할까?


    정답


    GTest test = new GTest(1,  "hello_test"); 
                    test.record(request, new GTest.InstrumentationFilter() { 
                            
                            @Override 
                            public boolean matches(Object item) { 
                                    return (item.name == "GET" || item.name == "POST"); 
                            } 
                    }); 

    위와 같은 방식으로 해결할 수 있지만 request 자체를 instrumentation하는 것 보다는 test 자체를 instrumentation하는 것이 더 편합니다. 방식은 아래와 같습니다.


    @BeforeProcess 
            public static void beforeProcess() { 
                    test = new GTest(1, "Hello"); 
                    request = new HTTPRequest(); 
            } 
    
            @BeforeThread 
            public void beforeThread() { 
                    grinder.statistics.delayReports=true 
                    grinder.getLogger().info("before thread in MyTest."); 
                    // 여기서 Request 가 아닌 doTest 를 Instrumentation 합니다. 
                    test.record(this, "doTest"); 
            } 
    
    
            @Test 
            public void testHello(){ 
                    // 앞에서 request 가지고 일단 장난 치고 
                    // request.setUrl() / request.setsetHeaders() / request.setData()  같은 
                    // 실제 테스트로 넘깁니다. 
                    doTest(request); 
            } 
            
            /** DoTest 자체를 TPS로 처리합니다. */ 
            public void doTest(HTTPRequest request) { 
                    request.POST.... 
            } 


    댓글