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 }