Maven依赖(根据个人情况使用具体版本,我这儿因为框架关系,有默认版本,可不写)

  1. 1. <dependency>
  2. 2. <groupId>org.springframework.boot</groupId>
  3. 3. <artifactId>spring-boot-starter-web</artifactId>
  4. 4. </dependency>
  5. 5. <dependency>
  6. 6. <groupId>io.micrometer</groupId>
  7. 7. <artifactId>micrometer-registry-prometheus</artifactId>
  8. 8. </dependency>
  9. 9. <dependency>
  10. 10. <groupId>org.springframework.boot</groupId>
  11. 11. <artifactId>spring-boot-starter-actuator</artifactId>
  12. 12. </dependency>

配置文件(yml为例)

  1. 1. management:
  2. 2. endpoints:
  3. 3. web:
  4. 4. exposure:
  5. 5. include: '*' # info, health, beans, env, metrics, mappings, scheduledtasks, threaddump,prometheus
  6. 6. base-path: /actuator
  7. 7. metrics:
  8. 8. tags:
  9. 9. application: ${artifactId} # 公共标签

全局标签

  1. 1. @Bean
  2. 2. MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName) {
  3. 3. return registry -> registry.config().commonTags("application", applicationName);
  4. 4. }

自定义指标代码示例(DemoTable是个实体,DemoTableService是个借口,DemoTableServiceImpl是个接口实现类,缺的东西要么自行创建,要么根据情况忽略掉也可以)

