Cat.java
10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
package com.dianping.cat;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.unidal.helper.Files;
import org.unidal.helper.Properties;
import org.unidal.initialization.DefaultModuleContext;
import org.unidal.initialization.Module;
import org.unidal.initialization.ModuleContext;
import org.unidal.initialization.ModuleInitializer;
import org.unidal.lookup.ContainerLoader;
import com.dianping.cat.configuration.client.entity.ClientConfig;
import com.dianping.cat.configuration.client.entity.Server;
import com.dianping.cat.message.Event;
import com.dianping.cat.message.ForkedTransaction;
import com.dianping.cat.message.Heartbeat;
import com.dianping.cat.message.MessageProducer;
import com.dianping.cat.message.TaggedTransaction;
import com.dianping.cat.message.Trace;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.spi.MessageManager;
import com.dianping.cat.message.spi.MessageTree;
/**
* This is the main entry point to the system.
*/
public class Cat {
private static Cat s_instance = new Cat();
private static volatile boolean s_init = false;
private MessageProducer m_producer;
private MessageManager m_manager;
private PlexusContainer m_container;
private static void checkAndInitialize() {
if (!s_init) {
synchronized (s_instance) {
if (!s_init) {
initialize(new File(getCatHome(), "client.xml"));
log("WARN", "Cat is lazy initialized!");
s_init = true;
}
}
}
}
public static String createMessageId() {
return Cat.getProducer().createMessageId();
}
public static void destroy() {
s_instance.m_container.dispose();
s_instance = new Cat();
}
public static String getCatHome() {
String catHome = Properties.forString().fromEnv().fromSystem().getProperty("CAT_HOME", "/data/appdatas/cat");
return catHome;
}
public static String getCurrentMessageId() {
MessageTree tree = Cat.getManager().getThreadLocalMessageTree();
if (tree != null) {
String messageId = tree.getMessageId();
if (messageId == null) {
messageId = Cat.createMessageId();
tree.setMessageId(messageId);
}
return messageId;
} else {
return null;
}
}
public static Cat getInstance() {
return s_instance;
}
public static MessageManager getManager() {
checkAndInitialize();
return s_instance.m_manager;
}
public static MessageProducer getProducer() {
checkAndInitialize();
return s_instance.m_producer;
}
// this should be called during application initialization time
public static void initialize(File configFile) {
PlexusContainer container = ContainerLoader.getDefaultContainer();
initialize(container, configFile);
}
public static void initialize(PlexusContainer container, File configFile) {
ModuleContext ctx = new DefaultModuleContext(container);
Module module = ctx.lookup(Module.class, CatClientModule.ID);
if (!module.isInitialized()) {
ModuleInitializer initializer = ctx.lookup(ModuleInitializer.class);
ctx.setAttribute("cat-client-config-file", configFile);
initializer.execute(ctx, module);
}
}
public static void initialize(String... servers) {
File configFile = null;
try {
configFile = File.createTempFile("cat-client", ".xml");
ClientConfig config = new ClientConfig().setMode("client");
for (String server : servers) {
config.addServer(new Server(server));
}
Files.forIO().writeTo(configFile, config.toString());
} catch (IOException e) {
e.printStackTrace();
}
initialize(configFile);
}
public static boolean isInitialized() {
synchronized (s_instance) {
return s_instance.m_container != null;
}
}
static void log(String severity, String message) {
MessageFormat format = new MessageFormat("[{0,date,MM-dd HH:mm:ss.sss}] [{1}] [{2}] {3}");
System.out.println(format.format(new Object[] { new Date(), severity, "cat", message }));
}
public static void logError(String message, Throwable cause) {
Cat.getProducer().logError(message, cause);
}
public static void logError(Throwable cause) {
Cat.getProducer().logError(cause);
}
public static void logEvent(String type, String name) {
Cat.getProducer().logEvent(type, name);
}
public static void logEvent(String type, String name, String status, String nameValuePairs) {
Cat.getProducer().logEvent(type, name, status, nameValuePairs);
}
public static void logHeartbeat(String type, String name, String status, String nameValuePairs) {
Cat.getProducer().logHeartbeat(type, name, status, nameValuePairs);
}
public static void logMetric(String name, Object... keyValues) {
// TO REMOVE ME
}
/**
* Increase the counter specified by <code>name</code> by one.
*
* @param name
* the name of the metric default count value is 1
*/
public static void logMetricForCount(String name) {
logMetricInternal(name, "C", "1");
}
/**
* Increase the counter specified by <code>name</code> by one.
*
* @param name
* the name of the metric
*/
public static void logMetricForCount(String name, int quantity) {
logMetricInternal(name, "C", String.valueOf(quantity));
}
/**
* Increase the metric specified by <code>name</code> by <code>durationInMillis</code>.
*
* @param name
* the name of the metric
* @param durationInMillis
* duration in milli-second added to the metric
*/
public static void logMetricForDuration(String name, long durationInMillis) {
logMetricInternal(name, "T", String.valueOf(durationInMillis));
}
/**
* Increase the sum specified by <code>name</code> by <code>value</code> only for one item.
*
* @param name
* the name of the metric
* @param value
* the value added to the metric
*/
public static void logMetricForSum(String name, double value) {
logMetricInternal(name, "S", String.format("%.2f", value));
}
/**
* Increase the metric specified by <code>name</code> by <code>sum</code> for multiple items.
*
* @param name
* the name of the metric
* @param sum
* the sum value added to the metric
* @param quantity
* the quantity to be accumulated
*/
public static void logMetricForSum(String name, double sum, int quantity) {
logMetricInternal(name, "S,C", String.format("%s,%.2f", quantity, sum));
}
private static void logMetricInternal(String name, String status, String keyValuePairs) {
Cat.getProducer().logMetric(name, status, keyValuePairs);
}
public static void logRemoteCallClient(Context ctx) {
MessageTree tree = Cat.getManager().getThreadLocalMessageTree();
String messageId = tree.getMessageId();
if (messageId == null) {
messageId = Cat.createMessageId();
tree.setMessageId(messageId);
}
String childId = Cat.createMessageId();
Cat.logEvent(CatConstants.TYPE_REMOTE_CALL, "", Event.SUCCESS, childId);
String root = tree.getRootMessageId();
if (root == null) {
root = messageId;
}
ctx.addProperty(Context.ROOT, root);
ctx.addProperty(Context.PARENT, messageId);
ctx.addProperty(Context.CHILD, childId);
}
public static void logRemoteCallServer(Context ctx) {
MessageTree tree = Cat.getManager().getThreadLocalMessageTree();
String messageId = ctx.getProperty(Context.CHILD);
String rootId = ctx.getProperty(Context.ROOT);
String parentId = ctx.getProperty(Context.PARENT);
if (messageId != null) {
tree.setMessageId(messageId);
}
if (parentId != null) {
tree.setParentMessageId(parentId);
}
if (rootId != null) {
tree.setRootMessageId(rootId);
}
}
public static void logTrace(String type, String name) {
Cat.getProducer().logTrace(type, name);
}
public static void logTrace(String type, String name, String status, String nameValuePairs) {
Cat.getProducer().logTrace(type, name, status, nameValuePairs);
}
public static <T> T lookup(Class<T> role) throws ComponentLookupException {
return lookup(role, null);
}
public static <T> T lookup(Class<T> role, String hint) throws ComponentLookupException {
return s_instance.m_container.lookup(role, hint);
}
public static Event newEvent(String type, String name) {
return Cat.getProducer().newEvent(type, name);
}
public static ForkedTransaction newForkedTransaction(String type, String name) {
return Cat.getProducer().newForkedTransaction(type, name);
}
public static Heartbeat newHeartbeat(String type, String name) {
return Cat.getProducer().newHeartbeat(type, name);
}
public static TaggedTransaction newTaggedTransaction(String type, String name, String tag) {
return Cat.getProducer().newTaggedTransaction(type, name, tag);
}
public static Trace newTrace(String type, String name) {
return Cat.getProducer().newTrace(type, name);
}
public static Transaction newTransaction(String type, String name) {
return Cat.getProducer().newTransaction(type, name);
}
// this should be called when a thread ends to clean some thread local data
public static void reset() {
// remove me
}
// this should be called when a thread starts to create some thread local data
public static void setup(String sessionToken) {
Cat.getManager().setup();
}
private Cat() {
}
void setContainer(PlexusContainer container) {
try {
m_container = container;
m_manager = container.lookup(MessageManager.class);
m_producer = container.lookup(MessageProducer.class);
} catch (ComponentLookupException e) {
throw new RuntimeException("Unable to get instance of MessageManager, "
+ "please make sure the environment was setup correctly!", e);
}
}
public static interface Context {
public final String ROOT = "_catRootMessageId";
public final String PARENT = "_catParentMessageId";
public final String CHILD = "_catChildMessageId";
public void addProperty(String key, String value);
public String getProperty(String key);
}
}