Get name of calling function, line number and file name in c++

8.5k views Asked by At

I have wrote following code to write logs in my log file. This code is working fine for logging messages but now i have to integrate this in multiple files i need file path of caller, caller function name and line number.

Kindly help me to achieve this .

#include "Source.h"

bool CLogManager::fileOpenError = false;
std::string CLogManager::logFileName = "";
CLogManager* CLogManager::logManager = NULL;
FILE* CLogManager::file = NULL;

CLogManager :: CLogManager(){}
CLogManager :: ~CLogManager()
{
    if (file)
        fclose(file);
}
CLogManager* CLogManager::getInstance()
{
    if(logManager==NULL)
    {
        logManager = new CLogManager();
        logFileName = currentDateTime();
    }
    return logManager;
}
const std::string CLogManager::currentDateTime()
{
    time_t now = time(0);
    char currTime[30];
    strftime(currTime, sizeof(currTime), "Log_%Y_%m_%dT%H_%M_%S.xml", localtime(&now));
    return currTime;
}
void CLogManager::Log (char *message)
{
    file = fopen(logFileName.c_str(), "a+");
    if(file == NULL) 
    {
        if(fileOpenError == false)
        {
            std::cout << "There was an error While opening Log File."<<std::endl;
            fileOpenError = true;
        }
        return;
    }
    fputs(message, file);
    fputs("\n", file);
}

int main ()
{
    CLogManager::getInstance();
    CLogManager::Log("Sorry some error occured");
    CLogManager::Log("Please try again");
    CLogManager::Log("Wait");
    return 0;
}
3

There are 3 answers

1
luk32 On BEST ANSWER

When I need a fast "printf" logging, I use this marco for message logging that is branded with filename and line:

#define _MSG(msg) do{ std::cerr << __FILE__ << "(@" << __LINE__ << "): " << msg << '\n'; } while( false )

The above macro will inject a msg into a std::cerr pipeline. You can take out parts you need or modify it for your purposes. It hinges on __FILE__ and __LINE__ macros, which are defined by standard:

__FILE__ The presumed name of the current source file (a character string literal).

__LINE__ The presumed line number (within the current source file) of the current source line (an integer constant).

Function names are not so easy to get, and I don't think there is a nice way to get it.

If you want logging through functions I would define some macro, or make function that would take int and char* for line and file respectively. Something like log(int line, char* source_file, string message).

0
Amadeus On

To utilize the LogManager class that you already have written, you could do something like this:

void CLogManager::Log(char *message, std::string FileName = "Unset", std::string FunctionName = "Unset", int LineNumber = -1)
{
...
}

Then, anywhere you want to use your Logging function as it is right now, you would just do:

::Log(message);

But, if you wanted to include File/Function/Line information, you would do this:

::Log(message, __FILE__, __FUNCTION__, __LINE__);

You can adjust the defaults from "Unset" to anything you wanted (including just ""). I might also suggest in that function that you could have the output be different based upon whether the FileName parameter (passed to the function) is the default or not. That way your log file would look clean.

0
JVE999 On

Since C++ 20, you can use std::source_location.

From the example on CPPReference.com:

#include <iostream>
#include <string_view>
#include <source_location>
 
void log(const std::string_view message,
         const std::source_location location = 
               std::source_location::current())
{
    std::cout << "file: "
              << location.file_name() << "("
              << location.line() << ":"
              << location.column() << ") `"
              << location.function_name() << "`: "
              << message << '\n';
}
 
template <typename T> void fun(T x)
{
    log(x);
}
 
int main(int, char*[])
{
    log("Hello world!");
    fun("Hello C++20!");
}

Output:

file: main.cpp(23:8) `int main(int, char**)`: Hello world!
file: main.cpp(18:8) `void fun(T) [with T = const char*]`: Hello C++20!