TestMetric.java(代码中对指标的阐释-摘抄自互联网,,,忘了哪儿了。。。)

  1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. import com.capitek.cloud.sub.server.entity.DemoTable;
  3. import com.capitek.cloud.sub.server.service.DemoTableService;
  4. import io.micrometer.core.instrument.*;
  5. 5. import org.springframework.beans.factory.annotation.Autowired;
  6. 6. import org.springframework.stereotype.Component;
  7. 7.
  8. 8. import javax.annotation.PostConstruct;
  9. 9.
  10. 10. @Component
  11. 11. public class TestMetric {
  12. 12.
  13. 13. @Autowired
  14. 14. private DemoTableService demoTableService;
  15. 15.
  16. 16. @Autowired
  17. 17. private MeterRegistry meterRegistry;
  18. 18.
  19. 19. // 只增的指标
  20. 20. // 以下4个counter指标名称相同,标签不同,根据标签可区分彼此
  21. 21. public Counter boyJavaCounter;
  22. 22. public Counter boyCPlusCounter;
  23. 23. public Counter girlJavaCounter;
  24. 24. public Counter girlCPlusCounter;
  25. 25.
  26. 26. // 可增减的指标
  27. 27. public Gauge demoGauge;
  28. 28.
  29. 29. // 计时器
  30. 30. public Timer demoTimer;
  31. 31.
  32. 32. // 计算分布使用此指标
  33. 33. public DistributionSummary demoSummary;
  34. 34.
  35. 35. @PostConstruct
  36. 36. private void init() {
  37. 37.
  38. 38. /**----------------------------------------------↓Counter↓---------------------------------------------------*/
  39. 39.
  40. 40. /**
  41. 41. * Counter是一种比较简单的Meter,它是一种单值的度量类型,或者说是一个单值计数器。
  42. 42. * Counter的作用是记录总量或者计数值,适用于一些单向增长类型的统计,例如下单、支付次数、接口请求总量记录等等,
  43. 43. * 通过Tag可以区分不同的场景,对于下单,可以使用不同的Tag标记不同的业务来源或者是按日期划分,
  44. 44. * 对于Http请求总量记录,可以使用Tag区分不同的URL。
  45. 45. *
  46. 46. * 定义四个Counter指标,按照性别与技术栈分组(分组是根据标签任意自定义,自己觉得合理即可),当然,如指标不需要分组,则定义一个Counter即可。
  47. 47. * 注意:description没什么实际作用,且同一指标名只能拥有一个description,后设置的无效,因此description应设置为一种通用的描述性文字。如下为设置效果。
  48. 48. * 其中application标签是全局标签,全局标签会作用于每一个指标中
  49. 49. */
  50. 50. /**
  51. 51. # HELP employee_count_total 性别为boy,技术栈为java的人数
  52. 52. # TYPE employee_count_total counter
  53. 53. employee_count_total{application="subsystem-demo",job="c++",sex="girl",} 0.0
  54. 54. employee_count_total{application="subsystem-demo",job="c++",sex="boy",} 0.0
  55. 55. employee_count_total{application="subsystem-demo",job="java",sex="girl",} 0.0
  56. 56. employee_count_total{application="subsystem-demo",job="java",sex="boy",} 0.0
  57. 57. */
  58. 58. boyJavaCounter = Counter.builder("employee.count").tags(Tags.of("sex", "boy", "job", "java")).description("性别为boy,技术栈为java的人数").register(meterRegistry);
  59. 59. boyCPlusCounter = Counter.builder("employee.count").tags(Tags.of("sex", "boy", "job", "c++")).description("性别为boy,技术栈为c++的人数").register(meterRegistry);
  60. 60. girlJavaCounter = Counter.builder("employee.count").tags(Tags.of("sex", "girl", "job", "java")).description("性别为girl,技术栈为java的人数").register(meterRegistry);
  61. 61. girlCPlusCounter = Counter.builder("employee.count").tags(Tags.of("sex", "girl", "job", "c++")).description("性别为girl,技术栈为c++的人数").register(meterRegistry);
  62. 62.
  63. 63. /**----------------------------------------------↑Counter↑----------------------------------------------------*/
  64. 64.
  65. 65. /**----------------------------------------------↓Gauge↓------------------------------------------------------*/
  66. 66.
  67. 67. // 定义一个Gauge指标,每次拉取指标时,gauge的值会从demoTableService::getTest接口中获取
  68. 68. demoGauge = Gauge.builder("employee_online", demoTableService::getTest).description("this is demo gauge description").register(meterRegistry);
  69. 69. // 如下为设置效果
  70. 70. /**
  71. 71. * # HELP employee_online this is demo gauge description
  72. 72. * # TYPE employee_online gauge
  73. 73. * employee_online{application="subsystem-demo",} 4.0
  74. 74. */
  75. 75.
  76. 76. /**----------------------------------------------↑Gauge↑------------------------------------------------------*/
  77. 77.
  78. 78. /**----------------------------------------------↓Summary↓----------------------------------------------------*/
  79. 79.
  80. 80. // 计算分布情况
  81. 81. /**
  82. 82. * 计算分布情况,不依赖于时间
  83. 83. * Summary(摘要)主要用于跟踪事件的分布,在Micrometer中,对应的类是DistributionSummary(分发摘要)。
  84. 84. * 它的使用方式和Timer十分相似,但是它的记录值并不依赖于时间单位。
  85. 85. */
  86. 86. demoSummary = DistributionSummary.builder("demo.summary")
  87. 87. .tag("summary_tag", "summary_tag_value")
  88. 88. .description("this is a demo summary metric")
  89. 89. .register(meterRegistry);
  90. 90. demoSummary.record(3D);
  91. 91. demoSummary.record(4D);
  92. 92. demoSummary.record(5D);
  93. 93. demoSummary.record(6D);
  94. 94. demoSummary.record(10D);
  95. 95. // 如下为设置效果
  96. 96. /**
  97. 97. * # HELP demo_summary this is a demo summary metric
  98. 98. * # TYPE demo_summary summary
  99. 99. * demo_summary_count{application="subsystem-demo",summary_tag="summary_tag_value",} 5.0
  100. 100. * demo_summary_sum{application="subsystem-demo",summary_tag="summary_tag_value",} 28.0
  101. 101. * # HELP demo_summary_max this is a demo summary metric
  102. 102. * # TYPE demo_summary_max gauge
  103. 103. * demo_summary_max{application="subsystem-demo",summary_tag="summary_tag_value",} 10.0
  104. 104. */
  105. 105.
  106. 106. /**----------------------------------------------↑Summary↑----------------------------------------------------*/
  107. 107.
  108. 108. /**----------------------------------------------↓Timer↓------------------------------------------------------*/
  109. 109.
  110. 110. /**
  111. 111. * 计算分布情况,依赖于时间
  112. 112. * Timer(计时器)适用于记录耗时比较短的事件的执行时间,通过时间分布展示事件的序列和发生频率。
  113. 113. * 所有的Timer的实现至少记录了发生的事件的数量和这些事件的总耗时,从而生成一个时间序列。
  114. 114. * Timer的基本单位基于服务端的指标而定,但是实际上我们不需要过于关注Timer的基本单位,因为Micrometer在存储生成的时间序列的时候会自动选择适当的基本单位。
  115. 115. *
  116. 116. * 如果一个任务的耗时很长,直接使用 Timer 并不是一个好的选择,因为 Timer 只有在任务完成之后才会记录时间。
  117. 117. * 更好的选择是使用 LongTaskTimer。LongTaskTimer 可以在任务进行中记录已经耗费的时间
  118. 118. */
  119. 119. demoTimer = Timer.builder("demo.timer")
  120. 120. .tag("demo_timer_tag", "demo_timer_tag_value")
  121. 121. .description("this is a demo timer")
  122. 122. .register(meterRegistry);
  123. 123. demoTimer.record(() -> {
  124. 124. demoTableService.getTest();
  125. 125. });
  126. 126. // 如下为设置效果
  127. 127. /**
  128. 128. * # HELP demo_timer_seconds this is a demo timer
  129. 129. * # TYPE demo_timer_seconds summary
  130. 130. * demo_timer_seconds_count{application="subsystem-demo",demo_timer_tag="demo_timer_tag_value",} 1.0
  131. 131. * demo_timer_seconds_sum{application="subsystem-demo",demo_timer_tag="demo_timer_tag_value",} 0.035948626
  132. 132. * # HELP demo_timer_seconds_max this is a demo timer
  133. 133. * # TYPE demo_timer_seconds_max gauge
  134. 134. * demo_timer_seconds_max{application="subsystem-demo",demo_timer_tag="demo_timer_tag_value",} 0.035948626
  135. 135. */
  136. 136.
  137. 137. /**----------------------------------------------↑Timer↑------------------------------------------------------*/
  138. 138.
  139. 139. }
  140. 140. }

