[asterisk-scf-commits] asterisk-scf/integration/logger.git branch "logformat" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Apr 20 07:33:37 CDT 2011


branch "logformat" has been created
        at  4abb4342686cdc8df849a76149d0f3baf04fee09 (commit)

- Log -----------------------------------------------------------------
commit 4abb4342686cdc8df849a76149d0f3baf04fee09
Author: Fred Anderson <fanderson at digium.com>
Date:   Wed Apr 20 07:24:03 2011 -0500

    Re-did the time delta to be more correct

diff --git a/client/src/LogFormatter.cpp b/client/src/LogFormatter.cpp
index ddddf36..42d2dd3 100644
--- a/client/src/LogFormatter.cpp
+++ b/client/src/LogFormatter.cpp
@@ -122,7 +122,8 @@ void LogFormatter::logs(const std::string& name, Level level, const std::string&
     if ((pos=outStr.find(SPECIFIER("d"),0))!=std::string::npos)
     {
         // take labs() on the off chance delta represents a negative duration
-        boost::posix_time::time_duration delta = timeDelta();
+        boost::posix_time::time_duration delta = 
+                boost::posix_time::microsec_clock::universal_time() - mLastMsgTime;
         long secs = labs(delta.total_milliseconds() / 1000),
              msecs = labs(delta.total_milliseconds() % 1000);
         std::stringstream s("");
@@ -136,14 +137,5 @@ void LogFormatter::logs(const std::string& name, Level level, const std::string&
         outStr.replace(pos,2,message);
     }
     mOut->logs(name,level,outStr);
-}
-
-
-boost::posix_time::time_duration LogFormatter::timeDelta()
-{
-    boost::posix_time::time_duration d = boost::posix_time::microsec_clock::universal_time() - mLastMsgTime;
-
     mLastMsgTime = boost::posix_time::microsec_clock::universal_time();
-    return d;
 }
-
diff --git a/client/test/Logger-test.cpp b/client/test/Logger-test.cpp
index 2e65a3e..662b779 100644
--- a/client/test/Logger-test.cpp
+++ b/client/test/Logger-test.cpp
@@ -136,6 +136,9 @@ BOOST_AUTO_TEST_CASE(test_stream_timedelta)
     ExpectedLogOut out("0.001: src:Debug:TimeDelta test\n");
     Logger uut("src", out, Debug, "$d: $n:$p:$m");
 
+    // This is probably not the best test, since it's theoretically possible
+    // for more than one millisecond to pass between the creation of the
+    // expected message above and the actual message below.
     usleep(1000);  // force a millisecond to pass
     uut(Debug) << "TimeDelta test" << '\n';
     out.check();

commit 9916249c3287ad50e8b78bad24fa48d30c151da4
Author: Fred Anderson <fanderson at digium.com>
Date:   Wed Apr 20 07:06:47 2011 -0500

    Whoops! Forgot one.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c055ab..616d740 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,12 +40,15 @@ include_directories(include)
 asterisk_scf_component_add_file(logging-client client/src/Logger.cpp)
 asterisk_scf_component_add_file(logging-client client/src/LoggerFactory.cpp)
 asterisk_scf_component_add_file(logging-client client/src/LogOut.cpp)
+asterisk_scf_component_add_file(logging-client client/src/LogFormatter.cpp)
 asterisk_scf_component_add_file(logging-client client/src/IceConfigurator.cpp)
 asterisk_scf_component_add_file(logging-client client/src/IceLogger.cpp)
 asterisk_scf_component_add_file(logging-client client/src/OstreamLogger.cpp)
 asterisk_scf_component_add_file(logging-client client/src/IceConfigurator.h)
 asterisk_scf_component_add_file(logging-client include/AsteriskSCF/logger.h)
 asterisk_scf_component_add_file(logging-client include/AsteriskSCF/Logger/LogOut.h)
+asterisk_scf_component_add_file(logging-client include/AsteriskSCF/Logger/LogConsts.h)
+asterisk_scf_component_add_file(logging-client include/AsteriskSCF/Logger/LogFormatter.h)
 asterisk_scf_component_add_file(logging-client include/AsteriskSCF/Logger/IceLogger.h)
 asterisk_scf_component_add_file(logging-client include/AsteriskSCF/Logger/Level.h)
 

commit 87a19a06a61814d7871eb2d24d1158374f6679cf
Author: Fred Anderson <fanderson at digium.com>
Date:   Wed Apr 20 06:47:00 2011 -0500

    HYDRA-354: allow formatting for log messages

diff --git a/client/src/IceLogger.cpp b/client/src/IceLogger.cpp
index 2cba8ae..f67056c 100644
--- a/client/src/IceLogger.cpp
+++ b/client/src/IceLogger.cpp
@@ -55,7 +55,7 @@ void IceLogger::logs(const std::string& name, Level logLevel,
                 "!!! Unable to log to server.  Please check configuration and server status.\n"
                 "!!! Logging to stderr instead.\n";
         }
-        std::clog << name << ":" << logLevel << ":" << message << '\n';
+        std::clog << message << '\n';
     }
 }
 
diff --git a/client/src/LogFormatter.cpp b/client/src/LogFormatter.cpp
new file mode 100644
index 0000000..ddddf36
--- /dev/null
+++ b/client/src/LogFormatter.cpp
@@ -0,0 +1,149 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include <AsteriskSCF/logger.h>
+
+using namespace AsteriskSCF::System::Logging;
+
+LogFormatter::LogFormatter(LogOut* out, const std::string& fmtStr) :
+    mOut(out), mFormat(fmtStr), mLastMsgTime(boost::posix_time::microsec_clock::universal_time())
+{
+}
+
+
+LogFormatter::LogFormatter(const LogFormatter& orig) :
+    mOut(orig.mOut), mFormat(orig.mFormat), mLastMsgTime(boost::posix_time::microsec_clock::universal_time())
+{
+}
+
+
+LogFormatter::~LogFormatter()
+{
+}
+
+
+void LogFormatter::setFormat(const std::string& fmtStr)
+{
+    mFormat = fmtStr;
+}
+
+
+void LogFormatter::setOutput(LogOut* out)
+{
+    mOut = out;
+}
+
+
+/**
+ * Formats a log string and sends it to mOut
+ */
+void LogFormatter::logs(const std::string& name, Level level, const std::string& message)
+{
+    std::string outStr(mFormat);
+    std::size_t pos;
+
+    // Logger name
+    if ((pos=outStr.find(SPECIFIER("n"),0))!=std::string::npos)
+    {
+        outStr.replace(pos,2,name);
+    }
+    // Priority / level
+    if ((pos=outStr.find(SPECIFIER("p"),0))!=std::string::npos)
+    {
+        std::stringstream s("");
+
+        s << level;
+        outStr.replace(pos,2,s.str());
+    }
+    // Client host name
+    if ((pos=outStr.find(SPECIFIER("h"),0))!=std::string::npos)
+    {
+        char host[128];
+
+        if (gethostname(host,128))
+        {
+            std::strncpy(host,"unknown_host",128);
+        }
+        outStr.replace(pos,2,std::string(host));
+    }
+    // Client timestamp (formatted)
+    if ((pos=outStr.find(SPECIFIER("t{"),0))!=std::string::npos)
+    {
+        try
+        {
+            std::size_t pos2 = outStr.find("}",pos+3);
+            if (pos2!=std::string::npos)
+            {
+                std::string timeFormat = outStr.substr(pos+3,pos2-3);
+                time_t now = time(NULL);
+                char timeStamp[TIMESTAMP_SIZE];
+       
+                strftime(timeStamp,TIMESTAMP_SIZE,timeFormat.c_str(),localtime(&now));
+                outStr.replace(pos,pos+pos2+1,std::string(timeStamp));
+            }
+        }
+        catch (...)
+        {
+           // Don't do anything to outStr, so timestamp will look bad
+           // and signal to someone that the format is wrong
+        }
+    }
+    // Client timestamp (unformatted)
+    if ((pos=outStr.find(SPECIFIER("t"),0))!=std::string::npos)
+    {
+        char timeStamp[TIMESTAMP_SIZE];
+        std::time_t now = time(NULL);
+     
+        strftime(timeStamp,TIMESTAMP_SIZE,TimestampFormat.c_str(),localtime(&now));
+        outStr.replace(pos,2,std::string(timeStamp));
+    }
+    // Thread ID
+    if ((pos=outStr.find(SPECIFIER("i"),0))!=std::string::npos)
+    {
+        std::stringstream s("");
+
+        s << boost::this_thread::get_id();
+        outStr.replace(pos,2,s.str());
+    }
+    // Time delta since last message
+    if ((pos=outStr.find(SPECIFIER("d"),0))!=std::string::npos)
+    {
+        // take labs() on the off chance delta represents a negative duration
+        boost::posix_time::time_duration delta = timeDelta();
+        long secs = labs(delta.total_milliseconds() / 1000),
+             msecs = labs(delta.total_milliseconds() % 1000);
+        std::stringstream s("");
+
+        s << secs << "." << std::setfill('0') << std::setw(3) << msecs;
+        outStr.replace(pos,2,s.str());
+    }
+    // Check for message last so we don't modify it
+    if ((pos=outStr.find(SPECIFIER("m"),0))!=std::string::npos)
+    {
+        outStr.replace(pos,2,message);
+    }
+    mOut->logs(name,level,outStr);
+}
+
+
+boost::posix_time::time_duration LogFormatter::timeDelta()
+{
+    boost::posix_time::time_duration d = boost::posix_time::microsec_clock::universal_time() - mLastMsgTime;
+
+    mLastMsgTime = boost::posix_time::microsec_clock::universal_time();
+    return d;
+}
+
diff --git a/client/src/Logger.cpp b/client/src/Logger.cpp
index 99b651b..98d45d3 100644
--- a/client/src/Logger.cpp
+++ b/client/src/Logger.cpp
@@ -16,29 +16,37 @@
 
 #include <cassert>
 #include <cstdio>
