Spring Boot : Count Page Views - Actuators

前端 未结 2 695
刺人心
刺人心 2021-01-26 20:51

I have a requirement to count the views on each endpoint. The idea is to create one common Request Count Mapping for all endpoints which should return the view count based on a

相关标签:
2条回答
  • 2021-01-26 20:54

    So you want to encapsulate actuator/metrics with /admin/count

    There are many ways and library for calling Rest API in Java

    I will add the simplest one

    Something like this

    public JSONObject sendRequestToURL(@PathVariable("finalURL") String urlToRead)
    {
          StringBuilder result = new StringBuilder();
          URL url = new URL(urlToRead);
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setRequestMethod("GET");
          BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
          String line;
          while ((line = rd.readLine()) != null) {
             result.append(line);
          }
          rd.close();
          return new JSONObject(result.toString());  // org.json
    }
    

    Edit 1:

    You are almost there. Just need to parse String to JSONObject. Try this maybe

    String strJson = result.toString().replace("\\\"","'");
    JSONObject jo = new JSONObject(strJson.substring(1,json.length()-1));
    return jo;
    

    Edit 2:

    I guess you have Spring Security in place.

    And when you are calling an API internally, Spring is treating as an external call which requires Authentication.

    As a workaround, you can exclude /actuator API from security context.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
         .antMatchers("/actuator*").permitAll()
    
         ...
    }
    

    or in XML

    <security:http  auto-config="true"  use-expressions="true"   >
        <security:intercept-url pattern="/actuator*" access="permitAll"/>
    
        ...
    </security:http>
    

    And hopefully Spring security will ignore this URL and you will not get Login Form.

    0 讨论(0)
  • 2021-01-26 21:18

    The idea is you will get the endPoint from user to display to show the view counts which will be done using @RequestParam. Based on the request endPoint create the URLtoMap according to your requirements

    (i.e methods, status, outcome, exception etc, e.g. http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/user/101&tag=method:GET).


    @RequestMapping(path="/admin/count",method=RequestMethod.POST)
        public int count(@RequestParam(name="endPoint") final String endPoint) throws IOException, JSONException
        {
            final String URLtoMap = "http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:" + endPoint + "";
            return sendRequestToURL(URLtoMap);
        }
    

    Now Based on the URLtoMap send Request using HttpURLConnection and get the output using BufferedReader. As I am using Spring Security I was redirected to Login Page. To solve the problem I have added antMatchers in SecurityConfig file as below. If you facing JSONException: Value of type java.lang.String cannot be converted to JSONObject then refer this

    public int sendRequestToURL(@PathVariable("URLtoMap") String URLtoMap) throws IOException, JSONException
    {
          int count = 0;
          StringBuilder result = new StringBuilder();
          URL url = new URL(URLtoMap);
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setRequestMethod("GET");
          BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
          String line;
          while ((line = rd.readLine()) != null) {
             result.append(line);
          }
          rd.close();
    
          try {
                JSONObject jsonObject =new JSONObject(result.toString().replace("\"", "")); 
                JSONObject jsonCountObject = new JSONObject(jsonObject.getJSONArray("measurements").get(0).toString());
                count =(int) jsonCountObject.get("value");
            }
            catch (JSONException e) {
                e.printStackTrace();
            }
    
          return count;
    }
    

    SecurityConfig

    @Override
            protected void configure(HttpSecurity http) throws Exception{
    
                 http
                 .csrf().disable()
                 .authorizeRequests().antMatchers("/login").permitAll()
                 .antMatchers(HttpMethod.GET,"/actuator/**").permitAll() 
                 .antMatchers(HttpMethod.POST,"/actuator/**").permitAll() 
    }
    

    pom.xml

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>
    
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    
    <dependency>
      <groupId>org.json</groupId>
      <artifactId>json</artifactId>
      <version>20090211</version>
    </dependency>
    

    Import the Correct Packages

    import org.json.JSONException;
    import org.json.JSONObject;
    import java.net.URL;
    import java.net.HttpURLConnection;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    0 讨论(0)
提交回复
热议问题