ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/valves/JsonAccessLogValve.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/valves/JsonAccessLogValve.java
Status
scanned
Type
file
Name
JsonAccessLogValve.java
Extension
.java
Programming language
Java
Mime type
text/html
File type
HTML document, ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
11654 (11.4 KB)
MD5
c4e4e5205fe59cacdf796b854894bbac
SHA1
98d4750ac6193cf7fbb412e8eeb171f8896ddd0f
SHA256
4f5bb55056a50a3731420f74c784deaefc22a3a6e419b35f0ee0889257c9843d
SHA512

      
    
SHA1_git
bae58b56114e61f9bdb55971223b1fc75a8ea4da
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
JsonAccessLogValve.java | 11.4 KB |

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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 org.apache.catalina.valves; import java.io.CharArrayWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.tomcat.util.json.JSONFilter; /** * Access log valve derivative that rewrites entries as JSON. * <p> * <b>Important note: the attribute names are not final.</b> * <p> * Patterns are mapped to attributes as followed: * <ul> * <li>a: remoteAddr</li> * <li>A: localAddr</li> * <li>b: size (byteSent: size)</li> * <li>B: byteSentNC</li> * <li>D: elapsedTime</li> * <li>F: firstByteTime</li> * <li>h: host</li> * <li>H: protocol</li> * <li>l: logicalUserName</li> * <li>m: method</li> * <li>p: port</li> * <li>q: query</li> * <li>r: request</li> * <li>s: statusCode</li> * <li>S: sessionId</li> * <li>t: time (dateTime: time)</li> * <li>T: elapsedTimeS</li> * <li>u: user</li> * <li>U: path (requestURI: path)</li> * <li>v: localServerName</li> * <li>I: threadName</li> * <li>X: connectionStatus</li> * <li>%{xxx}a: remoteAddress-xxx</li> * <li>%{xxx}p: port-xxx</li> * <li>%{xxx}t: time-xxx</li> * <li>%{xxx}c: cookies</li> * <li>%{xxx}i: requestHeaders</li> * <li>%{xxx}o: responseHeaders</li> * <li>%{xxx}r: requestAttributes</li> * <li>%{xxx}s: sessionAttributes</li> * <li>%{xxx}L: identifier</li> * </ul> * The attribute list is based on * <a href="https://github.com/fluent/fluentd/blob/master/lib/fluent/plugin/parser_apache2.rb#L72">parser_apache2.rb</a> */ public class JsonAccessLogValve extends AccessLogValve { private static final Map<Character,String> PATTERNS; static { Map<Character,String> pattern2AttributeName = new HashMap<>(); pattern2AttributeName.put(Character.valueOf('a'), "remoteAddr"); pattern2AttributeName.put(Character.valueOf('A'), "localAddr"); pattern2AttributeName.put(Character.valueOf('b'), "size"); pattern2AttributeName.put(Character.valueOf('B'), "byteSentNC"); pattern2AttributeName.put(Character.valueOf('D'), "elapsedTime"); pattern2AttributeName.put(Character.valueOf('F'), "firstByteTime"); pattern2AttributeName.put(Character.valueOf('h'), "host"); pattern2AttributeName.put(Character.valueOf('H'), "protocol"); pattern2AttributeName.put(Character.valueOf('I'), "threadName"); pattern2AttributeName.put(Character.valueOf('l'), "logicalUserName"); pattern2AttributeName.put(Character.valueOf('m'), "method"); pattern2AttributeName.put(Character.valueOf('p'), "port"); pattern2AttributeName.put(Character.valueOf('q'), "query"); pattern2AttributeName.put(Character.valueOf('r'), "request"); pattern2AttributeName.put(Character.valueOf('s'), "statusCode"); pattern2AttributeName.put(Character.valueOf('S'), "sessionId"); pattern2AttributeName.put(Character.valueOf('t'), "time"); pattern2AttributeName.put(Character.valueOf('T'), "elapsedTimeS"); pattern2AttributeName.put(Character.valueOf('u'), "user"); pattern2AttributeName.put(Character.valueOf('U'), "path"); pattern2AttributeName.put(Character.valueOf('v'), "localServerName"); pattern2AttributeName.put(Character.valueOf('X'), "connectionStatus"); PATTERNS = Collections.unmodifiableMap(pattern2AttributeName); } private static final Map<Character,String> SUB_OBJECT_PATTERNS; static { Map<Character,String> pattern2AttributeName = new HashMap<>(); pattern2AttributeName.put(Character.valueOf('c'), "cookies"); pattern2AttributeName.put(Character.valueOf('i'), "requestHeaders"); pattern2AttributeName.put(Character.valueOf('o'), "responseHeaders"); pattern2AttributeName.put(Character.valueOf('r'), "requestAttributes"); pattern2AttributeName.put(Character.valueOf('s'), "sessionAttributes"); pattern2AttributeName.put(Character.valueOf('L'), "identifier"); SUB_OBJECT_PATTERNS = Collections.unmodifiableMap(pattern2AttributeName); } /** * write any char */ protected static class CharElement implements AccessLogElement { private final char ch; public CharElement(char ch) { this.ch = ch; } @Override public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.write(ch); } } private boolean addSubkeyedItems(ListIterator<AccessLogElement> iterator, List<JsonWrappedElement> elements, String patternAttribute) { if (!elements.isEmpty()) { iterator.add(new StringElement("\"" + patternAttribute + "\": {")); for (JsonWrappedElement element : elements) { iterator.add(element); iterator.add(new CharElement(',')); } iterator.previous(); iterator.remove(); iterator.add(new StringElement("},")); return true; } return false; } @Override protected AccessLogElement[] createLogElements() { Map<Character,List<JsonWrappedElement>> subTypeLists = new HashMap<>(); for (Character pattern : SUB_OBJECT_PATTERNS.keySet()) { subTypeLists.put(pattern, new ArrayList<>()); } boolean hasSub = false; List<AccessLogElement> logElements = new ArrayList<>(Arrays.asList(super.createLogElements())); ListIterator<AccessLogElement> lit = logElements.listIterator(); lit.add(new CharElement('{')); while (lit.hasNext()) { AccessLogElement logElement = lit.next(); // remove all other elements, like StringElements if (!(logElement instanceof JsonWrappedElement wrappedLogElement)) { lit.remove(); continue; } // Remove items which should be written as // Json objects and add them later in correct order AccessLogElement ale = wrappedLogElement.getDelegate(); if (ale instanceof HeaderElement) { subTypeLists.get(Character.valueOf('i')).add(wrappedLogElement); lit.remove(); } else if (ale instanceof ResponseHeaderElement) { subTypeLists.get(Character.valueOf('o')).add(wrappedLogElement); lit.remove(); } else if (ale instanceof RequestAttributeElement) { subTypeLists.get(Character.valueOf('r')).add(wrappedLogElement); lit.remove(); } else if (ale instanceof SessionAttributeElement) { subTypeLists.get(Character.valueOf('s')).add(wrappedLogElement); lit.remove(); } else if (ale instanceof CookieElement) { subTypeLists.get(Character.valueOf('c')).add(wrappedLogElement); lit.remove(); } else if (ale instanceof IdentifierElement) { subTypeLists.get(Character.valueOf('L')).add(wrappedLogElement); lit.remove(); } else { // Keep the simple items and add separator lit.add(new CharElement(',')); } } // Add back the items that are output as Json objects for (Character pattern : SUB_OBJECT_PATTERNS.keySet()) { if (addSubkeyedItems(lit, subTypeLists.get(pattern), SUB_OBJECT_PATTERNS.get(pattern))) { hasSub = true; } } // remove last comma (or possibly "},") lit.previous(); lit.remove(); // Last item was a sub object, close it if (hasSub) { lit.add(new StringElement("}}")); } else { lit.add(new CharElement('}')); } return logElements.toArray(new AccessLogElement[0]); } @Override protected AccessLogElement createAccessLogElement(String name, char pattern) { AccessLogElement ale = super.createAccessLogElement(name, pattern); return new JsonWrappedElement(pattern, name, true, ale); } @Override protected AccessLogElement createAccessLogElement(char pattern) { AccessLogElement ale = super.createAccessLogElement(pattern); return new JsonWrappedElement(pattern, true, ale); } private static class JsonWrappedElement implements AccessLogElement, CachedElement { private final CharSequence attributeName; private final boolean quoteValue; private final AccessLogElement delegate; private CharSequence escapeJsonString(CharSequence nonEscaped) { return JSONFilter.escape(nonEscaped); } JsonWrappedElement(char pattern, String key, boolean quoteValue, AccessLogElement delegate) { this.quoteValue = quoteValue; this.delegate = delegate; String patternAttribute = PATTERNS.get(Character.valueOf(pattern)); if (patternAttribute == null) { patternAttribute = "other-" + Character.toString(pattern); } if (key != null && !key.isEmpty()) { if (SUB_OBJECT_PATTERNS.containsKey(Character.valueOf(pattern))) { this.attributeName = escapeJsonString(key); } else { this.attributeName = escapeJsonString(patternAttribute + "-" + key); } } else { this.attributeName = escapeJsonString(patternAttribute); } } JsonWrappedElement(char pattern, boolean quoteValue, AccessLogElement delegate) { this(pattern, null, quoteValue, delegate); } public AccessLogElement getDelegate() { return delegate; } @Override public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.append('"').append(attributeName).append('"').append(':'); if (quoteValue) { buf.append('"'); } delegate.addElement(buf, request, response, time); if (quoteValue) { buf.append('"'); } } @Override public void cache(Request request) { if (delegate instanceof CachedElement) { ((CachedElement) delegate).cache(request); } } } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
11.76
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9
https://github.com/fluent/fluentd/blob/master/lib/fluent/plugin/parser_apache2.rb#L72 72 72