+#include <sstream>
+#include <iomanip>
+#include <cstdlib>
+#include <time.h>
+
+#include <boost/thread/thread.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 #include <AsteriskSCF/logger.h>
 
 using namespace AsteriskSCF::System::Logging;
 
-const int MESSAGE_SIZE = 120;
 
-LogBuf::LogBuf(LogOut& out, const std::string& name, Level logLevel) :
-    mOut(out), nName(name), mLogLevel(logLevel)
+LogBuf::LogBuf(const boost::shared_ptr<LogFormatter> formatter, const std::string& name, Level level) :
+    mFormatter(formatter), mName(name), mLogLevel(level)
 {
 }
 
+
 // NOTE: The copy constructor below intentionally calls the default constructor of its
 // std::streambuf base, rather than calling the copy constructor. The copy constructor
 // of std::streambuf is private (so it cannot be called), but more importantly, the
 // std::streambuf base object has no useful state that needs to be copied when a
 // LogBuf is copied.
 LogBuf::LogBuf(const LogBuf& orig) :
-    std::streambuf(), mOut(orig.mOut), nName(orig.nName), mLogLevel(orig.mLogLevel)
+    std::streambuf(), mFormatter(orig.mFormatter), mName(orig.mName), mLogLevel(orig.mLogLevel)
 {
     mBuffer.str(orig.mBuffer.str());
 }
 
+
 LogBuf::~LogBuf()
 {
     if (!mBuffer.str().empty())
@@ -47,6 +55,7 @@ LogBuf::~LogBuf()
     }
 }
 
+
 int LogBuf::overflow(int c)
 {
     if (c == '\n' || c == traits_type::eof())
@@ -57,24 +66,29 @@ int LogBuf::overflow(int c)
     return mBuffer.sputc((char) c);
 }
 
+
 void LogBuf::sendBuffer()
 {
-    // logic looks a bit backwards, but that's in case out.logs()
+    // logic looks a bit backwards, but that's in case mFormatter.logs()
     // throws an exception, we still want to clear the buffer.
     const std::string& message = mBuffer.str();
     mBuffer.str("");
-    // send
-    mOut.logs(nName, mLogLevel, message);
+    // send it to the formatter
+    mFormatter.get()->logs(mName,mLogLevel,message);
 }
 
-Logger::LoggerImpl::LoggerImpl(const std::string& name, LogOut& out, Level logLevel) :
-    mParent(), mName(name), mOut(&out), mLogLevel(logLevel), mInheritedLevel(false)
+
+Logger::LoggerImpl::LoggerImpl(const std::string& name, LogOut& out, Level logLevel,
+        const std::string& fmtStr) :
+    mParent(), mName(name), mOut(&out), mLogLevel(logLevel), mFormatter(new LogFormatter(&out,fmtStr)), mInheritedLevel(false),
+    mInheritedFormatter(false)
 {
 }
 
+
 Logger::LoggerImpl::LoggerImpl(const boost::shared_ptr<LoggerImpl>& parent, const std::string& name) :
-    mParent(parent), mName(name), mOut(parent->mOut), mLogLevel(Off),
-    mInheritedLevel(true)
+    mParent(parent), mName(name), mOut(parent->mOut), mLogLevel(Off), mFormatter(parent->mFormatter),
+    mInheritedLevel(true), mInheritedFormatter(true)
 {
     // parent ptr must be non-null
     assert(parent != 0);
@@ -86,32 +100,37 @@ Logger::LoggerImpl::~LoggerImpl()
 {
 }
 
+
 CondStream Logger::LoggerImpl::operator()(Level level) const
 {
-    return CondStream(*mOut, mName, level, isEnabledFor(level));
+    return CondStream(getEffectiveFormatter(),mName,level,isEnabledFor(level));
 }
 
-void Logger::LoggerImpl::logs(Level level, const std::string& message) const
+
+void Logger::LoggerImpl::logs(Level level, const std::string& message)
 {
     if (isEnabledFor(level))
     {
-        mOut->logs(mName, level, message);
+        mFormatter.get()->logs(mName,level,message);
     }
 }
 
-void Logger::LoggerImpl::vlogf(Level level, char const *fmt, va_list ap) const
+
+void Logger::LoggerImpl::vlogf(Level level, char const *fmt, va_list ap) 
 {
     if (isEnabledFor(level))
     {
         char message[MESSAGE_SIZE];
         vsnprintf(message, sizeof(message), fmt, ap);
-        mOut->logs(mName, level, message);
+        mFormatter.get()->logs(mName,level,std::string(message));
     }
 }
 
+
 void Logger::LoggerImpl::setOutput(LogOut& out)
 {
     this->mOut = &out;
+    mFormatter.get()->setOutput(&out);
     boost::lock_guard<boost::mutex> childLock(mChildrenMutex);
     for (Children::const_iterator i = mChildren.begin();
          i != mChildren.end();
@@ -124,21 +143,23 @@ void Logger::LoggerImpl::setOutput(LogOut& out)
 
 void Logger::LoggerImpl::setLevel(Level logLevel)
 {
-    boost::unique_lock<boost::shared_mutex> lock(mLevelMutex);
+    boost::unique_lock<boost::shared_mutex> lock(mInheritedMutex);
     mLogLevel = logLevel;
     mInheritedLevel = false;
 }
 
+
 void Logger::LoggerImpl::unsetLevel()
 {
-    boost::unique_lock<boost::shared_mutex> lock(mLevelMutex);
+    boost::unique_lock<boost::shared_mutex> lock(mInheritedMutex);
     mInheritedLevel = true;
     mLogLevel = Off;
 }
 
+
 Level Logger::LoggerImpl::getEffectiveLevel() const
 {
-    boost::shared_lock<boost::shared_mutex> lock(mLevelMutex);
+    boost::shared_lock<boost::shared_mutex> lock(mInheritedMutex);
     // If parent is null, either we've never had a parent, or that
     // parent has been destroyed.
     boost::shared_ptr<const LoggerImpl> parent = mParent.lock();
@@ -153,6 +174,39 @@ Level Logger::LoggerImpl::getEffectiveLevel() const
     }
 }
 
+
+void Logger::LoggerImpl::setFormat(const std::string& fmtStr)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mInheritedMutex);
+    mFormatter.reset(new LogFormatter(mOut,fmtStr));
+    mInheritedFormatter = false;
+}
+
+
+void Logger::LoggerImpl::unsetFormat()
+{
+    boost::unique_lock<boost::shared_mutex> lock(mInheritedMutex);
+    mFormatter.reset();
+    mInheritedFormatter = true;
+}
+
+
+boost::shared_ptr<LogFormatter> Logger::LoggerImpl::getEffectiveFormatter() const
+{
+    boost::shared_lock<boost::shared_mutex> lock(mInheritedMutex);
+    boost::shared_ptr<const LoggerImpl> parent = mParent.lock();
+
+    if (mInheritedFormatter == true && parent != 0)
+    {
+        return parent->getEffectiveFormatter();
+    }
+    else
+    {
+        return mFormatter;
+    }
+}
+
+
 Logger Logger::LoggerImpl::getChild(const boost::shared_ptr<LoggerImpl>& self,
     const std::string& childName)
 {
@@ -169,6 +223,7 @@ Logger Logger::LoggerImpl::getChild(const boost::shared_ptr<LoggerImpl>& self,
     return Logger(child);
 }
 
+
 std::vector<Logger> Logger::LoggerImpl::getChildren() const
 {
     std::vector<Logger> r;
@@ -181,4 +236,3 @@ std::vector<Logger> Logger::LoggerImpl::getChildren() const
     }
     return r;
 }
