Skip to content

Commit 85edb6c

Browse files
committed
[#9892] Update agent proxy-user plugin for apache format
update update
1 parent 1879c4a commit 85edb6c

File tree

9 files changed

+421
-46
lines changed

9 files changed

+421
-46
lines changed

agent-plugins/proxy-user/README.md

+70-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,79 @@ pinpoint.config
77
#### HTTP headers option.
88
~~~
99
# User-specified HTTP headers
10-
# e.g. profiler.proxy.http.headers=X-Trace, X-Request
10+
# Supports apache and nginx formats.
11+
# e.g. profiler.proxy.http.headers=X-Trace, X-Request, X-ApacheLB, X-SSL-nginx
1112
profiler.proxy.http.headers=
1213
~~~
1314

15+
### Apache HTTP Server
16+
17+
* [http://httpd.apache.org/docs/2.4/en/mod/mod\_headers.html](http://httpd.apache.org/docs/2.4/en/mod/mod_headers.html)
18+
19+
Add HTTP header.
20+
21+
```text
22+
X-ApacheLB: t=991424704447256 D=3775428
23+
```
24+
25+
e.g.
26+
27+
httpd.conf
28+
29+
```text
30+
<IfModule mod_jk.c>
31+
...
32+
RequestHeader set X-ApacheLB "%t %D"
33+
...
34+
</IfModule>
35+
```
36+
37+
**%t is required value.**
38+
39+
### Nginx
40+
41+
* [http://nginx.org/en/docs/http/ngx\_http\_core\_module.html](http://nginx.org/en/docs/http/ngx_http_core_module.html)
42+
* [http://nginx.org/en/docs/http/ngx\_http\_proxy\_module.html\#proxy\_set\_header](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header)
43+
44+
Add HTTP header.
45+
46+
```text
47+
X-SSL-nginx: t=1504248328.423 D=0.123
48+
```
49+
50+
e.g.
51+
52+
nginx.conf
53+
54+
```text
55+
...
56+
server {
57+
listen 9080;
58+
server_name localhost;
59+
60+
location / {
61+
...
62+
set $pinpoint_proxy_header "t=$msec D=$request_time";
63+
proxy_set_header X-SSL-nginx $pinpoint_proxy_header;
64+
}
65+
}
66+
...
67+
```
68+
69+
or
70+
71+
```text
72+
http {
73+
...
74+
75+
proxy_set_header X-SSL-nginx t=$msec;
76+
77+
...
78+
}
79+
```
80+
81+
**t=$msec is required value.**
82+
1483
### Mobile app
1584
Add HTTP header.
1685
~~~

agent-plugins/proxy-user/src/main/java/com/navercorp/pinpoint/agent/plugin/proxy/user/UserRequestParser.java

+67-25
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
import java.util.List;
2828

2929
public class UserRequestParser implements ProxyRequestParser {
30+
static final String PREFIX_RECEIVED = "t=";
31+
static final String PREFIX_DURATION = "D=";
32+
3033
private List<String> headerNameList = Collections.emptyList();
3134

3235
@Override
@@ -44,61 +47,100 @@ public void init(ProfilerConfig profilerConfig) {
4447
if (profilerConfig == null) {
4548
return;
4649
}
47-
this.headerNameList = profilerConfig.readList(UserRequestConstants.USER_PROXY_HEADER_NAME_LIST);
50+
headerNameList = profilerConfig.readList(UserRequestConstants.USER_PROXY_HEADER_NAME_LIST);
4851
}
4952

5053
@Override
5154
public ProxyRequestHeader parseHeader(String name, String value) {
5255
final ProxyRequestHeaderBuilder header = new ProxyRequestHeaderBuilder();
5356
header.setApp(name);
54-
for (String token : StringUtils.tokenizeToStringList(value, " ")) {
55-
if (token.startsWith("t=")) {
56-
final long receivedTimeMillis = toReceivedTimeMillis(token.substring(2));
57-
if (receivedTimeMillis > 0) {
58-
header.setReceivedTimeMillis(receivedTimeMillis);
59-
header.setValid(true);
60-
} else {
61-
header.setValid(false);
62-
header.setCause("invalid received time");
63-
return header.build();
64-
}
65-
} else if (token.startsWith("D=")) {
66-
final long durationTimeMicroseconds = toDurationTimeMicros(token.substring(2));
67-
if (durationTimeMicroseconds > 0) {
68-
header.setDurationTimeMicroseconds((int) durationTimeMicroseconds);
69-
}
57+
58+
final List<String> tokenList = StringUtils.tokenizeToStringList(value, " ");
59+
final String receivedTimeValue = findValue(tokenList, PREFIX_RECEIVED);
60+
if (receivedTimeValue != null) {
61+
final long receivedTimeMillis = toReceivedTimeMillis(receivedTimeValue);
62+
if (receivedTimeMillis > 0) {
63+
header.setReceivedTimeMillis(receivedTimeMillis);
64+
header.setValid(true);
65+
} else {
66+
header.setValid(false);
67+
header.setCause("invalid received time");
68+
return header.build();
69+
}
70+
} else {
71+
header.setValid(false);
72+
header.setCause("not found received time");
73+
return header.build();
74+
}
75+
final String durationTimeValue = findValue(tokenList, PREFIX_DURATION);
76+
if (durationTimeValue != null) {
77+
final long durationTimeMicroseconds = toDurationTimeMicros(durationTimeValue);
78+
if (durationTimeMicroseconds > 0) {
79+
header.setDurationTimeMicroseconds((int) durationTimeMicroseconds);
7080
}
7181
}
7282

7383
return header.build();
7484
}
7585

76-
public long toReceivedTimeMillis(final String value) {
86+
String findValue(List<String> tokenList, String prefix) {
87+
for (String token : tokenList) {
88+
if (token.startsWith(prefix)) {
89+
return token.substring(prefix.length());
90+
}
91+
}
92+
return null;
93+
}
94+
95+
long toReceivedTimeMillis(final String value) {
7796
if (value == null) {
7897
return 0;
7998
}
8099

81100
final int length = value.length();
101+
if (length < 13) {
102+
return 0;
103+
}
82104

105+
if (length >= 16) {
106+
// apache - microseconds
107+
return NumberUtils.parseLong(value.substring(0, length - 3), 0);
108+
}
83109
final int millisPosition = value.lastIndexOf('.');
84110
if (millisPosition != -1) {
85-
if (length - millisPosition != 4) {
111+
// nginx - seconds.milliseconds
112+
// e.g. 1504230492.763
113+
if (millisPosition < 10 || length - millisPosition != 4) {
86114
// invalid format.
87115
return 0;
88116
}
89-
String strValue = value.substring(0, millisPosition) + value.substring(millisPosition + 1);
117+
final String strValue = value.substring(0, millisPosition) + value.substring(millisPosition + 1);
90118
return NumberUtils.parseLong(strValue, 0);
91-
}else {
92-
return NumberUtils.parseLong(value, 0);
93119
}
120+
// app - milliseconds
121+
return NumberUtils.parseLong(value, 0);
94122
}
95123

96-
public int toDurationTimeMicros(final String value) {
124+
int toDurationTimeMicros(final String value) {
97125
if (value == null) {
98126
return 0;
99127
}
100128

101-
// to microseconds.
102-
return NumberUtils.parseInteger(value, 0);
129+
final int length = value.length();
130+
final int millisPosition = value.lastIndexOf('.');
131+
if (millisPosition != -1) {
132+
// nginx
133+
// e.g. 0.000
134+
if (length - millisPosition != 4) {
135+
// invalid format.
136+
return 0;
137+
}
138+
final String strValue = value.substring(0, millisPosition) + value.substring(millisPosition + 1);
139+
return NumberUtils.parseInteger(strValue, 0) * 1000;
140+
} else {
141+
// apache, app
142+
// to microseconds.
143+
return NumberUtils.parseInteger(value, 0);
144+
}
103145
}
104146
}

agent-plugins/proxy-user/src/test/java/com/navercorp/pinpoint/agent/plugin/proxy/user/UserRequestParserTest.java

+68-16
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,38 @@
2222
import static org.assertj.core.api.Assertions.assertThat;
2323

2424
public class UserRequestParserTest {
25+
static final String HEADER_NAME = "X-LB-SSL";
2526

2627
@Test
2728
public void parse() {
2829
UserRequestParser parser = new UserRequestParser();
2930
String value = "t=1625212448369 D=123";
30-
ProxyRequestHeader proxyHttpHeader = parser.parseHeader("HEADER_NAME", value);
31+
ProxyRequestHeader proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
3132
assertThat(proxyHttpHeader.isValid()).isTrue();
3233
assertThat(1625212448369L).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
3334
assertThat(123L).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
34-
assertThat("HEADER_NAME").isEqualTo(proxyHttpHeader.getApp());
35+
assertThat(HEADER_NAME).isEqualTo(proxyHttpHeader.getApp());
36+
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
37+
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
38+
39+
// apache
40+
final long currentTimeMillis = System.currentTimeMillis();
41+
value = "t=" + currentTimeMillis + "999" + " D=12345";
42+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
43+
assertThat(proxyHttpHeader.isValid()).isTrue();
44+
assertThat(currentTimeMillis).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
45+
assertThat(12345).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
46+
assertThat(HEADER_NAME).isEqualTo(proxyHttpHeader.getApp());
47+
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
48+
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
49+
50+
// nginx
51+
value = "t=1504248328.423 D=0.123";
52+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
53+
assertThat(proxyHttpHeader.isValid()).isTrue();
54+
assertThat(1504248328423L).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
55+
assertThat(123000L).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
56+
assertThat(HEADER_NAME).isEqualTo(proxyHttpHeader.getApp());
3557
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
3658
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
3759
}
@@ -40,10 +62,31 @@ public void parse() {
4062
public void parseOnlyReceivedTime() {
4163
UserRequestParser parser = new UserRequestParser();
4264
String value = "t=1625212448369";
43-
ProxyRequestHeader proxyHttpHeader = parser.parseHeader("HEADER_NAME", value);
65+
ProxyRequestHeader proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
4466
assertThat(proxyHttpHeader.isValid()).isTrue();
4567
assertThat(1625212448369L).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
4668
assertThat(-1).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
69+
assertThat(HEADER_NAME).isEqualTo(proxyHttpHeader.getApp());
70+
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
71+
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
72+
73+
// apache
74+
final long currentTimeMillis = System.currentTimeMillis();
75+
value = "t=" + currentTimeMillis + "999";
76+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
77+
assertThat(currentTimeMillis).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
78+
assertThat(-1).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
79+
assertThat(HEADER_NAME).isEqualTo(proxyHttpHeader.getApp());
80+
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
81+
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
82+
83+
// nginx
84+
value = "t=1504248328.423";
85+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
86+
assertThat(proxyHttpHeader.isValid()).isTrue();
87+
assertThat(1504248328423L).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
88+
assertThat(-1).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
89+
assertThat(HEADER_NAME).isEqualTo(proxyHttpHeader.getApp());
4790
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
4891
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
4992
}
@@ -52,26 +95,35 @@ public void parseOnlyReceivedTime() {
5295
public void parseNotFoundReceived() {
5396
UserRequestParser parser = new UserRequestParser();
5497
String value = "D=123";
55-
ProxyRequestHeader proxyHttpHeader = parser.parseHeader("HEADER_NAME", value);
98+
ProxyRequestHeader proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
5699
assertThat(proxyHttpHeader.isValid()).isFalse();
57100
}
58101

59-
@Test
60-
public void parseReceivedSeconds() {
61-
UserRequestParser parser = new UserRequestParser();
62-
String value = "t=1625212448.369";
63-
ProxyRequestHeader proxyHttpHeader = parser.parseHeader("HEADER_NAME", value);
64-
assertThat(1625212448369L).isEqualTo(proxyHttpHeader.getReceivedTimeMillis());
65-
assertThat(-1).isEqualTo(proxyHttpHeader.getDurationTimeMicroseconds());
66-
assertThat(-1).isEqualTo(proxyHttpHeader.getIdlePercent());
67-
assertThat(-1).isEqualTo(proxyHttpHeader.getBusyPercent());
68-
}
69-
70102
@Test
71103
public void parseInvalidReceived() {
72104
UserRequestParser parser = new UserRequestParser();
73105
String value = "t=1625212448:369";
74-
ProxyRequestHeader proxyHttpHeader = parser.parseHeader("HEADER_NAME", value);
106+
ProxyRequestHeader proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
107+
assertThat(proxyHttpHeader.isValid()).isFalse();
108+
109+
value = "t=alpha-1625212448369";
110+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
111+
assertThat(proxyHttpHeader.isValid()).isFalse();
112+
113+
value = "t=-1625212448369";
114+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
115+
assertThat(proxyHttpHeader.isValid()).isFalse();
116+
117+
value = "t=1000";
118+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
119+
assertThat(proxyHttpHeader.isValid()).isFalse();
120+
121+
value = "t=-16252124483691784578975972957897594795479379";
122+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
123+
assertThat(proxyHttpHeader.isValid()).isFalse();
124+
125+
value = "t=123.456";
126+
proxyHttpHeader = parser.parseHeader(HEADER_NAME, value);
75127
assertThat(proxyHttpHeader.isValid()).isFalse();
76128
}
77129
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<project xmlns="http://maven.apache.org/POM/4.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
<parent>
8+
<groupId>com.navercorp.pinpoint</groupId>
9+
<artifactId>pinpoint-agent-testweb</artifactId>
10+
<version>2.6.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>pinpoint-agent-proxy-plugin-testweb</artifactId>
14+
15+
<packaging>jar</packaging>
16+
17+
<properties>
18+
<pinpoint.agent.jvmargument>
19+
${pinpoint.agent.default.jvmargument}
20+
</pinpoint.agent.jvmargument>
21+
</properties>
22+
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-webflux</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-autoconfigure</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>com.navercorp.pinpoint</groupId>
34+
<artifactId>pinpoint-agent-testweb-commons</artifactId>
35+
</dependency>
36+
</dependencies>
37+
38+
</project>

0 commit comments

Comments
 (0)