0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

c++ builder > "my" ErrorLoggerUnit / Usage

Last updated at Posted at 2016-02-08

This article is for
http://stackoverflow.com/questions/35251103/how-to-capture-suddenly-destructed-tthread?noredirect=1#comment58234908_35251103

Environment

implemented_on
RadStudio XE4 using C++ on  Windows 7pro
working_on
Windows 7 Embedded (English)

header

ErrorLoggerUnit.h
//---------------------------------------------------------------------------

/*
2016 Feb. 08
Translated comments from my native languate to English
to share with StackExchange
*/


#ifndef ErrorLoggerUnitH
#define ErrorLoggerUnitH

#include <System.hpp> // for String
#include <System.Classes.hpp> // for TList

class TErrorLogger {
public:
	enum ErrorLevel_e {
		High = 0,	// Critical
		Middle,		// Such as retry
		Low,
		Debug,		// debug
		Info        // Not Error, but corresponding to mtInformation
	};

private:
	struct ErrorInfo_t {
		TDateTime datetime;
		ErrorLevel_e errorLevel;
		String summary;
		String detail;
		String funcPlace; // function name and index
	};

	int m_maxNumRecords; // Maximum record number
	TList *m_list; // Store ErrorInfo_t
	String m_filepath; // Save destination
	bool m_debugMode; // false: if(errorLevel==Debug) {will not Add()}

	String __fastcall getErrorLevelString(int errorLevel);
	String __fastcall getTitleString(); // items of getDataString
	String __fastcall getDataString(int idx); // return ErrorInfo_t strings

protected:
public:
	void __fastcall Add(int errorLevel_, String summary_, String details_, String funcPlace_);
	int __fastcall Save(); // return number of records / -1:error
	int __fastcall Save(String filename);
	void __fastcall Clear();

	// test functions
	static int __fastcall Test_run_through();

	__fastcall TErrorLogger(String filepath, int maxNum, bool debugMode);
	__fastcall ~TErrorLogger();	
};

#endif // ErrorLoggerUnitH

source (.cpp)

ErrorLoggerUnit.cpp
//---------------------------------------------------------------------------

#pragma hdrstop

#include <memory> // for unique_ptr
#include "ErrorLoggerUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

/*
v0.13 2016 Feb. 03
...
*/

//#define DEBUG_DO_PRINT // for debug print

static const String errorLevelStr[] = {	
	L"High", L"Middle", L"Low", L"Debug", L"Info"
};
int errLevelSize = sizeof(errorLevelStr) / sizeof(errorLevelStr[0]);

static void debug_outputDebugString(String prefix, String msg)
{
        // Used to comment out all debug print easily

#ifdef DEBUG_DO_PRINT
	String work = L"ErrorLoggerUnit >" + prefix + L": " + msg;
	OutputDebugString(work.c_str()); // @ debug_outputDebugString
#endif
}

__fastcall TErrorLogger::TErrorLogger(String filepath, int maxNum, bool debugMode)
{
	m_maxNumRecords = maxNum;
	m_filepath = filepath;
	m_list = new TList();
	m_debugMode = debugMode;
}

__fastcall TErrorLogger::~TErrorLogger()
{
	if (this == NULL) {
		return; // error
	}

	for(int idx=0; idx < m_list->Count; idx++) {
		delete m_list->Items[idx];
	}

	if (m_list != NULL) {
		delete m_list;
		m_list = NULL;
	}
}

void __fastcall TErrorLogger::Add(int errorLevel_, String summary_, String details_, String funcPlace_)
{
	if (this == NULL) {
		String msg = L"ERR > TErrorLogger variable not initialized";
		debug_outputDebugString(L"Add", msg.c_str());
		return; // error
	}
	if (m_debugMode == false && errorLevel_ == TErrorLogger::Debug) {
		return; // will not Add in debug
	}

	if (m_list == NULL) {
		m_list = new TList();
	}

	if (m_list->Count >= m_maxNumRecords) { // Ring Buffer
		m_list->Delete(0);
	}

	ErrorInfo_t *info = new ErrorInfo_t();

	info->datetime = Now();
	info->errorLevel = (ErrorLevel_e)errorLevel_;
	info->summary = summary_;
	info->detail = details_;
	info->funcPlace = funcPlace_;

	m_list->Add(info);
}