-
diff --git a/client/src/LoggerFactory.cpp b/client/src/LoggerFactory.cpp
index 3ad3c42..07fe13b 100644
--- a/client/src/LoggerFactory.cpp
+++ b/client/src/LoggerFactory.cpp
@@ -35,6 +35,7 @@ namespace
 boost::once_flag oneFactory = BOOST_ONCE_INIT;
 LoggerFactory *loggerFactory = 0;
 
+
 void initLoggerFactory()
 {
     static boost::shared_ptr<LogOut> out = buildOstreamLogger(std::cout);
@@ -44,6 +45,45 @@ void initLoggerFactory()
 
 }
 
+
+/**
+ * Builds a formatted string with some source code information in it.
+ */
+std::string AsteriskSCF::System::Logging::sourceInfoStr(const std::string& fmt, unsigned int line,
+                                                        const char* fcn, const char* file)
+{
+    std::string s(fmt);
+    std::size_t pos;
+    bool found = true;
+    
+    while (found)
+    {
+        found = false;
+        if ((pos=s.find(SPECIFIER("l"),0))!=std::string::npos)
+        {
+            s.replace(pos,2,boost::lexical_cast<std::string>(line));
+            found = true;
+        }
+        if ((pos=s.find(SPECIFIER("f"),0))!=std::string::npos)
+        {
+            s.replace(pos,2,boost::lexical_cast<std::string>(fcn));
+            found = true;
+        }
+        if ((pos=s.find(SPECIFIER("sp"),0))!=std::string::npos)
+        {
+            s.replace(pos,3,boost::lexical_cast<std::string>(file));
+            found = true;
+        }
+        if ((pos=s.find(SPECIFIER("sf"),0))!=std::string::npos)
+        {
+            s.replace(pos,3,boost::lexical_cast<std::string>(basename(file)));
+            found = true;
+        }
+    }
+    return s;
+}
+
+
 LoggerFactory& AsteriskSCF::System::Logging::getLoggerFactory()
 {
     boost::call_once(initLoggerFactory, oneFactory);
diff --git a/client/src/OstreamLogger.cpp b/client/src/OstreamLogger.cpp
index d3b35c6..0233e72 100644
--- a/client/src/OstreamLogger.cpp
+++ b/client/src/OstreamLogger.cpp
@@ -33,7 +33,7 @@ public:
     void logs(const std::string& name, Level logLevel,
         const std::string& message)
     {
-        mOut << name << ":" << logLevel << ":" << message << '\n';
+        mOut << message << '\n';
     }
 
 private:
diff --git a/client/test/ExpectedLogOut.h b/client/test/ExpectedLogOut.h
index 5617129..c79c248 100644
--- a/client/test/ExpectedLogOut.h
+++ b/client/test/ExpectedLogOut.h
@@ -31,7 +31,7 @@ public:
     void logs(const std::string& name, Level logLevel,
         const std::string& message)
     {
-        mActual << name << ":" << logLevel << ":" << message << '\n';
+        mActual << message << '\n';
     }
 
     void check()
diff --git a/client/test/LogBuf-test.cpp b/client/test/LogBuf-test.cpp
index 845f5f6..4dd63fc 100644
--- a/client/test/LogBuf-test.cpp
+++ b/client/test/LogBuf-test.cpp
@@ -27,7 +27,8 @@ BOOST_AUTO_TEST_SUITE(LogStreamTest)
 BOOST_AUTO_TEST_CASE(test_stream)
 {
     ExpectedLogOut out("src:Info:testing\n");
-    LogBuf uut(out, "src", Info);
+    boost::shared_ptr<LogFormatter> formatter(new LogFormatter(&out));
+    LogBuf uut(formatter, "src", Info);
     std::ostream stream(&uut);
 
     stream << "testing" << '\n';
@@ -37,7 +38,8 @@ BOOST_AUTO_TEST_CASE(test_stream)
 BOOST_AUTO_TEST_CASE(test_stream_format)
 {
     ExpectedLogOut out("src:Debug:debug f00d\n");
-    LogBuf buf(out, "src", Debug);
+    boost::shared_ptr<LogFormatter> formatter(new LogFormatter(&out));
+    LogBuf buf(formatter, "src", Debug);
     std::ostream uut(&buf);
 
     uut << "debug " << std::hex << 61453 << '\n';
diff --git a/client/test/Logger-test.cpp b/client/test/Logger-test.cpp
index 0964c6f..2e65a3e 100644
--- a/client/test/Logger-test.cpp
+++ b/client/test/Logger-test.cpp
@@ -32,6 +32,17 @@ BOOST_AUTO_TEST_CASE( test_log )
     out.check();
 }
 
+
+BOOST_AUTO_TEST_CASE( test_log_srcinfo )
+{
+    ExpectedLogOut out("src:Debug:Logger-test.cpp: Debug Message\n");
+    Logger uut("src", out, Debug);
+
+    uut.logs(Debug, SRCINFO("$sf: ") + "Debug Message");
+    out.check();
+}
+
+
 BOOST_AUTO_TEST_CASE( test_logf )
 {
     ExpectedLogOut out("src:Critical:Critical message f00d\n");
@@ -41,6 +52,7 @@ BOOST_AUTO_TEST_CASE( test_logf )
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE( test_same_level )
 {
     ExpectedLogOut out("src:Debug:debug\n");
@@ -50,6 +62,7 @@ BOOST_AUTO_TEST_CASE( test_same_level )
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE( test_log_squelched )
 {
     ExpectedLogOut out("");
@@ -59,6 +72,7 @@ BOOST_AUTO_TEST_CASE( test_log_squelched )
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE(test_stream_on)
 {
     ExpectedLogOut out("src:Debug:debug\n");
@@ -68,6 +82,7 @@ BOOST_AUTO_TEST_CASE(test_stream_on)
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE(test_stream_off)
 {
     ExpectedLogOut out("");
@@ -77,6 +92,7 @@ BOOST_AUTO_TEST_CASE(test_stream_off)
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE(test_stream)
 {
     ExpectedLogOut out("src:Info:testing\n");
@@ -86,15 +102,61 @@ BOOST_AUTO_TEST_CASE(test_stream)
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE(test_stream_format)
 {
-    ExpectedLogOut out("src:Debug:debug f00d\n");
-    Logger uut("src", out, Debug);
+    char host[120];
+
+    BOOST_REQUIRE(gethostname(host,120)==0); 
+    ExpectedLogOut out("Debug:src:"+std::string(host)+": debug f00d\n");
+    Logger uut("src", out, Debug, "$p:$n:$h: $m");
 
     uut(Debug) << "debug " << std::hex << 61453 << '\n';
     out.check();
 }
 
+
+BOOST_AUTO_TEST_CASE(test_stream_timestamp)
+{
+    char ts[120];
+    time_t now = time(NULL);
+
+    strftime(ts,120,"%x %X",localtime(&now));
+
+    ExpectedLogOut out(std::string(ts)+": src:Debug:TimeStamp test:Logger-test.cpp\n");
+    Logger uut("src", out, Debug, "$t: $n:$p:$m");
+
+    uut(Debug) << "TimeStamp test:" << SRCINFO("$sf") << '\n';
+    out.check();
+}
+
+
+BOOST_AUTO_TEST_CASE(test_stream_timedelta)
+{
+    ExpectedLogOut out("0.001: src:Debug:TimeDelta test\n");
+    Logger uut("src", out, Debug, "$d: $n:$p:$m");
+
+    usleep(1000);  // force a millisecond to pass
+    uut(Debug) << "TimeDelta test" << '\n';
+    out.check();
+}
+
+
+BOOST_AUTO_TEST_CASE(test_stream_timestamp_formatted)
+{
+    char ts[120];
+    time_t now = time(NULL);
+
+    strftime(ts,120,"%x %H:%M:%S%p",localtime(&now));
+
+    ExpectedLogOut out(std::string(ts)+": src:Debug:TimeStamp format test\n");
+    Logger uut("src", out, Debug, "$t{%x %H:%M:%S%p}: $n:$p:$m");
+
+    uut(Debug) << "TimeStamp format test" << '\n';
+    out.check();
+}
+
+
 BOOST_AUTO_TEST_CASE(test_stream_lots)
 {
     ExpectedLogOut out("src:Debug:debug\nsrc:Info:info\n");
@@ -105,6 +167,7 @@ BOOST_AUTO_TEST_CASE(test_stream_lots)
     out.check();
 }
 
+
 BOOST_AUTO_TEST_CASE(test_endl)
 {
     ExpectedLogOut out("src:Info:testing\n");
diff --git a/include/AsteriskSCF/Logger/LogConsts.h b/include/AsteriskSCF/Logger/LogConsts.h
new file mode 100644
index 0000000..e82152d
--- /dev/null
+++ b/include/AsteriskSCF/Logger/LogConsts.h
@@ -0,0 +1,40 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace AsteriskSCF
+{
+namespace System
+{
+namespace Logging
+{
+
+const int MESSAGE_SIZE = 512;
+
+const int TIMESTAMP_SIZE = 64;
+
+const int HOSTNAME_SIZE = 128;
+
+const std::string DefaultLogFormat = "$n:$p:$m";
+
+const std::string TimestampFormat = "%x %X";
+
+} // Logging
+} // System
+} // AsteriskSCF
diff --git a/include/AsteriskSCF/Logger/LogFormatter.h b/include/AsteriskSCF/Logger/LogFormatter.h
new file mode 100644
index 0000000..63a0dbe
--- /dev/null
+++ b/include/AsteriskSCF/Logger/LogFormatter.h
@@ -0,0 +1,83 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#pragma once
+
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/current_function.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <AsteriskSCF/Logger/LogOut.h>
+#include <AsteriskSCF/Logger/Level.h>
+
+/**
+ * Prepends a format specifier identifier onto a format specifier string for the logger format string.
+ * This is a macro to make it easy to change this character, like to a % or something else if desired.
+ */
+#define SPECIFIER(S) "$" S
+
+/**
+ * Macro for getting some source information into a log message. 
+ * @param S formatting string for macro, can have the following specifiers (note: the $ is really whatever the SPECIFIER macro uses) :
+ * $l  -  current line number
+ * $f  -  current function name
+ * $sf -  source file name
+ * $sp -  source file name, including path
+ */
+#define SRCINFO(S) \
+      AsteriskSCF::System::Logging::sourceInfoStr(boost::lexical_cast<std::string>(S), \
+                                                  __LINE__, BOOST_CURRENT_FUNCTION, __FILE__)
+
+
+namespace AsteriskSCF
+{
+namespace System
+{
+namespace Logging
+{
+
+class LogFormatter
+{
+public:
+    LogFormatter(LogOut* out, const std::string& fmtStr = DefaultLogFormat);
+    LogFormatter(const LogFormatter& orig);
+    ~LogFormatter();
+    void setFormat(const std::string& fmtStr);
+    void setOutput(LogOut* out);
+    void logs(const std::string& name, Level level, const std::string& message);
+private:
+    LogOut* mOut;
+    std::string mFormat;
+    boost::posix_time::ptime mLastMsgTime;
+    boost::posix_time::time_duration timeDelta();
+};
+
+/**
+ * Returns a semi-formatted string containing some source code
+ * information (line, function, file)
+ */
+ASTERISK_SCF_ICEBOX_EXPORT std::string sourceInfoStr(const std::string& fmt, unsigned int line, 
+                                                     const char* fcn, const char* file);
+
+} // Logging
+} // System
+} // AsteriskSCF
diff --git a/include/AsteriskSCF/logger.h b/include/AsteriskSCF/logger.h
index 67065ab..ac218bb 100644
--- a/include/AsteriskSCF/logger.h
+++ b/include/AsteriskSCF/logger.h
@@ -18,16 +18,20 @@
 
 #include <ostream>
 #include <cstdarg>
+#include <string>
 
 #include <boost/shared_ptr.hpp>
 #include <boost/thread/locks.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <boost/weak_ptr.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include <AsteriskSCF/System/Logger/LoggerIf.h>
 #include <AsteriskSCF/Logger/Level.h>
 #include <AsteriskSCF/Logger/LogOut.h>
+#include <AsteriskSCF/Logger/LogConsts.h>
+#include <AsteriskSCF/Logger/LogFormatter.h>
 
 namespace AsteriskSCF
 {
@@ -44,7 +48,7 @@ namespace Logging
 class LogBuf : public std::streambuf
 {
 public:
-    ASTERISK_SCF_ICEBOX_EXPORT LogBuf(LogOut& out, const std::string& name, Level logLevel);
+    ASTERISK_SCF_ICEBOX_EXPORT LogBuf(const boost::shared_ptr<LogFormatter> formatter, const std::string& name, Level level);
 
     /**
      * Copy ctor.
@@ -59,12 +63,12 @@ protected:
 
 private:
     std::stringbuf mBuffer;
-    LogOut& mOut;
-    const std::string nName;
-    const Level mLogLevel;
+    boost::shared_ptr<LogFormatter> mFormatter;
+    std::string mName;
+    Level mLogLevel;
 
     /**
-     * Sends the current buffer to out and clears it.
+     * Sends the current buffer to the formatter and clears it.
      */
     void sendBuffer();
 };
@@ -76,9 +80,8 @@ private:
 class CondStream
 {
 public:
-    CondStream(LogOut& out, const std::string& name, Level logLevel,
-        bool enabled) :
-        mBuf(out, name, logLevel), mStream(&mBuf), mEnabled(enabled)
+    CondStream(boost::shared_ptr<LogFormatter> formatter, const std::string& name, Level level, bool enabled) :
+        mBuf(formatter,name,level), mStream(&mBuf), mEnabled(enabled)
     {
     }
 
@@ -157,10 +160,12 @@ private:
 public:
     /** Construct a Logger for an existing implementation */
     Logger(const boost::shared_ptr<LoggerImpl>& impl);
+
     /**
      * Construct a root Logger.
      */
-    Logger(const std::string& name, LogOut& out, Level logLevel = Debug);
+    Logger(const std::string& name, LogOut& out, Level logLevel = Debug,
+           const std::string& fmtStr = DefaultLogFormat);
 
     /**
      * If true, this Logger would log messages of the given Level.
@@ -181,7 +186,7 @@ public:
     /**
      * Log a single message.
      */
-    void logs(Level level, const std::string& message) const;
+    void logs(Level level, const std::string& message);
 
     /**
      * Log a single printf-formatted message.
@@ -189,7 +194,7 @@ public:
 #ifdef __GNUC__
     __attribute__((format(printf, 3, 4)))
 #endif
-    void logf(Level level, char const *fmt, ...) const;
+    void logf(Level level, char const *fmt, ...);
 
     /**
      * Log a single vprintf-formatted message.
@@ -197,7 +202,7 @@ public:
 #ifdef __GNUC__
     __attribute__((format(printf, 3, 0)))
 #endif
-    void vlogf(Level level, char const *fmt, va_list ap) const;
+    void vlogf(Level level, char const *fmt, va_list ap);
 
     Logger getChild(const std::string& childName);
 
@@ -210,13 +215,13 @@ public:
     void setOutput(LogOut& out);
 
     /**
-     * Set's the current logLevel.  Until unsetLevel() is called, we are no
+     * Sets the current logLevel.  Until unsetLevel() is called, we are no
      * longer affected by changes to our parent's log level.
      */
     void setLevel(Level logLevel);
 
     /**
-     * Changes our logLevel to now inherit from out parent.
+     * Changes our logLevel to now inherit from our parent.
      */
     void unsetLevel();
 
@@ -225,10 +230,39 @@ public:
      */
     Level getEffectiveLevel() const;
 
+    /**
+     * Sets the current format string for log messages for this logger.
+     * The format string is composed of format specifiers and other text, much like
+     * the printf statement. Valid format specifiers are (the $ is really whatever is
+     * defined by the SPECIFIER macro) :
+     * 
+     * $n - the name of the logger
+     * $p - the priority/level of the message being logged
+     * $h - the client host name
+     * $t - current time, can be further formatted with additional specifiers following the strftime() format. The 
+     *      additional specifiers should be in a set of curly braces, like: $t{%x %X} would format the time into a date/time string.
+     *      If no additional format specifiers are given (ie, just $t), the system uses whatever the TimestampFormat const is set to.
+     * $i - thread id
+     * $d - delta in time between this message and the last one (shows as seconds.milliseconds)
+     * $m - the message to log. You probably always want this one.
+     */
+    void setFormat(const std::string& fmtStr);
+
+    /**
+     * Reverts logger's formatter to whatever its parent's is
+     */
+    void unsetFormat();
+
+    /**
+     * Returns the effective formatter of this logger
+     */
+    boost::shared_ptr<LogFormatter> getEffectiveFormatter() const;
+
 private:
     boost::shared_ptr<LoggerImpl> mImpl;
 };
 
+
 class Logger::LoggerImpl
 {
 public:
@@ -236,16 +270,13 @@ public:
      * Construct a root Logger.
      */
     ASTERISK_SCF_ICEBOX_EXPORT LoggerImpl(const std::string& name, LogOut& out,
-        Level logLevel = Debug);
-
+        Level logLevel = Debug, const std::string& fmtStr = DefaultLogFormat);
     /**
      * Construct a child Logger.
      */
     ASTERISK_SCF_ICEBOX_EXPORT LoggerImpl(
         const boost::shared_ptr<LoggerImpl>& parent, const std::string& name);
-
     ASTERISK_SCF_ICEBOX_EXPORT ~LoggerImpl();
-
     /**
      * If true, this Logger would log messages of the given Level.
      *
@@ -256,7 +287,6 @@ public:
     {
         return level >= getEffectiveLevel();
     }
-
     /**
      * Ostream style logging.
      *
@@ -264,24 +294,20 @@ public:
      * @return LogStream that logs at the given level.
      */
     ASTERISK_SCF_ICEBOX_EXPORT CondStream operator()(Level level) const;
-
     /**
      * Log a single message.
      */
-    ASTERISK_SCF_ICEBOX_EXPORT void logs(Level level, const std::string& message) const;
-
+    ASTERISK_SCF_ICEBOX_EXPORT void logs(Level level, const std::string& message);
     /**
      * Log a single vprintf-formatted message.
      */
 #ifdef __GNUC__
     __attribute__((format(printf, 3, 0)))
 #endif
-    ASTERISK_SCF_ICEBOX_EXPORT void vlogf(Level level, char const *fmt, va_list ap) const;
-
+    ASTERISK_SCF_ICEBOX_EXPORT void vlogf(Level level, char const *fmt, va_list ap);
     ASTERISK_SCF_ICEBOX_EXPORT Logger getChild(
         const boost::shared_ptr<LoggerImpl>& self, const std::string& childName);
     ASTERISK_SCF_ICEBOX_EXPORT std::vector<Logger> getChildren() const;
-
     const std::string& getName() const
     {
         return mName;
@@ -295,21 +321,44 @@ public:
     ASTERISK_SCF_ICEBOX_EXPORT void setOutput(LogOut& out);
 
     /**
-     * Set's the current logLevel.  Until unsetLevel() is called, we are no
+     * Sets the current logLevel.  Until unsetLevel() is called, we are no
      * longer affected by changes to our parent's log level.
      */
     ASTERISK_SCF_ICEBOX_EXPORT void setLevel(Level logLevel);
-
     /**
      * Changes our logLevel to now inherit from out parent.
      */
     ASTERISK_SCF_ICEBOX_EXPORT void unsetLevel();
-
     /**
      * Returns the effective level of this Logger.
      */
     ASTERISK_SCF_ICEBOX_EXPORT Level getEffectiveLevel() const;
-
+    /**
+     * Sets the current format string for log messages for this logger.
+     * The format string is composed of format specifiers and other text, much like
+     * the printf statement. Valid format specifiers are (the $ is really whatever is
+     * defined by the SPECIFIER macro) :
+     * 
+     * $n - the name of the logger
+     * $p - the priority/level of the message being logged
+     * $h - the client host name
+     * $t - current time, can be further formatted with additional specifiers following the strftime() format. The 
+     *      additional specifiers should be in a set of curly braces, like: $t{%x %X} would format the time into a date/time string.
+     *      If no additional format specifiers are given (ie, just $t), the system uses whatever the TimestampFormat const is set to.
+     * $i - thread id
+     * $d - delta in time between this message and the last one (shows as seconds.milliseconds)
+     * $m - the message to log. You probably always want this one.
+     */
+    ASTERISK_SCF_ICEBOX_EXPORT void setFormat(const std::string& fmtStr);
+    /**
+     * Reverts logger's formatter to whatever its parent's is
+     */
+    ASTERISK_SCF_ICEBOX_EXPORT void unsetFormat();
+    /**
+     * Returns the effective format string of this logger
+     */
+    ASTERISK_SCF_ICEBOX_EXPORT boost::shared_ptr<LogFormatter> getEffectiveFormatter() const;
+    
 private:
     // non-copyable
     LoggerImpl(const Logger&);
@@ -335,7 +384,6 @@ private:
      * Map of children.  The key is the next final node in that child's name.
      */
     Children mChildren;
-
     /**
      * Name of this logger, in dotted-notation.
      */
@@ -344,22 +392,30 @@ private:
      * Output for log messages.
      */
     LogOut *mOut;
-
     /**
-     * Mutex for accessing mLogLevel and mInheritedLevel.  It's a shared_mutext
+     * Mutex for accessing mLogLevel, mInherited, and mFormatter.  It's a shared_mutex
      * to reduce read contention on the mutex.
      */
-    mutable boost::shared_mutex mLevelMutex;
+    mutable boost::shared_mutex mInheritedMutex;
     /**
      * Current level of this Logger.  Only applicable if inheritedLevel == false.
      */
     Level mLogLevel;
     /**
-     * If true, then our effectiveLevel == parent->effectiveLevel.
+     * Current formatter for this logger
+     */
+    boost::shared_ptr<LogFormatter> mFormatter; 
+    /**
+     * If true, then our effectiveLevel == parent->effectiveLevel 
      */
     bool mInheritedLevel;
+    /**
+     * If true, then our effectiveFormatter == parent->effectiveFormatter
+     */
+    bool mInheritedFormatter;
 };
 
+
 // since these are all simple delegates to LoggerImpl, inline them
 
 inline Logger::Logger(const boost::shared_ptr<LoggerImpl>& impl) :
@@ -367,24 +423,33 @@ inline Logger::Logger(const boost::shared_ptr<LoggerImpl>& impl) :
 {
 }
 
-inline Logger::Logger(const std::string& name, LogOut& out, Level logLevel) :
-    mImpl(new LoggerImpl(name, out, logLevel))
+
+inline Logger::Logger(const std::string& name, LogOut& out, Level logLevel,
+        const std::string& fmtStr) :
+    mImpl(new LoggerImpl(name, out, logLevel, fmtStr))
 {
 }
 
+
 inline bool Logger::isEnabledFor(Level level) const
 {
     return mImpl->isEnabledFor(level);
 }
+
+
 inline CondStream Logger::operator()(Level level) const
 {
     return (*mImpl)(level);
 }
-inline void Logger::logs(Level level, const std::string& message) const
+
+
+inline void Logger::logs(Level level, const std::string& message)
 {
     mImpl->logs(level, message);
 }
-inline void Logger::logf(Level level, char const *fmt, ...) const
+
+
+inline void Logger::logf(Level level, char const *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -399,43 +464,80 @@ inline void Logger::logf(Level level, char const *fmt, ...) const
     }
     va_end(ap);
 }
-inline void Logger::vlogf(Level level, char const *fmt, va_list ap) const
+
+
+inline void Logger::vlogf(Level level, char const *fmt, va_list ap)
 {
     mImpl->vlogf(level, fmt, ap);
 }
+
+
 inline Logger Logger::getChild(const std::string& childName)
 {
     return mImpl->getChild(mImpl, childName);
 }
+
+
 inline std::vector<Logger> Logger::getChildren() const
 {
     return mImpl->getChildren();
 }
+
+
 inline const std::string& Logger::getName() const
 {
     return mImpl->getName();
 }
+
+
 inline LogOut& Logger::getOutput() const
 {
     return mImpl->getOutput();
 }
+
+
 inline void Logger::setOutput(LogOut& out)
 {
     mImpl->setOutput(out);
 }
+
+
 inline void Logger::setLevel(Level logLevel)
 {
     mImpl->setLevel(logLevel);
 }
+
+
 inline void Logger::unsetLevel()
 {
     mImpl->unsetLevel();
 }
+
+
 inline Level Logger::getEffectiveLevel() const
 {
     return mImpl->getEffectiveLevel();
 }
 
+
+inline void Logger::setFormat(const std::string& fmtStr)
+{
+    mImpl->setFormat(fmtStr);
+}
+
+
+inline void Logger::unsetFormat()
+{
+    mImpl->unsetFormat();
+}
+
+
+inline boost::shared_ptr<LogFormatter> Logger::getEffectiveFormatter() const 
+{
+    return mImpl->getEffectiveFormatter();
+}
+
+
 /**
  * Main entry point into the Logger system.
  */
@@ -475,6 +577,11 @@ ASTERISK_SCF_ICEBOX_EXPORT boost::shared_ptr<LogOut> buildOstreamLogger(std::ost
  */
 ASTERISK_SCF_ICEBOX_EXPORT LoggerFactory& getLoggerFactory();
 
+
+ASTERISK_SCF_ICEBOX_EXPORT std::string formatLogString(const std::string& fmt, const std::string& msg,
+        Level level, const std::string& name, const boost::posix_time::time_duration& delta);
+
+
 } // Logging
 } // System
 } // AsteriskSCF

commit f72807265551350b1046235d1ef1bac5a4129d0f
Author: David M. Lee <dlee at digium.com>
Date:   Fri Apr 15 13:38:56 2011 -0500

    Fixed signed/unsigned mixing warning.

diff --git a/server/src/ChainedLogOut.cpp b/server/src/ChainedLogOut.cpp
index 66a6e71..65c2166 100644
--- a/server/src/ChainedLogOut.cpp
+++ b/server/src/ChainedLogOut.cpp
@@ -56,12 +56,16 @@ std::ostream& ChainedLogOut::logs(std::ostream& out, const std::string& name,
     Level logLevel, const std::string& message)
 {
     // date level name(1) message
-    std::string::size_type lastDot = name.rfind('.');
-    if (lastDot == std::string::npos)
+    std::string::size_type nameStart = name.rfind('.');
+    if (nameStart == std::string::npos)
     {
-        lastDot = -1;
+        nameStart = 0;
     }
-    std::string lastname = name.substr(lastDot + 1);
+    else
+    {
+        ++nameStart;
+    }
+    std::string lastname = name.substr(nameStart);
     {
         std::ostream::fmtflags flags = out.flags();
         out << getCurrentTime() << ' ' << std::setw(9) << logLevel << ' '

commit f4de0d7e6036e93e56e282277c73ace693245218
Author: David M. Lee <dlee at digium.com>
Date:   Fri Apr 15 10:21:19 2011 -0500

    Removed extra print I should not have comitted.

diff --git a/client/src/IceLogger.cpp b/client/src/IceLogger.cpp
index 5bc5efd..2cba8ae 100644
--- a/client/src/IceLogger.cpp
+++ b/client/src/IceLogger.cpp
@@ -105,7 +105,6 @@ void ConfiguredIceLogger::updateLoggerFromServiceLocator()
 
 void ConfiguredIceLogger::locateFinished(const Ice::AsyncResultPtr& r)
 {
-  std::clog << "==> " << this << '\n';
     ServiceLocatorPrx locator = ServiceLocatorPrx::uncheckedCast(r->getProxy());
     try
     {

commit 7f9676d31bd13ab3fbd04e749ecbda42707fd2b5
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Thu Apr 14 13:25:27 2011 -0500

    Minor fixes for various code constructs that trip up GCC with new warning
    options enabled (-Wextra, -Wconversion, -Wformat, and others).

diff --git a/client/src/IceLogger.cpp b/client/src/IceLogger.cpp
index 84ca654..5bc5efd 100644
--- a/client/src/IceLogger.cpp
+++ b/client/src/IceLogger.cpp
@@ -133,13 +133,13 @@ void ConfiguredIceLogger::locateFinished(const Ice::AsyncResultPtr& r)
     }
 }
 
-void ConfiguredIceLogger::comparisonRegistered(const std::string& guid,
+void ConfiguredIceLogger::comparisonRegistered(const std::string& /* guid */,
     const Ice::Current&)
 {
     // no-op
 }
 
-void ConfiguredIceLogger::comparisonUnregistered(const std::string& guid,
+void ConfiguredIceLogger::comparisonUnregistered(const std::string& /* guid */,
     const Ice::Current&)
 {
     // no-op
diff --git a/client/src/Logger.cpp b/client/src/Logger.cpp
index bd56c19..99b651b 100644
--- a/client/src/Logger.cpp
+++ b/client/src/Logger.cpp
@@ -28,8 +28,13 @@ LogBuf::LogBuf(LogOut& out, const std::string& name, Level logLevel) :
 {
 }
 
+// NOTE: The copy constructor below intentionally calls the default constructor of its
+// std::streambuf base, rather than calling the copy constructor. The copy constructor
+// of std::streambuf is private (so it cannot be called), but more importantly, the
+// std::streambuf base object has no useful state that needs to be copied when a
+// LogBuf is copied.
 LogBuf::LogBuf(const LogBuf& orig) :
-    mOut(orig.mOut), nName(orig.nName), mLogLevel(orig.mLogLevel)
+    std::streambuf(), mOut(orig.mOut), nName(orig.nName), mLogLevel(orig.mLogLevel)
 {
     mBuffer.str(orig.mBuffer.str());
 }
@@ -49,7 +54,7 @@ int LogBuf::overflow(int c)
         sendBuffer();
         return c;
     }
-    return mBuffer.sputc(c);
+    return mBuffer.sputc((char) c);
 }
 
 void LogBuf::sendBuffer()
diff --git a/include/AsteriskSCF/logger.h b/include/AsteriskSCF/logger.h
index 9cabc4c..67065ab 100644
--- a/include/AsteriskSCF/logger.h
+++ b/include/AsteriskSCF/logger.h
@@ -186,11 +186,17 @@ public:
     /**
      * Log a single printf-formatted message.
      */
+#ifdef __GNUC__
+    __attribute__((format(printf, 3, 4)))
+#endif
     void logf(Level level, char const *fmt, ...) const;
 
     /**
      * Log a single vprintf-formatted message.
      */
+#ifdef __GNUC__
+    __attribute__((format(printf, 3, 0)))
+#endif
     void vlogf(Level level, char const *fmt, va_list ap) const;
 
     Logger getChild(const std::string& childName);
@@ -267,6 +273,9 @@ public:
     /**
      * Log a single vprintf-formatted message.
      */
+#ifdef __GNUC__
+    __attribute__((format(printf, 3, 0)))
+#endif
     ASTERISK_SCF_ICEBOX_EXPORT void vlogf(Level level, char const *fmt, va_list ap) const;
 
     ASTERISK_SCF_ICEBOX_EXPORT Logger getChild(
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 90d2abc..0723e0a 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -101,9 +101,9 @@ void LoggingService::setDefaultProperty(Ice::Properties& props,
     }
 }
 
-void LoggingService::start(const std::string& name,
+void LoggingService::start(const std::string&,
     const Ice::CommunicatorPtr& communicator,
-    const Ice::StringSeq& args)
+    const Ice::StringSeq&)
 {
     setupDefaultProperties(communicator);
 
@@ -181,7 +181,7 @@ void LoggingService::stop()
 }
 
 extern "C" ASTERISK_SCF_ICEBOX_EXPORT IceBox::Service* createLoggingService(
-    Ice::CommunicatorPtr communicator)
+    Ice::CommunicatorPtr)
 {
     return new LoggingService;
 }

commit 9269caafa5e14d096519ac719c35304e616a673a
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Tue Apr 12 16:34:42 2011 -0500

    Resolve a variable shadowing warning.

diff --git a/client/test/ExpectedLogOut.h b/client/test/ExpectedLogOut.h
index 2fdcb02..5617129 100644
--- a/client/test/ExpectedLogOut.h
+++ b/client/test/ExpectedLogOut.h
@@ -24,24 +24,24 @@ class ExpectedLogOut : public LogOut
 {
 public:
     ExpectedLogOut(const std::string& expected) :
-        expected(expected)
+        mExpected(expected)
     {
     }
 
     void logs(const std::string& name, Level logLevel,
         const std::string& message)
     {
-        actual << name << ":" << logLevel << ":" << message << '\n';
+        mActual << name << ":" << logLevel << ":" << message << '\n';
     }
 
     void check()
     {
-        BOOST_CHECK_EQUAL(expected, actual.str());
+        BOOST_CHECK_EQUAL(mExpected, mActual.str());
     }
 
 private:
-    std::string expected;
-    std::stringstream actual;
+    std::string mExpected;
+    std::stringstream mActual;
 };
 
 

commit 12e7b02ac0de5f2e71591870faca2932525a5984
Author: Brent Eagles <beagles at digium.com>
Date:   Fri Apr 1 12:13:00 2011 -0230

    Fix compilation error and some formatting issues.

diff --git a/client/src/IceLogger.cpp b/client/src/IceLogger.cpp
index 4f00e07..84ca654 100644
--- a/client/src/IceLogger.cpp
+++ b/client/src/IceLogger.cpp
@@ -48,7 +48,8 @@ void IceLogger::logs(const std::string& name, Level logLevel,
 
     if (!logged)
     {
-        if (!mHasPrintedNoServerNotice) {
+        if (!mHasPrintedNoServerNotice)
+        {
             mHasPrintedNoServerNotice = true;
             std::clog <<
                 "!!! Unable to log to server.  Please check configuration and server status.\n"
@@ -59,13 +60,14 @@ void IceLogger::logs(const std::string& name, Level logLevel,
 }
 
 IceUtil::Handle<ConfiguredIceLogger> ConfiguredIceLogger::create(
-    const LoggingServerPrx& server) {
+    const LoggingServerPrx& server)
+{
     ConfiguredIceLoggerPtr r = new ConfiguredIceLogger(server);
     return r;
 }
 
-IceUtil::Handle<ConfiguredIceLogger> ConfiguredIceLogger::create(
-    const Core::Discovery::V1::ServiceLocatorPrx& locator) {
+IceUtil::Handle<ConfiguredIceLogger> ConfiguredIceLogger::create(const ServiceLocatorPrx& locator)
+{
     // You cannot call updateLoggerFromServiceLocator directly from the ctor.
     // It implicitly creates a ConfiguredIceLoggerPtr for the AMI call.  If the
     // AMI call completes before the ctor complete, then the object will be
@@ -93,11 +95,9 @@ void ConfiguredIceLogger::updateLoggerFromServiceLocator()
         // we must use AMI to free this thread up for servicing requests
         // if this client is used by the service locator itself, a
         // synchronous call to locate would result in a deadlock
-        ServiceLocatorParamsPtr loggingServerParams =
-            new ServiceLocatorParams(LoggingServerCategory);
+        ServiceLocatorParamsPtr loggingServerParams = new ServiceLocatorParams(LoggingServerCategory);
 
-        Ice::CallbackPtr callback = Ice::newCallback(
-            this, &ConfiguredIceLogger::locateFinished);
+        Ice::CallbackPtr callback = Ice::newCallback(this, &ConfiguredIceLogger::locateFinished);
 
         mLocator->begin_locate(loggingServerParams, callback);
     }
@@ -128,8 +128,7 @@ void ConfiguredIceLogger::locateFinished(const Ice::AsyncResultPtr& r)
     }
     catch (const std::exception& e)
     {
-        std::clog << "(Logger) Failed to locate LoggerService: " <<
-            e.what() << '\n';
+        std::clog << "(Logger) Failed to locate LoggerService: " << e.what() << '\n';
         mLogger.setServer(LoggingServerPrx());
     }
 }
@@ -139,11 +138,13 @@ void ConfiguredIceLogger::comparisonRegistered(const std::string& guid,
 {
     // no-op
 }
+
 void ConfiguredIceLogger::comparisonUnregistered(const std::string& guid,
     const Ice::Current&)
 {
     // no-op
 }
+
 void ConfiguredIceLogger::serviceRegistered(const std::string& guid,
     const Ice::Current&)
 {
@@ -152,6 +153,7 @@ void ConfiguredIceLogger::serviceRegistered(const std::string& guid,
         updateLoggerFromServiceLocator();
     }
 }
+
 void ConfiguredIceLogger::serviceUnregistered(const std::string& guid,
     const Ice::Current&)
 {
@@ -160,6 +162,7 @@ void ConfiguredIceLogger::serviceUnregistered(const std::string& guid,
         updateLoggerFromServiceLocator();
     }
 }
+
 void ConfiguredIceLogger::serviceSuspended(const std::string& guid,
     const Ice::Current&)
 {
@@ -168,6 +171,7 @@ void ConfiguredIceLogger::serviceSuspended(const std::string& guid,
         updateLoggerFromServiceLocator();
     }
 }
+
 void ConfiguredIceLogger::serviceUnsuspended(const std::string& guid,
     const Ice::Current&)
 {
@@ -240,7 +244,5 @@ ConfiguredIceLoggerPtr AsteriskSCF::System::Logging::createIceLogger(
         std::clog << "(Logger) TopicManager.Proxy not set.  "
             "Will not receive updates.\n";
     }
-
     return logger;
-
 }

commit 3a5e8dcbb6ebd33be6397971509b59557063f8b8
Author: David M. Lee <dlee at digium.com>
Date:   Thu Mar 31 16:04:50 2011 -0500

    Fixed race condition in ConfiguredIceLogger ctor
    
    ConfiguredIceLogger was calling updateLoggerFromServiceLocator() in its
    ctor.  This implicitly created a IceUtil::Handle for the object.  If the
    AMI call completed before the ctor finished, then the object would be
    destroyed before the caller could created their own Handle.
    
    The factory functions ensure that a Handle is created prior to invoking
    the AMI call.

diff --git a/client/src/IceLogger.cpp b/client/src/IceLogger.cpp
index c27d05b..4f00e07 100644
--- a/client/src/IceLogger.cpp
+++ b/client/src/IceLogger.cpp
@@ -58,6 +58,23 @@ void IceLogger::logs(const std::string& name, Level logLevel,
     }
 }
 
+IceUtil::Handle<ConfiguredIceLogger> ConfiguredIceLogger::create(
+    const LoggingServerPrx& server) {
+    ConfiguredIceLoggerPtr r = new ConfiguredIceLogger(server);
+    return r;
+}
+
+IceUtil::Handle<ConfiguredIceLogger> ConfiguredIceLogger::create(
+    const Core::Discovery::V1::ServiceLocatorPrx& locator) {
+    // You cannot call updateLoggerFromServiceLocator directly from the ctor.
+    // It implicitly creates a ConfiguredIceLoggerPtr for the AMI call.  If the
+    // AMI call completes before the ctor complete, then the object will be
+    // deleted before the callee can create their own ConfiguredIceLoggerPtr.
+    ConfiguredIceLoggerPtr r = new ConfiguredIceLogger(locator);
+    r->updateLoggerFromServiceLocator();
+    return r;
+}
+
 ConfiguredIceLogger::ConfiguredIceLogger(const LoggingServerPrx& server)
 {
     mLogger.setServer(server);
@@ -66,7 +83,7 @@ ConfiguredIceLogger::ConfiguredIceLogger(const LoggingServerPrx& server)
 ConfiguredIceLogger::ConfiguredIceLogger(const ServiceLocatorPrx& locator) :
     mLocator(locator)
 {
-    updateLoggerFromServiceLocator();
+    // do not call updateLoggerFromServiceLocator.  see comment in create()
 }
 
 void ConfiguredIceLogger::updateLoggerFromServiceLocator()
@@ -88,6 +105,7 @@ void ConfiguredIceLogger::updateLoggerFromServiceLocator()
 
 void ConfiguredIceLogger::locateFinished(const Ice::AsyncResultPtr& r)
 {
+  std::clog << "==> " << this << '\n';
     ServiceLocatorPrx locator = ServiceLocatorPrx::uncheckedCast(r->getProxy());
     try
     {
@@ -171,7 +189,7 @@ ConfiguredIceLoggerPtr AsteriskSCF::System::Logging::createIceLogger(
             "LoggerServer.Proxy");
         if (server)
         {
-            return ConfiguredIceLoggerPtr(new ConfiguredIceLogger(
+            return ConfiguredIceLoggerPtr(ConfiguredIceLogger::create(
                     LoggingServerPrx::checkedCast(server)));
         }
     }
@@ -194,8 +212,7 @@ ConfiguredIceLoggerPtr AsteriskSCF::System::Logging::createIceLogger(
                   << LoggingServerGuid << '\n';
     }
 
-    ConfiguredIceLoggerPtr logger = new ConfiguredIceLogger(locator);
-    logger->updateLoggerFromServiceLocator();
+    ConfiguredIceLoggerPtr logger = ConfiguredIceLogger::create(locator);
 
     IceStorm::TopicManagerPrx topicManager =
         IceStorm::TopicManagerPrx::uncheckedCast(
diff --git a/include/AsteriskSCF/Logger/IceLogger.h b/include/AsteriskSCF/Logger/IceLogger.h
index cc74d06..3719f99 100644
--- a/include/AsteriskSCF/Logger/IceLogger.h
+++ b/include/AsteriskSCF/Logger/IceLogger.h
@@ -48,17 +48,19 @@ class ConfiguredIceLogger : public Discovery::Events
 {
 public:
     /**
-     * Configure an IceLogger directly with the LoggingServer.
+     * Factory function to create an IceLogger directly with the LoggingServer.
      *
      * @param server Server proxy to log to.
      */
-    ConfiguredIceLogger(const LoggingServerPrx& server);
+    static IceUtil::Handle<ConfiguredIceLogger> create(
+        const LoggingServerPrx& server);
     /**
      * Configure an IceLogger which gets LoggingServer from the ServiceLocator.
      *
      * @param locator Locator to use to get the LoggingServer proxy.
      */
-    ConfiguredIceLogger(const Core::Discovery::V1::ServiceLocatorPrx& locator);
+    static IceUtil::Handle<ConfiguredIceLogger> create(
+        const Core::Discovery::V1::ServiceLocatorPrx& locator);
 
     LogOut& getLogger() { return mLogger; }
 
@@ -71,6 +73,20 @@ public:
     void serviceSuspended(const std::string& guid, const Ice::Current&);
     void serviceUnsuspended(const std::string& guid, const Ice::Current&);
 
+protected:
+    /**
+     * Configure an IceLogger directly with the LoggingServer.
+     *
+     * @param server Server proxy to log to.
+     */
+    ConfiguredIceLogger(const LoggingServerPrx& server);
+    /**
+     * Configure an IceLogger which gets LoggingServer from the ServiceLocator.
+     *
+     * @param locator Locator to use to get the LoggingServer proxy.
+     */
+    ConfiguredIceLogger(const Core::Discovery::V1::ServiceLocatorPrx& locator);
+
 private:
     IceLogger mLogger;
     Core::Discovery::V1::ServiceLocatorPrx mLocator;

commit 7d3ca9ec1f0dd4e2deb1b1b31ea30ed3bf3dc2f0
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Mar 21 19:59:26 2011 -0500

    Fixed several issues discovered during UTF string testing.
     - ConfiguredIceLogger.cpp - Constructor initialization was commented out.
     - Others: The LocatorServiceMangement.Proxy property was named differently from every other components reference to that proxy, requiring duplicate config entries.

diff --git a/client/src/IceLogger.cpp b/client/src/IceLogger.cpp
index 42622c6..c27d05b 100644
--- a/client/src/IceLogger.cpp
+++ b/client/src/IceLogger.cpp
@@ -66,7 +66,7 @@ ConfiguredIceLogger::ConfiguredIceLogger(const LoggingServerPrx& server)
 ConfiguredIceLogger::ConfiguredIceLogger(const ServiceLocatorPrx& locator) :
     mLocator(locator)
 {
-    //updateLoggerFromServiceLocator();
+    updateLoggerFromServiceLocator();
 }
 
 void ConfiguredIceLogger::updateLoggerFromServiceLocator()
diff --git a/server/config/logging-server.conf b/server/config/logging-server.conf
index 0cf4f37..4611cfb 100644
--- a/server/config/logging-server.conf
+++ b/server/config/logging-server.conf
@@ -8,7 +8,7 @@ IceBox.Service.Logger=logging-service:createLoggingService
 AsteriskSCF.LoggingService.Endpoints=default
 
 # A proxy to the service locator management service
-ServiceLocatorManagement.Proxy=LocatorServiceManagement:tcp -p 4422
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
 
 # A proxy to the IceStorm topic manager
 TopicManager.Proxy=AsteriskSCFIceStorm/TopicManager:default -p 10000
diff --git a/server/src/main.cpp b/server/src/main.cpp
index 7f1d5ca..90d2abc 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -58,9 +58,10 @@ void LoggingService::registerWithServiceLocator(
 {
     try
     {
+        std::string locatorServiceProxyStr("LocatorServiceManagement.Proxy");
         std::string locatorManagementProxyString =
             communicator->getProperties()->getProperty(
-                "ServiceLocatorManagement.Proxy");
+               locatorServiceProxyStr);
         if (!locatorManagementProxyString.empty())
         {
             ServiceLocatorManagementPrx management =
@@ -72,6 +73,10 @@ void LoggingService::registerWithServiceLocator(
                 LoggingServerCategory);
             mServiceManagement->addLocatorParams(params, "");
         }
+        else
+        {
+            std::clog << locatorServiceProxyStr << " not defined. ";
+        }
     }
     catch (const std::exception& e)
     {

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/logger.git



More information about the asterisk-scf-commits mailing list