Skip to content

Commit 77ea29a

Browse files
committed
[SCB-2897] add accesslog and requestlog for WebSocket
1 parent 18a2ce1 commit 77ea29a

File tree

10 files changed

+550
-32
lines changed

10 files changed

+550
-32
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.servicecomb.common.accessLog.ws;
19+
20+
import com.netflix.config.DynamicPropertyFactory;
21+
22+
public class WebSocketAccessLogConfig {
23+
private static final String BASE = "servicecomb.accesslog.ws.";
24+
25+
private static final String SERVER_BASE = BASE + "server.";
26+
27+
private static final String CLIENT_BASE = BASE + "client.";
28+
29+
private static final String SERVER_LOG_ENABLED = SERVER_BASE + "enabled";
30+
31+
private static final String CLIENT_LOG_ENABLED = CLIENT_BASE + "enabled";
32+
33+
private boolean serverLogEnabled;
34+
35+
private boolean clientLogEnabled;
36+
37+
public static final WebSocketAccessLogConfig INSTANCE = new WebSocketAccessLogConfig();
38+
39+
private WebSocketAccessLogConfig() {
40+
clientLogEnabled = DynamicPropertyFactory
41+
.getInstance().getBooleanProperty(CLIENT_LOG_ENABLED, false).get();
42+
serverLogEnabled = DynamicPropertyFactory
43+
.getInstance().getBooleanProperty(SERVER_LOG_ENABLED, false).get();
44+
}
45+
46+
public boolean isServerLogEnabled() {
47+
return serverLogEnabled;
48+
}
49+
50+
public boolean isClientLogEnabled() {
51+
return clientLogEnabled;
52+
}
53+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.servicecomb.common.accessLog.ws;
19+
20+
import java.text.SimpleDateFormat;
21+
import java.util.Date;
22+
import java.util.Locale;
23+
import java.util.TimeZone;
24+
25+
import org.apache.servicecomb.core.event.WebSocketActionEvent;
26+
27+
/**
28+
* Similar to {@link org.apache.servicecomb.common.accessLog.core.AccessLogGenerator},
29+
* this is an access log generator for WebSocket protocol.
30+
*/
31+
public class WebSocketAccessLogGenerator {
32+
33+
public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
34+
35+
public static final Locale DEFAULT_LOCALE = Locale.US;
36+
37+
public static final TimeZone TIME_ZONE = TimeZone.getDefault();
38+
39+
private final ThreadLocal<SimpleDateFormat> datetimeFormatHolder = new ThreadLocal<>();
40+
41+
public String generateServerLog(WebSocketActionEvent actionEvent) {
42+
return generateLog(actionEvent);
43+
}
44+
45+
public String generateClientLog(WebSocketActionEvent actionEvent) {
46+
return generateLog(actionEvent);
47+
}
48+
49+
private String generateLog(WebSocketActionEvent actionEvent) {
50+
return actionEvent.getInvocationType()
51+
+ "|"
52+
+ actionEvent.getOperationMeta().getMicroserviceQualifiedName()
53+
+ "|"
54+
+ formatTimestampToDateTimeStr(actionEvent.getActionStartTimestamp())
55+
+ "|"
56+
+ actionEvent.getTraceId()
57+
+ "|"
58+
+ actionEvent.getConnectionId()
59+
+ "|"
60+
+ actionEvent.getActionType()
61+
+ "|"
62+
+ (actionEvent.getActionStartTimestamp() - actionEvent.getScheduleStartTimestamp())
63+
+ "|"
64+
+ actionEvent.getActionTimeCostMillis()
65+
+ "|"
66+
+ actionEvent.getHandleThreadName()
67+
+ "|"
68+
+ actionEvent.getDataSize();
69+
}
70+
71+
private String formatTimestampToDateTimeStr(long timestamp) {
72+
return getDatetimeFormat()
73+
.format(new Date(timestamp));
74+
}
75+
76+
private SimpleDateFormat getDatetimeFormat() {
77+
SimpleDateFormat dateFormat = datetimeFormatHolder.get();
78+
if (null == dateFormat) {
79+
dateFormat = new SimpleDateFormat(DEFAULT_DATETIME_PATTERN, DEFAULT_LOCALE);
80+
dateFormat.setTimeZone(TIME_ZONE);
81+
82+
datetimeFormatHolder.set(dateFormat);
83+
}
84+
85+
return dateFormat;
86+
}
87+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.servicecomb.common.accessLog.ws;
19+
20+
import org.apache.servicecomb.common.accessLog.AccessLogConfig;
21+
import org.apache.servicecomb.common.accessLog.AccessLogInitializer;
22+
import org.apache.servicecomb.core.event.WebSocketActionEvent;
23+
import org.apache.servicecomb.swagger.invocation.InvocationType;
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
26+
27+
import com.google.common.eventbus.AllowConcurrentEvents;
28+
import com.google.common.eventbus.EventBus;
29+
import com.google.common.eventbus.Subscribe;
30+
31+
public class WebSocketAccessLogInitializer implements AccessLogInitializer {
32+
private static final Logger ACCESS_LOG_LOGGER = LoggerFactory.getLogger("ws.accesslog");
33+
34+
private static final Logger REQUEST_LOG_LOGGER = LoggerFactory.getLogger("ws.requestlog");
35+
36+
private WebSocketAccessLogGenerator accessLogGenerator;
37+
38+
private boolean clientLogEnabled;
39+
40+
private boolean serverLogEnabled;
41+
42+
@Override
43+
public void init(EventBus eventBus, AccessLogConfig accessLogConfig) {
44+
WebSocketAccessLogConfig config = WebSocketAccessLogConfig.INSTANCE;
45+
clientLogEnabled = config.isClientLogEnabled();
46+
serverLogEnabled = config.isServerLogEnabled();
47+
if (clientLogEnabled || serverLogEnabled) {
48+
accessLogGenerator = new WebSocketAccessLogGenerator();
49+
eventBus.register(this);
50+
}
51+
}
52+
53+
@Subscribe
54+
@AllowConcurrentEvents
55+
public void onRequestReceived(WebSocketActionEvent actionEvent) {
56+
if (actionEvent == null) {
57+
return;
58+
}
59+
InvocationType invocationType = actionEvent.getInvocationType();
60+
if (invocationType == null) {
61+
return;
62+
}
63+
64+
switch (invocationType) {
65+
case CONSUMER:
66+
if (clientLogEnabled) {
67+
REQUEST_LOG_LOGGER.info(accessLogGenerator.generateClientLog(actionEvent));
68+
}
69+
break;
70+
case PRODUCER: {
71+
if (serverLogEnabled) {
72+
ACCESS_LOG_LOGGER.info(accessLogGenerator.generateServerLog(actionEvent));
73+
}
74+
break;
75+
}
76+
default:
77+
throw new IllegalStateException("unexpected websocket invocation type: " + invocationType);
78+
}
79+
}
80+
}

common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.common.accessLog.AccessLogInitializer

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717

1818
org.apache.servicecomb.common.accessLog.client.ClientDefaultInitializer
1919
org.apache.servicecomb.common.accessLog.server.ServerDefaultInitializer
20+
org.apache.servicecomb.common.accessLog.ws.WebSocketAccessLogInitializer

0 commit comments

Comments
 (0)