mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-07-06 15:34:10 +02:00
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
This commit is contained in:
30
tango/example/logging/chainsaw.d
Normal file
30
tango/example/logging/chainsaw.d
Normal file
@@ -0,0 +1,30 @@
|
||||
import tango.core.Thread;
|
||||
|
||||
import tango.util.log.Log,
|
||||
tango.util.log.Log4Layout,
|
||||
tango.util.log.SocketAppender;
|
||||
|
||||
import tango.net.InternetAddress;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Hooks up to Chainsaw for remote log capture. Chainsaw should be
|
||||
configured to listen with an XMLSocketReciever
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
void main()
|
||||
{
|
||||
// get a logger to represent this module
|
||||
auto logger = Log.getLogger ("example.chainsaw");
|
||||
|
||||
// hook up an appender for XML output
|
||||
logger.addAppender (new SocketAppender (new InternetAddress("127.0.0.1", 4448), new Log4Layout));
|
||||
|
||||
while (true)
|
||||
{
|
||||
logger.info ("Hello Chainsaw!");
|
||||
Thread.sleep (1.0);
|
||||
}
|
||||
}
|
||||
322
tango/example/logging/context.d
Normal file
322
tango/example/logging/context.d
Normal file
@@ -0,0 +1,322 @@
|
||||
/*******************************************************************************
|
||||
|
||||
copyright: Copyright (c) 2007 Stonecobra. All rights reserved
|
||||
|
||||
license: BSD style: $(LICENSE)
|
||||
|
||||
version: Initial release: December 2007
|
||||
|
||||
author: stonecobra
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
module context;
|
||||
|
||||
import tango.core.Thread,
|
||||
tango.util.log.Log,
|
||||
tango.util.log.Event,
|
||||
tango.util.log.EventLayout,
|
||||
tango.util.log.ConsoleAppender;
|
||||
|
||||
import tango.util.log.model.IHierarchy;
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Allows the dynamic setting of log levels on a per-thread basis.
|
||||
Imagine that a user request comes into your production threaded
|
||||
server. You can't afford to turn logging up to trace for the sake
|
||||
of debugging this one users problem, but you also can't afford to
|
||||
find the problem and fix it. So now you just set the override log
|
||||
level to TRACE for the thread the user is on, and you get full trace
|
||||
output for only that user.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
class ThreadLocalDiagnosticContext : IHierarchy.Context
|
||||
{
|
||||
private ThreadLocal!(DCData) dcData;
|
||||
private char[128] tmp;
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
public this()
|
||||
{
|
||||
dcData = new ThreadLocal!(DCData);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
set the 'diagnostic' Level for logging. This overrides
|
||||
the Level in the current Logger. The default level starts
|
||||
at NONE, so as not to modify the behavior of existing clients
|
||||
of tango.util.log
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
void setLevel (ILevel.Level level)
|
||||
{
|
||||
auto data = dcData.val;
|
||||
data.level = level;
|
||||
dcData.val = data;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
All log appends will be checked against this to see if a
|
||||
log level needs to be temporarily adjusted.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
bool isEnabled (ILevel.Level setting, ILevel.Level level = ILevel.Level.Trace)
|
||||
{
|
||||
return level >= setting || level >= dcData.val.level;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
Return the label to use for the current log message. Usually
|
||||
called by the Layout. This implementation returns "{}".
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
char[] label ()
|
||||
{
|
||||
return dcData.val.getLabel;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
Push another string into the 'stack'. This strings will be
|
||||
appened together when getLabel is called.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
void push (char[] label)
|
||||
{
|
||||
auto data = dcData.val;
|
||||
data.push(label);
|
||||
dcData.val = data;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
pop the current label off the stack.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
void pop ()
|
||||
{
|
||||
auto data = dcData.val;
|
||||
data.pop;
|
||||
dcData.val = data;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
Clear the label stack.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
void clear()
|
||||
{
|
||||
auto data = dcData.val;
|
||||
data.clear;
|
||||
dcData.val = data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
The thread locally stored struct to hold the logging level and
|
||||
the label stack.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
private struct DCData {
|
||||
|
||||
ILevel.Level level = ILevel.Level.None;
|
||||
char[][8] stack;
|
||||
bool shouldUpdate = true;
|
||||
int stackIndex = 0;
|
||||
uint labelLength;
|
||||
char[256] labelContent;
|
||||
|
||||
|
||||
char[] getLabel() {
|
||||
if (shouldUpdate) {
|
||||
labelLength = 0;
|
||||
append(" {");
|
||||
for (int i = 0; i < stackIndex; i++) {
|
||||
append(stack[i]);
|
||||
if (i < stackIndex - 1) {
|
||||
append(" ");
|
||||
}
|
||||
}
|
||||
append("}");
|
||||
shouldUpdate = false;
|
||||
}
|
||||
return labelContent[0..labelLength];
|
||||
}
|
||||
|
||||
void append(char[] x) {
|
||||
uint addition = x.length;
|
||||
uint newLength = labelLength + x.length;
|
||||
|
||||
if (newLength < labelContent.length)
|
||||
{
|
||||
labelContent [labelLength..newLength] = x[0..addition];
|
||||
labelLength = newLength;
|
||||
}
|
||||
}
|
||||
|
||||
void push(char[] label) {
|
||||
shouldUpdate = true;
|
||||
stack[stackIndex] = label.dup;
|
||||
stackIndex++;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
shouldUpdate = true;
|
||||
if (stackIndex > 0) {
|
||||
stack[stackIndex] = null;
|
||||
stackIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
shouldUpdate = true;
|
||||
for (int i = 0; i < stack.length; i++) {
|
||||
stack[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Simple console appender that counts the number of log lines it
|
||||
has written.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
class TestingConsoleAppender : ConsoleAppender {
|
||||
|
||||
int events = 0;
|
||||
|
||||
this (EventLayout layout = null)
|
||||
{
|
||||
super(layout);
|
||||
}
|
||||
|
||||
override void append (Event event)
|
||||
{
|
||||
events++;
|
||||
super.append(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Testing harness for the DiagnosticContext functionality.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
void main(char[][] args)
|
||||
{
|
||||
//set up our appender that counts the log output. This is the configuration
|
||||
//equivalent of importing tango.util.log.Configurator.
|
||||
auto appender = new TestingConsoleAppender(new SimpleTimerLayout);
|
||||
Log.getRootLogger.addAppender(appender);
|
||||
|
||||
char[128] tmp = 0;
|
||||
auto log = Log.getLogger("context");
|
||||
log.setLevel(log.Level.Info);
|
||||
|
||||
//first test, use all defaults, validating it is working. None of the trace()
|
||||
//calls should count in the test.
|
||||
for (int i=0;i < 10; i++) {
|
||||
log.info(log.format(tmp, "test1 {}", i));
|
||||
log.trace(log.format(tmp, "test1 {}", i));
|
||||
}
|
||||
if (appender.events !is 10) {
|
||||
log.error(log.format(tmp, "events:{}", appender.events));
|
||||
throw new Exception("Incorrect Number of events in normal mode");
|
||||
}
|
||||
|
||||
appender.events = 0;
|
||||
|
||||
//test the thread local implementation without any threads, as a baseline.
|
||||
//should be same result as test1
|
||||
auto context = new ThreadLocalDiagnosticContext;
|
||||
Log.getHierarchy.context(context);
|
||||
for (int i=0;i < 10; i++) {
|
||||
log.info(log.format(tmp, "test2 {}", i));
|
||||
log.trace(log.format(tmp, "test2 {}", i));
|
||||
}
|
||||
if (appender.events !is 10) {
|
||||
log.error(log.format(tmp, "events:{}", appender.events));
|
||||
throw new Exception("Incorrect Number of events in TLS single thread mode");
|
||||
}
|
||||
|
||||
appender.events = 0;
|
||||
|
||||
//test the thread local implementation without any threads, as a baseline.
|
||||
//This should count all logging requests, because the DiagnosticContext has
|
||||
//'overridden' the logging level on ALL loggers up to TRACE.
|
||||
context.setLevel(log.Level.Trace);
|
||||
for (int i=0;i < 10; i++) {
|
||||
log.info(log.format(tmp, "test3 {}", i));
|
||||
log.trace(log.format(tmp, "test3 {}", i));
|
||||
}
|
||||
if (appender.events !is 20) {
|
||||
log.error(log.format(tmp, "events:{}", appender.events));
|
||||
throw new Exception("Incorrect Number of events in TLS single thread mode with level set");
|
||||
}
|
||||
|
||||
appender.events = 0;
|
||||
|
||||
//test the thread local implementation without any threads, as a baseline.
|
||||
context.setLevel(log.Level.None);
|
||||
for (int i=0;i < 10; i++) {
|
||||
log.info(log.format(tmp, "test4 {}", i));
|
||||
log.trace(log.format(tmp, "test4 {}", i));
|
||||
}
|
||||
if (appender.events !is 10) {
|
||||
log.error(log.format(tmp, "events:{}", appender.events));
|
||||
throw new Exception("Incorrect Number of events in TLS single thread mode after level reset");
|
||||
}
|
||||
|
||||
//Now test threading. set up a trace context in one thread, with a label, while
|
||||
//keeping the second thread at the normal configuration.
|
||||
appender.events = 0;
|
||||
ThreadGroup tg = new ThreadGroup();
|
||||
tg.create({
|
||||
char[128] tmp = 0;
|
||||
context.setLevel(log.Level.Trace);
|
||||
context.push("specialthread");
|
||||
context.push("2ndlevel");
|
||||
for (int i=0;i < 10; i++) {
|
||||
log.info(log.format(tmp, "test5 {}", i));
|
||||
log.trace(log.format(tmp, "test5 {}", i));
|
||||
}
|
||||
});
|
||||
tg.create({
|
||||
char[128] tmp = 0;
|
||||
context.setLevel(log.Level.None);
|
||||
for (int i=0;i < 10; i++) {
|
||||
log.info(log.format(tmp, "test6 {}", i));
|
||||
log.trace(log.format(tmp, "test6 {}", i));
|
||||
}
|
||||
});
|
||||
tg.joinAll();
|
||||
|
||||
if (appender.events !is 30) {
|
||||
log.error(log.format(tmp, "events:{}", appender.events));
|
||||
throw new Exception("Incorrect Number of events in TLS multi thread mode");
|
||||
}
|
||||
}
|
||||
|
||||
102
tango/example/logging/logging.d
Normal file
102
tango/example/logging/logging.d
Normal file
@@ -0,0 +1,102 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Shows how the basic functionality of Logger operates.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
private import tango.util.log.Log,
|
||||
tango.util.log.Configurator;
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Search for a set of prime numbers
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
void compute (Logger log, uint max)
|
||||
{
|
||||
byte* feld;
|
||||
int teste=1,
|
||||
mom,
|
||||
hits=0,
|
||||
s=0,
|
||||
e = 1;
|
||||
int count;
|
||||
char tmp[128] = void;
|
||||
|
||||
void set (byte* f, uint x)
|
||||
{
|
||||
*(f+(x)/16) |= 1 << (((x)%16)/2);
|
||||
}
|
||||
|
||||
byte test (byte* f, uint x)
|
||||
{
|
||||
return cast(byte) (*(f+(x)/16) & (1 << (((x)%16)/2)));
|
||||
}
|
||||
|
||||
// information level
|
||||
log.info (log.format (tmp, "Searching prime numbers up to {}", max));
|
||||
|
||||
feld = (new byte[max / 16 + 1]).ptr;
|
||||
|
||||
// get milliseconds since application began
|
||||
auto begin = log.runtime;
|
||||
|
||||
while ((teste += 2) < max)
|
||||
if (! test (feld, teste))
|
||||
{
|
||||
if ((++hits & 0x0f) == 0)
|
||||
// more information level
|
||||
log.info (log.format (tmp, "found {}", hits));
|
||||
|
||||
for (mom=3*teste; mom < max; mom += teste<<1)
|
||||
set (feld, mom);
|
||||
}
|
||||
|
||||
// get number of milliseconds we took to compute
|
||||
auto period = log.runtime - begin;
|
||||
|
||||
if (hits)
|
||||
// more information
|
||||
log.info (log.format (tmp, "{} prime numbers found in {} millsecs", hits, period));
|
||||
else
|
||||
// a warning level
|
||||
log.warn ("no prime numbers found");
|
||||
|
||||
// check to see if we're enabled for
|
||||
// tracing before we expend a lot of effort
|
||||
if (log.isEnabled (log.Level.Trace))
|
||||
{
|
||||
e = max;
|
||||
count = 0 - 2;
|
||||
if (s % 2 is 0)
|
||||
count++;
|
||||
|
||||
while ((count+=2) < e)
|
||||
// log trace information
|
||||
if (! test (feld, count))
|
||||
log.trace (log.format (tmp, "prime found: {}", count));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Compute a bunch of prime numbers
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
void main()
|
||||
{
|
||||
// get a logger to represent this module. We could just as
|
||||
// easily share a name with some other module(s)
|
||||
auto log = Log.getLogger ("example.logging");
|
||||
try {
|
||||
compute (log, 1000);
|
||||
|
||||
} catch (Exception x)
|
||||
{
|
||||
// log the exception as an error
|
||||
log.error ("Exception: " ~ x.toString);
|
||||
}
|
||||
}
|
||||
31
tango/example/logging/multilog.d
Normal file
31
tango/example/logging/multilog.d
Normal file
@@ -0,0 +1,31 @@
|
||||
import tango.util.log.Log;
|
||||
import tango.util.log.Log4Layout;
|
||||
import tango.util.log.FileAppender;
|
||||
import tango.util.log.ConsoleAppender;
|
||||
import tango.util.log.RollingFileAppender;
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Shows how to setup multiple appenders on logging tree
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
void main ()
|
||||
{
|
||||
// set default logging level at the root
|
||||
auto log = Log.getRootLogger;
|
||||
log.setLevel (log.Level.Trace);
|
||||
|
||||
// 10 logs, all with 10 mbs each
|
||||
log.addAppender (new RollingFileAppender("rolling.log", 9, 1024*1024*10));
|
||||
|
||||
// a single file appender, with an XML layout
|
||||
log.addAppender (new FileAppender ("single.log", new Log4Layout));
|
||||
|
||||
// console appender
|
||||
log.addAppender (new ConsoleAppender);
|
||||
|
||||
// log to all
|
||||
log.trace ("three-way logging");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user