Grafana集成到自己的系统

        最近,公司要求要做一个监控系统,除了要有数据监控统计外,还需要做服务资源的监控。我稍微跟公司运维沟通了下,公司有使用grafana+prometheus做监控。

       prometheus是套服务监控系统,自带图表,但图表支持不是很丰富。grafana是个开源的数据可视化工具,有丰富的图片功能,还有警报功能等,刚好可以与prometheus搭配使用。

       一开始打算采用直接调用prometheus的接口+第三方可视化插件进行可视化开发,但发现除了grafana外,没有其他有丰富图表支持的工具,但grafana是独立的一套可视化工具,要在自己的前端里用上可能并不方便。

      后面想了下,前端有个神奇的标签,可以将第三方网页嵌入自己的页面展示,他就是<iframe>,在iframe的src中配置URL地址,即可引用第三方页面。

<iframe src="http//127.0.0.1:3000/d/JsX_vEwGk/dashboard?orgId=1m"></iframe>

      在嵌入链接后,发现无法显示页面,后面查阅资料,发现是两个原因:

     1、grafana需要登录(看运维默认设置是否需要登录)

     2、grafana不允许嵌入

    解决方案:在grafana的配置中允许匿名访问,允许嵌入。

 

grafana配置文件默认在/etc/grafana/grafana.ini

1、允许匿名访问(不需要登录)

[auth.anonymous]

# enable anonymous access

enabled = true

2、允许被嵌入 

allow_embedding = true  

 

但是,公司运维告诉我,grafana映射了外网,必须要设置登录访问!!! 

这样的话,就没那么简单了!

想了一下,发现只能做个代理转发,在代理的过程验证登录后转发到grafana。

方案1:用nginx,配置认证代理。(运维觉得这样他不好管理,就让我自己在我的后端写一个认证代理转发,这个大家看公司要求吧,我这里不采用本方案)

方案2:java做代理,这里用的是 smiley-http-proxy-servlet。

Talk is cheap,show you my code!

 

前端代码:

<div role="tabpanel" class="tab-pane" id="server">
							<div class="embed-responsive embed-responsive-16by9">
								<iframe class="embed-responsive-item" src="/grafana/d/JsX_vEwGk/dashboard?orgId=1m&kiosk" allowfullscreen></iframe>
							</div>
						</div>

这里用了bootstrap,所以加了一些其他样式,让iframe可以响应式显示。

 

application.yml

#配置grafana的代理转发和授权key,key是用于完成Grafana身份认证的,需要事先在Grafana上创建
proxy:
  grafana:
    servlet_url: /grafana/*
    target_url: http://127.0.0.1:3000/grafana
    key: xxxxxxx

授权key的话,让运维提供。

这里有个小技巧:grafana的原URL地址最好配置加多一个路径/grafana/,否则可能出现访问正常,但静态资源加载失败,因为静态资源加载的按当前路径下为父目录。

 

pom.xml

<dependency>
	<groupId>org.mitre.dsmiley.httpproxy</groupId>
	<artifactId>smiley-http-proxy-servlet</artifactId>
	<version>1.11</version>
</dependency>

 

ProxyServletConfiguration.java:

public class ProxyServletConfiguration {
    /**
     * 读取配置文件中路由设置
     */
    @Value("${proxy.grafana.servlet_url}")
    private String servlet_url;
    /**
     * 读取配置中代理目标地址
     */
    @Value("${proxy.grafana.target_url}")
    private String target_url;

    @Bean
    public Servlet createProxyServlet() {
        /** 创建新的ProxyServlet */
        return new GrafanaProxyServlet();
    }

    @Bean
    public ServletRegistrationBean proxyServletRegistration() {
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(createProxyServlet(), servlet_url);
        //设置网址以及参数
        Map<String, String> params = ImmutableMap.of("targetUri", target_url, "log", "true");
        registrationBean.setInitParameters(params);
        return registrationBean;
    }
}

GrafanaProxyServlet.java:
public class GrafanaProxyServlet extends ProxyServlet {

    @Value("${proxy.grafana.key}")
    private String key;

    @Override
    protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse, HttpRequest proxyRequest) throws IOException {
        if (this.doLog) {
            this.log("proxy " + servletRequest.getMethod() + " uri: " + servletRequest.getRequestURI() + " -- " + proxyRequest.getRequestLine().getUri());
        }
        Object userObj = servletRequest.getSession().getAttribute("user");
        log.info("登录拦截器校验 userObj = {}", JsonUtil.getJson().toJson(userObj));

        if(null == userObj){
            return null;
        }

        proxyRequest.setHeader("Authorization", "Basic "+key);
        HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);

        return response;
    }
}

这里我还做了自己系统的登录拦截判断,再执行grafana的代理转发。

 

Grafana集成到自己的系统

大功告成!!!

 

小彩蛋:

grafana的URL地址有个参数:kiosk,分在无该参数、&kiosk=tv、&kiosk的3种情况下,页面会隐藏部分元素,比如可用于隐藏一些下拉框。

上一篇:JAVA 常用方法实例 instanceof 和 类型转换


下一篇:Filter过滤器基础使用