Skip to content

Commit

Permalink
Implement AccessLog support for HTTP/2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
AzeemMuzammil committed May 21, 2024
1 parent 1725057 commit a8d6a34
Show file tree
Hide file tree
Showing 16 changed files with 653 additions and 18 deletions.
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ modules = [
[[package]]
org = "ballerina"
name = "observe"
version = "1.2.2"
version = "1.2.3"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]
Expand Down
4 changes: 4 additions & 0 deletions ballerina/http_log_manager.bal
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ public type TraceLogAdvancedConfiguration record {|
# Represents HTTP access log configuration.
#
# + console - Boolean value to enable or disable console access logs
# + format - The format of access logs to be printed (either `flat` or `json`)
# + attributes - The list of attributes of access logs to be printed
# + path - Optional file path to store access logs
public type AccessLogConfiguration record {|
boolean console = false;
string format = "flat";
string[] attributes?;
string path?;
|};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,12 @@ public final class HttpConstants {
public static final String HTTP_TRACE_LOG_ENABLED = "http.tracelog.enabled";
public static final String HTTP_ACCESS_LOG = "http.accesslog";
public static final String HTTP_ACCESS_LOG_ENABLED = "http.accesslog.enabled";
public static final String HTTP_LOG_FORMAT_JSON = "json";

// TraceLog and AccessLog configs
public static final BString HTTP_LOG_CONSOLE = StringUtils.fromString("console");
public static final BString HTTP_LOG_FORMAT = StringUtils.fromString("format");
public static final BString HTTP_LOG_ATTRIBUTES = StringUtils.fromString("attributes");
public static final BString HTTP_LOG_FILE_PATH = StringUtils.fromString("path");
public static final BString HTTP_TRACE_LOG_HOST = StringUtils.fromString("host");
public static final BString HTTP_TRACE_LOG_PORT = StringUtils.fromString("port");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import io.ballerina.runtime.api.values.BMap;
import io.ballerina.runtime.api.values.BString;
import io.ballerina.stdlib.http.api.logging.accesslog.HttpAccessLogConfig;
import io.ballerina.stdlib.http.api.logging.formatters.HttpAccessLogFormatter;
import io.ballerina.stdlib.http.api.logging.formatters.HttpTraceLogFormatter;
import io.ballerina.stdlib.http.api.logging.formatters.JsonLogFormatter;
Expand Down Expand Up @@ -70,6 +71,7 @@ public HttpLogManager(boolean traceLogConsole, BMap traceLogAdvancedConfig, BMap
this.protocol = protocol.getValue();
this.setHttpTraceLogHandler(traceLogConsole, traceLogAdvancedConfig);
this.setHttpAccessLogHandler(accessLogConfig);
HttpAccessLogConfig.initializeHttpAccessLogConfig(accessLogConfig);
}

/**
Expand Down Expand Up @@ -166,5 +168,4 @@ public void setHttpAccessLogHandler(BMap accessLogConfig) {
stdErr.println("ballerina: " + protocol + " access log enabled");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.ballerina.stdlib.http.api.logging.accesslog;

import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BMap;
import io.ballerina.runtime.api.values.BString;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static io.ballerina.stdlib.http.api.HttpConstants.HTTP_LOG_ATTRIBUTES;
import static io.ballerina.stdlib.http.api.HttpConstants.HTTP_LOG_FORMAT;
import static io.ballerina.stdlib.http.api.HttpConstants.HTTP_LOG_FORMAT_JSON;

public class HttpAccessLogConfig {
private static final Set<String> EXCLUDED_ATTRIBUTES = new HashSet<>(List.of(
"http_referrer", "http_user_agent", "http_x_forwarded_for"
));
private static BMap accessLogConfig = null;

public static void initializeHttpAccessLogConfig(BMap accessLogConfigFromBallerina) {
accessLogConfig = accessLogConfigFromBallerina;
}

public static List<String> getCustomHeaders() {
List<String> attributes = getAccessLogAttributes();
if (attributes == null) {
return Collections.emptyList();
}

return attributes.stream()
.filter(attr -> attr.startsWith("http_") && !EXCLUDED_ATTRIBUTES.contains(attr))
.map(attr -> attr.substring(5))
.collect(Collectors.toList());
}

public static HttpAccessLogFormat getAccessLogFormat() {
BString logFormat = accessLogConfig.getStringValue(HTTP_LOG_FORMAT);
if (logFormat.getValue().equals(HTTP_LOG_FORMAT_JSON)) {
return HttpAccessLogFormat.JSON;
}
return HttpAccessLogFormat.FLAT;
}

public static List<String> getAccessLogAttributes() {
BArray logAttributes = accessLogConfig.getArrayValue(HTTP_LOG_ATTRIBUTES);
if (logAttributes != null) {
return Arrays.stream(logAttributes.getStringArray())
.collect(Collectors.toList());
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package io.ballerina.stdlib.http.api.logging.accesslog;

public enum HttpAccessLogFormat {
FLAT, JSON
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package io.ballerina.stdlib.http.api.logging.accesslog;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

public class HttpAccessLogMessage {
private String ip;
private Calendar dateTime;
private String requestMethod;
private String requestUri;
private String scheme;
private int status;
private long requestBodySize;
private long responseBodySize;
private long requestTime;
private String httpReferrer;
private String httpUserAgent;
private String httpXForwardedFor;
private String host;
private int port;
private Map<String, String> customHeaders;

public HttpAccessLogMessage() {
this.customHeaders = new HashMap<>();
}

public HttpAccessLogMessage(String ip, Calendar dateTime, String requestMethod, String requestUri, String scheme,
int status, long responseBodySize, String httpReferrer, String httpUserAgent) {
this.ip = ip;
this.dateTime = dateTime;
this.requestMethod = requestMethod;
this.requestUri = requestUri;
this.scheme = scheme;
this.status = status;
this.responseBodySize = responseBodySize;
this.httpReferrer = httpReferrer;
this.httpUserAgent = httpUserAgent;
this.customHeaders = new HashMap<>();
}

public Calendar getDateTime() {
return dateTime;
}

public void setDateTime(Calendar dateTime) {
this.dateTime = dateTime;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public String getRequestMethod() {
return requestMethod;
}

public void setRequestMethod(String requestMethod) {
this.requestMethod = requestMethod;
}

public String getRequestUri() {
return requestUri;
}

public void setRequestUri(String requestUri) {
this.requestUri = requestUri;
}

public String getScheme() {
return scheme;
}

public void setScheme(String scheme) {
this.scheme = scheme;
}

public int getStatus() {
return status;
}

public void setStatus(int status) {
this.status = status;
}

public long getRequestBodySize() {
return requestBodySize;
}

public void setRequestBodySize(Long requestBodySize) {
this.requestBodySize = requestBodySize;
}

public long getResponseBodySize() {
return responseBodySize;
}

public void setResponseBodySize(Long responseBodySize) {
this.responseBodySize = responseBodySize;
}

public long getRequestTime() {
return requestTime;
}

public void setRequestTime(Long requestTime) {
this.requestTime = requestTime;
}

public String getHttpUserAgent() {
return httpUserAgent;
}

public String getHttpReferrer() {
return httpReferrer;
}

public void setHttpReferrer(String httpReferrer) {
this.httpReferrer = httpReferrer;
}

public void setHttpUserAgent(String httpUserAgent) {
this.httpUserAgent = httpUserAgent;
}

public String getHttpXForwardedFor() {
return httpXForwardedFor;
}

public void setHttpXForwardedFor(String httpXForwardedFor) {
this.httpXForwardedFor = httpXForwardedFor;
}

public String getHost() {
return this.host;
}

public void setHost(String host) {
this.host = host;
}

public int getPort() {
return this.port;
}

public void setPort(int port) {
this.port = port;
}

public Map<String, String> getCustomHeaders() {
return customHeaders;
}

public void setCustomHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
}

public void putCustomHeader(String headerKey, String headerValue) {
this.customHeaders.put(headerKey, headerValue);
}
}
Loading

0 comments on commit a8d6a34

Please sign in to comment.