DemoTableServiceImpl.java

  1. 1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. 2. import com.baomidou.mybatisplus.core.metadata.IPage;
  3. 3. import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
  4. 4. import com.capitek.cloud.common.constants.CommonConstants;
  5. 5. import com.capitek.cloud.common.model.PageParams;
  6. 6. import com.capitek.cloud.common.mybatis.base.service.impl.BaseServiceImpl;
  7. 7. import com.capitek.cloud.sub.server.annotation.DataFilter;
  8. 8. import com.capitek.cloud.sub.server.entity.DemoTable;
  9. 9. import com.capitek.cloud.sub.server.mapper.DemoTableMapper;
  10. 10. import com.capitek.cloud.sub.server.monitor.TestMetric;
  11. 11. import com.capitek.cloud.sub.server.service.DemoTableService;
  12. 12. import org.springframework.beans.factory.annotation.Autowired;
  13. 13. import org.springframework.stereotype.Service;
  14. 14. import org.springframework.transaction.annotation.Transactional;
  15. 15.
  16. 16. @Service
  17. 17. @Transactional(rollbackFor = Exception.class)
  18. 18. public class DemoTableServiceImpl extends BaseServiceImpl<DemoTableMapper, DemoTable> implements DemoTableService {
  19. 19.
  20. 20. @Autowired
  21. 21. private TestMetric testMetric;
  22. 22.
  23. 23. @Override
  24. 24. @DataFilter(user = true)
  25. 25. public IPage<DemoTable> findListPage(PageParams<DemoTable> pageParams) {
  26. 26. DemoTable query = pageParams.mapToObject(DemoTable.class);
  27. 27. QueryWrapper<DemoTable> queryWrapper = new QueryWrapper<DemoTable>();
  28. 28. queryWrapper.lambda()
  29. 29. .like(ObjectUtils.isNotEmpty(query.getName()), DemoTable::getName, query.getName())
  30. 30. .apply(ObjectUtils.isNotEmpty(pageParams.getRequestMap().get(CommonConstants.SQL_FILTER)), (String)pageParams.getRequestMap().get(CommonConstants.SQL_FILTER));
  31. 31. // 此处只是测试,某些指标值的修改应在合理的地方去触发
  32. 32. testMetric.boyJavaCounter.increment();
  33. 33. testMetric.boyCPlusCounter.increment();
  34. 34. testMetric.girlJavaCounter.increment();
  35. 35. testMetric.girlCPlusCounter.increment();
  36. 36. return page(pageParams, queryWrapper);
  37. 37. }
  38. 38.
  39. 39. // 只是一个简单的接口,返回个数儿给指标
  40. 40. @Override
  41. 41. public int getTest(){
  42. 42. return baseMapper.selectCount(new QueryWrapper<>());
  43. 43. }
  44. 44.
  45. 45. }