1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.hadoop.hbase.monitoring;
20  
21  import java.io.PrintWriter;
22  import java.text.SimpleDateFormat;
23  import java.util.Date;
24  import java.util.LinkedList;
25  import java.util.List;
26  
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  
29  import com.google.common.base.Charsets;
30  import com.google.common.base.Preconditions;
31  import com.google.common.collect.Lists;
32  
33  
34  
35  
36  
37  
38  
39  @InterfaceAudience.Private
40  public class MemoryBoundedLogMessageBuffer {
41    private final long maxSizeBytes;
42    private long usage = 0;
43    private LinkedList<LogMessage> messages;
44    
45    public MemoryBoundedLogMessageBuffer(long maxSizeBytes) {
46      Preconditions.checkArgument(
47          maxSizeBytes > 0);
48      this.maxSizeBytes = maxSizeBytes;
49      this.messages = Lists.newLinkedList();
50    }
51    
52    
53  
54  
55  
56    public synchronized void add(String messageText) {
57      LogMessage message = new LogMessage(messageText, System.currentTimeMillis());
58      
59      usage += message.estimateHeapUsage();
60      messages.add(message);
61      while (usage > maxSizeBytes) {
62        LogMessage removed = messages.remove();
63        usage -= removed.estimateHeapUsage();
64        assert usage >= 0;
65      }
66    }
67    
68    
69  
70  
71    public synchronized void dumpTo(PrintWriter out) {
72      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
73  
74      for (LogMessage msg : messages) {
75        out.write(df.format(new Date(msg.timestamp)));
76        out.write(" ");
77        out.println(new String(msg.message, Charsets.UTF_8));
78      }
79    }
80    
81    synchronized List<LogMessage> getMessages() {
82      
83      return Lists.newArrayList(messages);
84    }
85   
86    
87  
88  
89  
90    synchronized long estimateHeapUsage() {
91      return usage;
92    }
93    
94    private static class LogMessage {
95      
96      public final byte[] message;
97      public final long timestamp;
98      
99      
100 
101 
102 
103 
104     private static final long BASE_USAGE=100;
105     
106     public LogMessage(String message, long timestamp) {
107       this.message = message.getBytes(Charsets.UTF_8);
108       this.timestamp = timestamp;
109     }
110     
111     public long estimateHeapUsage() {
112       return message.length + BASE_USAGE;
113     }
114   }
115 
116 }