[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: 224
Joined: Fri Sep 13, 2013 2:59 pm

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

Post by Rudra »

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: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

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

Post by doublemax »

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: 4204
Joined: Sun Jan 03, 2010 5:45 pm

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

Post by PB »

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 1670 times
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

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

Post by PB »

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: 224
Joined: Fri Sep 13, 2013 2:59 pm

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

Post by Rudra »

Thanks for the reply.
It works for me.
Post Reply