[wxOSX][3.0.2] Adding function name, line to wxLog Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Rudra
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 214
Joined: Fri Sep 13, 2013 2:59 pm

[wxOSX][3.0.2] Adding function name, line to wxLog

Post by Rudra » Tue Aug 23, 2016 2:15 pm

Hi,

I just started with wxLog. I want to add function name and line number to the each log message. Do we have any macro or function like SetTimestamp for them.

Please suggest.

Thanks,
R.

User avatar
doublemax
Moderator
Moderator
Posts: 13881
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: [wxOSX][3.0.2] Adding function name, line to wxLog

Post by doublemax » Tue Aug 23, 2016 2:58 pm

Most compilers support the __LINE__ __FILE__ and __FUNCTION__ macros (among others).

https://gcc.gnu.org/onlinedocs/cpp/Stan ... acros.html
Use the source, Luke!

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2007
Joined: Sun Jan 03, 2010 5:45 pm

Re: [wxOSX][3.0.2] Adding function name, line to wxLog

Post by PB » Tue Aug 23, 2016 5:21 pm

I am afraid wxWidgets don't support something like this out of the box.

I would try something like this:

Code: Select all

#include <wx/wx.h>
#include <wx/log.h>

class LogFormatterWithFunctionInfo : public wxLogFormatter
{
    virtual wxString Format(wxLogLevel level,
                            const wxString& msg,
                            const wxLogRecordInfo& info) const 
    {
        
        return wxString::Format("%s [%s %s(%d)]",
            wxLogFormatter::Format(level, msg, info),
            info.func, info.filename, info.line);
    }
};


void TestLogFn()
{
    wxLogMessage("Hello");
}


class MyFrame : public wxFrame
{
public:
    MyFrame()
        : wxFrame(NULL, wxID_ANY, _("Test"), wxDefaultPosition, wxSize(400, 700))
    {                
        wxTextCtrl* textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
        delete wxLog::SetActiveTarget(new wxLogTextCtrl(textCtrl));
        // wxLog::DisableTimestamp();
        wxLog* log = wxLog::GetActiveTarget();
        if ( log )
            delete log->SetFormatter(new LogFormatterWithFunctionInfo);

        wxLogMessage("Hello");
        TestLogMethod();
        TestLogFn();
    }   
private:  
    void TestLogMethod()
    {
        wxLogMessage("Hello");
    }
};

class MyApp : public wxApp
{
public:   
    virtual bool OnInit()
    {
        (new MyFrame())->Show();
        return true;
    }
};
wxIMPLEMENT_APP(MyApp);
formatter.png
formatter.png (20.25 KiB) Viewed 571 times

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2007
Joined: Sun Jan 03, 2010 5:45 pm

Re: [wxOSX][3.0.2] Adding function name, line to wxLog

Post by PB » Tue Aug 23, 2016 9:24 pm

I have remembered that I had some code which logs extended information into a file. The code is based on presumption that we want to log some extra information but we do not want to bother the user with it, so we need to have several log targets.

In the example below, there is a demonstration of three chained log targets:
1. The default GUI target (dialog box)
2. Log text control created in the main frame constructor.
3. Persistent application log with extended information, implemented with wxFFile.

Of course, if you need the log for immediate diagnostics, perhaps it is better to collect the log message some other way and then have the application send the messages home via the internet. But this is beyond the topic.

Code: Select all

#include <wx/wx.h>
#include <wx/log.h>
#include <wx/datetime.h>
#include <wx/ffile.h>
#include <wx/msgdlg.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>

class wxFFileLog : public wxLog
{    
public:        
    wxFFileLog(const wxString& fileName)         
    {         
        wxLogNull ln;
        if ( m_logFile.Open(fileName, "a+") )        
            m_logFile.Write(wxString::Format("(%s) === LOGGING STARTED ===\n",
                wxDateTime::Now().FormatISOCombined(' ')));
    }

    ~wxFFileLog()
    {
        if ( IsLogFileOK() )
            m_logFile.Write(wxString::Format("(%s) === LOGGING FINISHED ===\n\n", 
                wxDateTime::Now().FormatISOCombined(' ')));
    }
        
    virtual void Flush() 
    { 
        if ( m_logFile.IsOpened() )
            m_logFile.Flush(); 
    }

    bool IsLogFileOK() const { return m_logFile.IsOpened() && !m_logFile.Error(); }
    wxString GetLogFileName() const { return m_logFile.GetName(); }    

protected:
    virtual void DoLogRecord(wxLogLevel level, const wxString& msg, const wxLogRecordInfo& info)
    {
        if ( !IsLogFileOK() )
            return;

        wxString prefix;

        prefix.Printf("(%s) ", wxDateTime(info.timestamp).FormatISOCombined(' '));
        
        switch ( level )
        {
            case wxLOG_Error:
                prefix += "ERROR: ";
                break;

            case wxLOG_Warning:
                prefix += "Warning: ";
                break;

            case wxLOG_Message:
                prefix += "Message: ";
                break;

            case wxLOG_Status:
                prefix += "Status: ";
                break;

            case wxLOG_Info:
                prefix += "Info: ";
                break;

            case wxLOG_Debug:                
                prefix += "Debug: ";
                break;

            case wxLOG_Trace:
                prefix += "Trace: ";
                break;

            default:
                prefix += "Other: ";
        }        

        m_logFile.Write(wxString::Format("%s%s [%s in %s(%d)]\n", prefix, msg, info.func, info.filename, info.line));        
    }

private:
    wxFFile  m_logFile;    
};

void TestLogFn()
{
    wxLogMessage("Hello");
}

class MyFrame : public wxFrame
{
public:
    MyFrame()
        : wxFrame(NULL, wxID_ANY, _("Test"), wxDefaultPosition, wxSize(300, 400))
    {                              
        wxTextCtrl* textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
        new wxLogChain(new wxLogTextCtrl(textCtrl));        

        wxLogError("This is error.");
        wxLogWarning("This is warning.");
        wxLogInfo("This is info.");
        TestLogMethod();
        TestLogFn();
    }   
private:  
    void TestLogMethod()
    {
        wxLogMessage("Hello");
    }
};

class MyApp : public wxApp
{
public:     
    virtual bool OnInit()
    {        
        if ( !wxApp::OnInit() )
            return false;
        
        wxString fileName(wxFileName(wxStandardPaths::Get().GetUserLocalDataDir(), "application_log.txt").GetFullPath());
        wxFFileLog* appLog = new wxFFileLog(fileName);

        if ( appLog->IsLogFileOK() )
        {
            new wxLogChain(appLog);
        }
        else
        {
            wxString msg;

            msg.Printf(_("Could not initialize the application log (file \"%s\"). \n\nContinue anyway?"), 
                appLog->GetLogFileName());
            delete appLog;

            if ( wxMessageBox(msg, _("Error"), wxYES_NO | wxICON_ERROR, NULL) 
                 != wxYES )
            {
                return false;
            }
        }

        (new MyFrame())->Show();
        return true;
    }

    virtual int OnExit()
    {
        delete wxLog::SetActiveTarget(NULL);        
        return wxApp::OnExit();
    }
};
wxIMPLEMENT_APP(MyApp);

Rudra
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 214
Joined: Fri Sep 13, 2013 2:59 pm

Re: [wxOSX][3.0.2] Adding function name, line to wxLog

Post by Rudra » Wed Aug 24, 2016 10:09 am

Thanks for the reply.
It works for me.

Post Reply