Skip to content

Commit

Permalink
add http_access log in HttpInvokeHelperImpl (#76)
Browse files Browse the repository at this point in the history
* add http_access log in HttpInvokeHelperImpl

---------

Co-authored-by: zeyu10 <[email protected]>
  • Loading branch information
techloghub and zeyu10 authored Aug 7, 2024
1 parent 5e0adb0 commit 98a347f
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.weibo.rill.flow.impl.service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.weibo.rill.flow.common.exception.TaskException;
import com.weibo.rill.flow.common.model.BizError;
Expand All @@ -27,14 +28,17 @@
import com.weibo.rill.flow.service.auth.AuthHeaderGenerator;
import com.weibo.rill.flow.service.invoke.HttpInvokeHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
Expand All @@ -51,6 +55,8 @@ public class HttpInvokeHelperImpl implements HttpInvokeHelper {
@Qualifier("authHeaderGenerator")
private AuthHeaderGenerator authHeaderGenerator;

private final Logger httpAccessLogger = LoggerFactory.getLogger("httpclientaccess");

@Override
public void appendRequestHeader(HttpHeaders httpHeaders, String executionId, TaskInfo task, Map<String, Object> input) {
authHeaderGenerator.appendRequestHeader(httpHeaders, executionId, task, input);
Expand Down Expand Up @@ -128,20 +134,47 @@ public String invokeRequest(String executionId, String taskInfoName, String url,
RestTemplate restTemplate = defaultRestTemplate;
String cause = null;
for (int i = 1; i <= maxInvokeTime; i++) {
long startTime = System.currentTimeMillis();
ResponseEntity<String> responseEntity = null;
try {
String result;
if (method == HttpMethod.GET) {
result = restTemplate.getForObject(url, String.class);
responseEntity = restTemplate.exchange(new URI(url), method, requestEntity, String.class);
} else {
result = restTemplate.postForObject(new URI(url), requestEntity, String.class);
responseEntity = restTemplate.postForEntity(new URI(url), requestEntity, String.class);
}
return result;
} catch (RestClientResponseException e) {
throw e;
return responseEntity.getBody();
} catch (Exception e) {
cause = e.getMessage();
} finally {
postHttpProcess(url, requestEntity, method, System.currentTimeMillis() - startTime, responseEntity);
}
}
throw new TaskException(BizError.ERROR_INVOKE_URI.getCode(), String.format("dispatchTask http fails due to %s", cause));
}


private void postHttpProcess(String url, HttpEntity<?> requestEntity, HttpMethod method, long timeout, ResponseEntity<String> responseEntity) {
try {
int code = responseEntity == null ? 500 : responseEntity.getStatusCode().value();
// 打印 http_access 日志
Object requestBody = parseBodyForHttpAccessLog(requestEntity.getBody());
String responseBody = (responseEntity == null || responseEntity.getBody() == null) ? "" : responseEntity.getBody();
int responseLength = responseBody.length();
responseBody = StringUtils.substring(responseBody, 0, 1000);
httpAccessLogger.info("{} {} {} {} {} {} {}", timeout, method, code, responseLength, url, requestBody, responseBody);
} catch (Exception e) {
log.warn("httpAccess log error", e);
}
}

private Object parseBodyForHttpAccessLog(Object body) {
try {
if (body instanceof Map) {
return new JSONObject((Map<String, Object>) body).toJSONString();
}
} catch (Exception e) {
log.warn("parseBodyForHttpAccessLog error: ", e);
}
return body;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package com.weibo.rill.flow.impl.service


import com.weibo.rill.flow.common.exception.TaskException
import com.weibo.rill.flow.service.invoke.HttpInvokeHelper
import org.springframework.http.HttpEntity
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.client.RestClientResponseException
import org.springframework.web.client.RestTemplate
import spock.lang.Specification
import spock.lang.Unroll

class HttpInvokeHelperImplTest extends Specification {
HttpInvokeHelper httpInvokeHelper = new HttpInvokeHelperImpl()
RestTemplate defaultRestTemplate = Mock(RestTemplate)
HttpInvokeHelper httpInvokeHelper = new HttpInvokeHelperImpl(defaultRestTemplate: defaultRestTemplate)

@Unroll
def "functionRequestParams test"() {
Expand All @@ -30,4 +37,45 @@ class HttpInvokeHelperImplTest extends Specification {
['query': ['user': 'Bob'], 'header': ['content-type': 'application/x-www-form-urlencoded'], 'body': ['title': 'first post']] || ['execution_id': "xxx", 'name': "testFunctionRequestParams", 'user': 'Bob'] | ['execution_id': "xxx", 'title': 'first post'] | ['content-type': 'application/x-www-form-urlencoded']
['input_num': 10, 'query': ['user': 'Bob'], 'header': ['content-type': 'application/x-www-form-urlencoded'], 'body': ['title': 'first post']] || ['execution_id': "xxx", 'name': "testFunctionRequestParams", 'user': 'Bob'] | ['execution_id': "xxx", 'input_num': 10, 'title': 'first post'] | ['content-type': 'application/x-www-form-urlencoded']
}

@Unroll
def "test invokeRequest"() {
when:
ResponseEntity<String> responseEntity = new ResponseEntity<>("response body", HttpStatus.OK)
HttpEntity<?> requestEntity = new HttpEntity<>(Map.of("data", "hello world"), null)
defaultRestTemplate.exchange(*_) >> responseEntity
defaultRestTemplate.postForEntity(*_) >> responseEntity
then:
httpInvokeHelper.invokeRequest("testExecutionId", "testTaskName",
"http://localhost:8080/testurl", requestEntity, HttpMethod.GET, 1) == "response body"
httpInvokeHelper.invokeRequest("testExecutionId", "testTaskName",
"http://localhost:8080/testurl", requestEntity, HttpMethod.POST, 1) == "response body"
}

@Unroll
def "test invokeRequest return null"() {
when:
ResponseEntity<String> responseEntity = new ResponseEntity<>(null, HttpStatus.BAD_GATEWAY)
HttpEntity<?> requestEntity = new HttpEntity<>(null, null)
defaultRestTemplate.exchange(*_) >> responseEntity
defaultRestTemplate.postForEntity(*_) >> responseEntity
then:
noExceptionThrown()
httpInvokeHelper.invokeRequest("testExecutionId", "testTaskName",
"http://localhost:8080/testurl", requestEntity, HttpMethod.GET, 1) == null
httpInvokeHelper.invokeRequest("testExecutionId", "testTaskName",
"http://localhost:8080/testurl", requestEntity, HttpMethod.POST, 1) == null
}

@Unroll
def "test invokeRequest throw exception"() {
given:
HttpEntity<?> requestEntity = new HttpEntity<>(null, null)
defaultRestTemplate.exchange(*_) >> { throw new RestClientResponseException("Bad Gateway Timeout", 504, "Bad Gateway Timeout", null, null, null) }
when:
httpInvokeHelper.invokeRequest("testExecutionId", "testTaskName",
"http://localhost:8080/testurl", requestEntity, HttpMethod.GET, 1)
then:
thrown(TaskException.class)
}
}

0 comments on commit 98a347f

Please sign in to comment.