Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;
}
like image 479
user2991556 Avatar asked Oct 17 '25 04:10

user2991556


2 Answers

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!
like image 170
JVE999 Avatar answered Oct 18 '25 20:10

JVE999


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).

like image 43
luk32 Avatar answered Oct 18 '25 21:10

luk32