String __fastcall TErrorLogger::getTitleString()
{
	if (this == NULL) {
		return L""; // error
	}

	String res = 
	    L"yy/mm/dd,hh:nn:ss"
		L",level"
		L",summary"
		L",detail"
		L",function:index";
	return res;
}

String __fastcall TErrorLogger::getDataString(int idx)
{
	if (this == NULL) {
		return L""; // error
	}

	ErrorInfo_t *info = (ErrorInfo_t *)(m_list->Items[idx]);

	if (idx < 0 || idx >= m_list->Count) {
		return L""; // error
	}

	String str;
	str = info->datetime.FormatString(L"yy/mm/dd,hh:nn:ss");
	str = str + L"," + IntToStr(info->errorLevel) 
		+ getErrorLevelString(info->errorLevel);
	str = str + L"," + info->summary;
	str = str + L"," + info->detail;
	str = str + L"," + info->funcPlace;

	return str;
}

String __fastcall TErrorLogger::getErrorLevelString(int errorLevel)
{
	if (this == NULL) {
		return L""; // error
	}
	if (errorLevel < 0 || errorLevel >= errLevelSize) {
		return L"";
	}
	return L"(" + errorLevelStr[errorLevel] + L")";
}

int __fastcall TErrorLogger::Save() {
	if (this == NULL) {
        return -1;
	}
	return Save(m_filepath);
}

int __fastcall TErrorLogger::Save(String filename)
{
	if (this == NULL) {
		return -1; // error
	}
	if (filename.Length() == 0) {
		return -1; // error
	}

	std::unique_ptr<TStringList> line(new TStringList);
	String dataStr;

	String title = getTitleString();
	line->Add(title);
	debug_outputDebugString(L"Save", title.c_str());

	for(int idx=0; idx < m_list->Count; idx++) {
		dataStr = getDataString(idx);
		line->Add(dataStr);
	}

	try {
		line->SaveToFile(filename);
	} catch (...) {
	}

	return line->Count;
}

/* static */int __fastcall TErrorLogger::Test_run_through()
{
	TErrorLogger *testError = new TErrorLogger(L"log.txt", /* maxNum=*/ 1000, /*debugMode=*/true);

	for(int loop=0; loop<3; loop++) {
		testError->Add(TErrorLogger::High,   L"UDP:Summary1", L"Detail1", L"funcA:idx1");
		testError->Add(TErrorLogger::Middle, L"UDP:Summary2", L"Detail2", L"funcA:idx2");
		testError->Add(TErrorLogger::High,   L"PC:Summary1", L"Detail3", L"funcB:idx1");
		testError->Add(TErrorLogger::Low,    L"PC:Summary2", L"Detail4", L"funcAdd:idx2");
		testError->Add(TErrorLogger::High,   L"PC:Summary3", L"Detail5", L"funcRemove:idx3");
		testError->Add(TErrorLogger::Debug,   L"Debug:Hello world", L"Detail5", L"");
		testError->Add(TErrorLogger::Info,   L"Not problem but", L"This is not a problem", L"");
	}

	int numRecord;
	numRecord = testError->Save();
	String msg = L"Saved " + IntToStr(numRecord) + L" records";
	debug_outputDebugString(L"Test_run_through", msg.c_str() );

	testError->Clear();
	numRecord = testError->Save(L"log2.txt");
	msg = L"Saved " + IntToStr(numRecord) + L" records";
	debug_outputDebugString(L"Test_run_through", msg.c_str() );

	delete testError;

	return numRecord;
}

void __fastcall TErrorLogger::Clear()
{
	if (this == NULL) { // new TErrorLogger()してない
		return; // error
	}

	for(int idx=0; idx < m_list->Count; idx++) {
		delete m_list->Items[idx];
	}

	m_list->Clear();

}

Usage

See Test_run_through() for example usage.

instantiate

TErrorLogger *m_errLog;
...
m_errLog = new TErrorLogger(kErrorLogFolder + L"\\" + kErrorLogFileName, kErrorLog_maxNumRecords, /* debugMode=*/false);
...

logging

m_errLog->Add(TErrorLogger::Info,   L"ctor", L"instance created", L"");
m_errLog->Save();
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?