🛠️

C言語のログ(logging:ロギング)処理(8)

3 min read

通信データはバイナリでログ出力

通信ログは文字データだけではなく制御コードも含まれることがある。
分かり易いところでは、終端文字であるNULLは文字列データの終端コードになるので文字列出力のログではダメでバイナリ出力する必要がある。
通信データのログであれば出力したデータを利用してテストデータとして流してみたりすることもあるのでデータ長も出力する必要がある。
通信データはデータ長がまちまちなのでデータ長を int型 などで出力するとワード境界で間が空いてしますので、データ長は文字列変換して char型 で出力する。
構造体なども同じ理由でワード境界で間が空いてしまうので使わないことにする。
などを気にしてプログラミング。

プログラム

// main関数 putBinaryLog() を呼出すところ抜粋
int main(void) {

	unsigned char *data;
	data = (unsigned char *)malloc(5);
	*(data + 0) = 0x0;
	*(data + 1) = 0x1;
	*(data + 2) = 0x2;
	*(data + 3) = 0x3;
	*(data + 4) = 0x4;

	putBinaryLog(5, data);

	free(data);
	
	return EXIT_SUCCESS;
}
// バイナリログファイル出力関数 のみ抜粋
void putBinaryLog(int dataLen, unsigned char *data)
{
	int		ret;				// 戻り値
	char	dateTime[32];		// 現在日時
	struct stat	stStat;			// ファイル情報の格納領域
	char	fileName[2048];		// ログファイル名
	FILE	*fp;				// ファイルディスクプリタ
	off_t	fileSize;			// ファイルサイズ
	int		renewFile;			// ファイル作成し直し要否

	char 	buff[5];			//

	// 現在日時文字列取得(YYYY-MM-DD HH:MM:SS.ssssss)
	memset(dateTime, 0x0, sizeof(dateTime));
	ret = getDateTime(LOG_DATETIME_FORMAT, sizeof(dateTime), dateTime);
	if(ret != 0){
		// エラーの場合ログ出力なし
		return;
	}

	ret = pthread_mutex_lock(&mutexBinaryLog);

	// ファイル名を取得
	memset(fileName, 0x0, sizeof(fileName));
	sprintf(fileName, "%s/%s.log", gIniValLog.logFilePathName, LOG_FILE_NAME);
	ret = stat(fileName, &stStat);
	if(ret != 0){
		// エラー
		// ファイルが存在しない場合、ファイルサイズに0を設定
		fileSize = 0;
	}
	else{
		// ファイルサイズ
		fileSize = stStat.st_size;
	}

	// ファイルサイズチェック
	renewFile = 0;
	if(fileSize >= gIniValLog.logFileSizeMax * LOG_FILE_SIZE_KB){
		renewFile = 1;
		//gLogCurNo++;
		//if(gLogCurNo > gIniValLog.logFileNumMax){
		//	gLogCurNo = 1;
		//}
		cangeGen();
	}

	// ログファイル名取得(フルパス)
	fp = NULL;
	if(renewFile == 0){
		// 既存ファイルに追加書き込み(ファイルがなければ新規作成)
		fp = fopen(fileName, "ab");
	}
	else{
		// ファイルを新規作成し直す
		fp = fopen(fileName, "wb");
	}

	if(fp == NULL){
		// ファイルオープンエラー
		// ファイルパス/ファイル名が不正の場合
		// パーミッションエラーの場合
		// ログ出力しない
		;
	}
	else{
		// データサイズ文字列変換
		sprintf(buff, "%4d", dataLen);
		// 日時出力 YYYY-MM-DD HH:MM:SS.ssssss 形式(26バイト)で出力
		fwrite(dateTime, sizeof(unsigned char), 26, fp);
		// データサイズ出力 4バイトの数字文字列で出力
		fwrite(buff, sizeof(unsigned char), 4, fp);
		// データ出力
		fwrite(data, sizeof(unsigned char), dataLen, fp);

		// ファイルフラッシュ
		ret = fflush(fp);
		if(ret == -1){
			// ファイルフラッシュエラー
			;
		}

		// ファイルクローズ
		ret = fclose(fp);
		if(ret == -1){
			// ファイルクローズエラー
			;
		}
	}

	ret = pthread_mutex_unlock(&mutexBinaryLog);

	return;
}

出力結果

00:0000 32 30 32 31 2D 31 30 2D-30 32 20 31 30 3A 30 37  2021-10-02 10:07 
00:0010 3A 33 38 2E 35 37 35 35-36 34 20 20 20 35 00 01  :38.575564   5.. 
00:0020 02 03 04                                         ...              

Discussion

ログインするとコメントできます