woniper

SpringBoot Actuator BeansEndPoint Class 본문

Spring

SpringBoot Actuator BeansEndPoint Class

woniper1 2016. 7. 28. 17:57

  오늘은 어떤 코드를 살펴볼까 고민하다가. 로컬 환경에 셋팅해 놓은 스프링 부트 패키지를 살펴보다가 actuator 패키지가 눈에 들어왔다. 스프링 부트에서는 actuator라는 멋진 녀석이 있는데, 이는 실행 중인 서버에 상태값이나 여러가지 정보를 확인 할 수 있는, 말하자면 모니터링 가능한 데이터를 자동으로 제공한다.

  잘 와닿지 않을 수 있는데 오늘 살펴본 actuator에서 BeanEndPoint Class가 하는 역할은 localhost:8080/beans 라는 url로 요청하면 현재 스프링 부트로 동작하는 서버에 bean으로 등록된 bean 리스트를 json 형태로 응답한다. 즉, localhost:8080에서 관리되는 bean 리스트를 조회한다는 것인데, 이런식으로 자동으로 제공되는 모니터링 가능 한 데이터를 제공한다. bean 리스트 말고도 여러가지 데이터를 제공하니 한번 살펴보면 많은 곳에 활용 가능할 것이다.


BeanEndPoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@ConfigurationProperties(prefix = "endpoints.beans")
public class BeansEndpoint extends AbstractEndpoint<List<Object>>
      implements ApplicationContextAware {
 
   private final LiveBeansView liveBeansView = new LiveBeansView();
 
   private final JsonParser parser = JsonParserFactory.getJsonParser();
 
   public BeansEndpoint() {
      super("beans");
   }
 
   @Override
   public void setApplicationContext(ApplicationContext context) throws BeansException {
      if (context.getEnvironment()
            .getProperty(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME) == null) {
         this.liveBeansView.setApplicationContext(context);
      }
   }
 
   @Override
   public List<Object> invoke() {
      return this.parser.parseList(this.liveBeansView.getSnapshotAsJson());
   }
}
cs

invoke 메소드를 보자 LiveBeansView라는 클래스에 getSnapshotAsJson 메소드를 호출 한다.


LiveBeansView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
protected String generateJson(Set<ConfigurableApplicationContext> contexts) {
   StringBuilder result = new StringBuilder("[\n");
   for (Iterator<ConfigurableApplicationContext> it = contexts.iterator(); it.hasNext();) {
      ConfigurableApplicationContext context = it.next();
      result.append("{\n\"context\": \"").append(context.getId()).append("\",\n");
      if (context.getParent() != null) {
         result.append("\"parent\": \"").append(context.getParent().getId()).append("\",\n");
      }
      else {
         result.append("\"parent\": null,\n");
      }
      result.append("\"beans\": [\n");
      ConfigurableListableBeanFactory bf = context.getBeanFactory();
      String[] beanNames = bf.getBeanDefinitionNames();
      boolean elementAppended = false;
      for (String beanName : beanNames) {
         BeanDefinition bd = bf.getBeanDefinition(beanName);
         if (isBeanEligible(beanName, bd, bf)) {
            if (elementAppended) {
               result.append(",\n");
            }
            result.append("{\n\"bean\": \"").append(beanName).append("\",\n");
            String scope = bd.getScope();
            if (!StringUtils.hasText(scope)) {
               scope = BeanDefinition.SCOPE_SINGLETON;
            }
            result.append("\"scope\": \"").append(scope).append("\",\n");
            Class<?> beanType = bf.getType(beanName);
            if (beanType != null) {
               result.append("\"type\": \"").append(beanType.getName()).append("\",\n");
            }
            else {
               result.append("\"type\": null,\n");
            }
            result.append("\"resource\": \"").append(getEscapedResourceDescription(bd)).append("\",\n");
            result.append("\"dependencies\": [");
            String[] dependencies = bf.getDependenciesForBean(beanName);
            if (dependencies.length > 0) {
               result.append("\"");
            }
            result.append(StringUtils.arrayToDelimitedString(dependencies, "\", \""));
            if (dependencies.length > 0) {
               result.append("\"");
            }
            result.append("]\n}");
            elementAppended = true;
         }
      }
      result.append("]\n");
      result.append("}");
      if (it.hasNext()) {
         result.append(",\n");
      }
   }
   result.append("]");
   return result.toString();
}
cs

getSnapshotAsJson 메소드 호출 시 내부에서 호출하는 generateJson 메소드인데 ConfigurableApplicationContext와 ConfigurableListableBeanFactory에 등록된 모든 bean을 가져와 json 문자열로 만드는것을 알 수 있다.


막상 코드를 보니 별거없다. ApplicationContext를 활용해 bean 정보를 모두 json 문자열로 만드는 것이다. 그래도 이런 것들을 자동으로 제공한다니, 참으로 편하다.

Comments