1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.loganalysis.util; 17 18 import java.util.LinkedList; 19 import java.util.List; 20 import java.util.ListIterator; 21 22 /** 23 * A utility class for storing a part of the log for retrieval later. 24 * <p> 25 * Stores that last N lines in a ring buffer along with an id. At a later time, the last X lines 26 * or that last Y lines which match a given id can be retrieved. For example, this class can be 27 * used to retrieve the last 15 lines of logcat or the last 15 lines of logcat matching a given PID 28 * from before when an event occurred. 29 * </p> 30 */ 31 public class LogTailUtil { 32 private LinkedList<LogLine> mRingBuffer = new LinkedList<LogLine>(); 33 private int mMaxBufferSize; 34 private int mLastTailSize; 35 private int mIdTailSize; 36 37 /** 38 * Store a line and id for retrieval later. 39 */ 40 private class LogLine { 41 public Integer mId = null; 42 public String mLine = null; 43 LogLine(Integer id, String line)44 public LogLine(Integer id, String line) { 45 mId = id; 46 mLine = line; 47 } 48 } 49 50 /** 51 * Constructor for {@link LogTailUtil} with the default arguments. 52 */ LogTailUtil()53 public LogTailUtil() { 54 this(500, 15, 15); 55 } 56 57 /** 58 * Constructor for {@link LogTailUtil}. 59 * 60 * @param maxBufferSize the size of the ring buffer 61 * @param lastTailSize the number of lines to retrieve when getting the last tail 62 * @param idTailSize the number of lines to retrieve when getting the id tail 63 */ LogTailUtil(int maxBufferSize, int lastTailSize, int idTailSize)64 public LogTailUtil(int maxBufferSize, int lastTailSize, int idTailSize) { 65 mMaxBufferSize = maxBufferSize; 66 mLastTailSize = lastTailSize; 67 mIdTailSize = idTailSize; 68 } 69 70 /** 71 * Add a line to the ring buffer. 72 * 73 * @param id the id of the line 74 * @param line the 75 */ addLine(Integer id, String line)76 public void addLine(Integer id, String line) { 77 mRingBuffer.add(new LogLine(id, line)); 78 if (mRingBuffer.size() > mMaxBufferSize) { 79 mRingBuffer.removeFirst(); 80 } 81 } 82 83 /** 84 * Get the last lines of the log. 85 * 86 * @return The last lines of the log joined as a {@link String}. 87 */ getLastTail()88 public String getLastTail() { 89 return getLastTail(mLastTailSize); 90 } 91 92 /** 93 * Get the last lines of the log. 94 * 95 * @param size the number of lines to return. 96 * @return The last {@code size} lines of the log joined as a {@link String}. 97 */ getLastTail(int size)98 public String getLastTail(int size) { 99 final int toIndex = mRingBuffer.size(); 100 final int fromIndex = Math.max(toIndex - size, 0); 101 102 List<String> tail = new LinkedList<String>(); 103 for (LogLine line : mRingBuffer.subList(fromIndex, toIndex)) { 104 tail.add(line.mLine); 105 } 106 return ArrayUtil.join("\n", tail).trim(); 107 } 108 109 /** 110 * Get the last lines of the log which match the given id. 111 * 112 * @param id the id of the lines to filter by 113 * @return The last lines of the log joined as a {@link String}. 114 */ getIdTail(int id)115 public String getIdTail(int id) { 116 return getIdTail(id, mIdTailSize); 117 } 118 119 /** 120 * Get the last lines of the log which match the given id. 121 * 122 * @param id the id of the lines to filter by 123 * @param size the number of lines to return 124 * @return The last {@code size} lines of the log joined as a {@link String}. 125 */ getIdTail(int id, int size)126 public String getIdTail(int id, int size) { 127 LinkedList<String> tail = new LinkedList<String>(); 128 ListIterator<LogLine> li = mRingBuffer.listIterator(mRingBuffer.size()); 129 while (li.hasPrevious() && tail.size() < size) { 130 LogLine line = li.previous(); 131 132 if (line.mId != null && line.mId.equals(id)) { 133 tail.addFirst(line.mLine); 134 } 135 } 136 return ArrayUtil.join("\n", tail).trim(); 137 } 138 } 139