Skip to content

Commit a652621

Browse files
committed
feat: Implement logging system for more detailed logs
- Add Logger class with file-based logging and configurable log levels - Replace all stdout/stderr with structured logging (DEBUG/INFO/WARN/ERROR) - Add command line options for log file (-l) and debug mode (-d) This will give us more insight into what the service is doing and how the connections to both pcap and the WhatPulse app is fairing.
1 parent a13a187 commit a652621

File tree

8 files changed

+432
-209
lines changed

8 files changed

+432
-209
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ CC=g++
22
CFLAGS=-std=c++17 -Wall -Wextra -O2 -pthread
33
LDFLAGS=-lpcap -pthread
44
TARGET=whatpulse-pcap-service
5-
SOURCES=main.cpp pcapservice.cpp tcpclient.cpp pcapcapturethread.cpp
6-
VERSION=1.0.0
5+
SOURCES=main.cpp pcapservice.cpp tcpclient.cpp pcapcapturethread.cpp logger.cpp
6+
VERSION=1.0.2
77

88
# Default target
99
all: $(TARGET)

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ When WhatPulse runs as an AppImage or in other restricted environments, it may n
1414

1515
### Package Manager Installation (Recommended)
1616

17-
Download the latest packages from the [GitHub Releases page](https://github.com/whatpulse/external-pcap-service/releases/latest).
17+
Download the latest packages from the [GitHub Releases page](https://github.com/whatpulse/linux-external-pcap-service).
1818

1919
Choose the package format for your Linux distribution:
2020

@@ -45,11 +45,11 @@ For automated downloads, use these commands to get the latest release:
4545

4646
```bash
4747
# Get latest release info
48-
LATEST_URL=$(curl -s https://api.github.com/repos/whatpulse/external-pcap-service/releases/latest | grep "browser_download_url" | grep "deb" | cut -d '"' -f 4)
48+
LATEST_URL=$(curl -s https://api.github.com/repos/whatpulse/linux-external-pcap-service/releases/latest | grep "browser_download_url" | grep "deb" | cut -d '"' -f 4)
4949
wget "$LATEST_URL"
5050

5151
# Or browse all releases:
52-
# https://github.com/whatpulse/external-pcap-service/releases
52+
# https://github.com/whatpulse/linux-external-pcap-service/releases
5353
```
5454

5555
### Build from Source
@@ -58,7 +58,7 @@ If packages aren't available for your distribution, or you prefer to build from
5858

5959
```bash
6060
# Download and extract source from GitHub releases
61-
# Visit: https://github.com/whatpulse/external-pcap-service/releases
61+
# Visit: https://github.com/whatpulse/linux-external-pcap-service/releases
6262
# Download: whatpulse-pcap-service-VERSION-source.tar.gz
6363

6464
tar xzf whatpulse-pcap-service-*-source.tar.gz

logger.cpp

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* WhatPulse External PCap Service - Logger Implementation
3+
*
4+
* Copyright (c) 2025 WhatPulse. All rights reserved.
5+
*
6+
* Licensed under CC BY-NC 4.0 with additional terms.
7+
* See LICENSE file for complete terms and conditions.
8+
*
9+
* NOTICE: This software integrates with WhatPulse services. Reverse engineering
10+
* the communication protocol or tampering with data transmission is prohibited.
11+
*
12+
* For licensing questions: [email protected]
13+
*/
14+
15+
#include "logger.h"
16+
#include <iostream>
17+
#include <iomanip>
18+
#include <ctime>
19+
20+
Logger &Logger::getInstance()
21+
{
22+
static Logger instance;
23+
return instance;
24+
}
25+
26+
void Logger::initialize(const std::string &logFile, LogLevel level, bool verbose)
27+
{
28+
m_level = level;
29+
m_verbose = verbose;
30+
31+
// Set performance logging intervals based on verbose mode
32+
if (verbose)
33+
{
34+
m_performanceInterval = m_verbosePerformanceInterval;
35+
}
36+
37+
if (!logFile.empty())
38+
{
39+
m_logFile.close();
40+
m_logFile.open(logFile, std::ios::app);
41+
if (!m_logFile.is_open())
42+
{
43+
std::cerr << "Failed to open log file: " << logFile << std::endl;
44+
return;
45+
}
46+
}
47+
48+
// Initial log entry
49+
std::stringstream ss;
50+
ss << "Logger initialized - Level: " << levelToString(level)
51+
<< ", Verbose: " << (verbose ? "Yes" : "No")
52+
<< ", Performance reports every: " << m_performanceInterval.count() << " seconds";
53+
log(LogLevel::INFO, ss.str());
54+
}
55+
56+
void Logger::log(LogLevel level, const std::string &message)
57+
{
58+
if (level < m_level)
59+
{
60+
return;
61+
}
62+
63+
std::string logEntry = getCurrentTimestamp() + " [" + levelToString(level) + "] " + message;
64+
65+
bool isOpen = m_logFile.is_open();
66+
if (isOpen)
67+
{
68+
m_logFile << logEntry << std::endl;
69+
m_logFile.flush();
70+
}
71+
if(!isOpen || m_verbose)
72+
{
73+
// Fallback to console if file logging fails
74+
if (level >= LogLevel::ERROR)
75+
{
76+
std::cerr << logEntry << std::endl;
77+
}
78+
else
79+
{
80+
std::cout << logEntry << std::endl;
81+
}
82+
}
83+
}
84+
85+
void Logger::logPerformance(const std::string &interfaceName, uint64_t packetCount, uint64_t totalBytes,
86+
double seconds, size_t queueSize, bool isConnected)
87+
{
88+
if (!shouldLogPerformance())
89+
{
90+
return;
91+
}
92+
93+
double mbps = (totalBytes * 8.0) / (seconds * 1024 * 1024);
94+
double pps = packetCount / seconds;
95+
96+
std::stringstream ss;
97+
ss << "PERF [" << interfaceName << "] "
98+
<< "Packets: " << packetCount << " (" << std::fixed << std::setprecision(1) << pps << " pps), "
99+
<< "Rate: " << std::setprecision(2) << mbps << " Mbps, "
100+
<< "Queue: " << queueSize << " packets, "
101+
<< "TCP: " << (isConnected ? "Connected" : "Disconnected");
102+
103+
log(LogLevel::INFO, ss.str());
104+
}
105+
106+
void Logger::logConnectionAttempt(const std::string &host, uint16_t port)
107+
{
108+
std::stringstream ss;
109+
ss << "TCP: Attempting to connect to " << host << ":" << port;
110+
log(LogLevel::INFO, ss.str());
111+
}
112+
113+
void Logger::logConnectionSuccess(const std::string &host, uint16_t port)
114+
{
115+
std::stringstream ss;
116+
ss << "TCP: Successfully connected to " << host << ":" << port;
117+
log(LogLevel::INFO, ss.str());
118+
}
119+
120+
void Logger::logConnectionFailed(const std::string &host, uint16_t port, const std::string &error)
121+
{
122+
std::stringstream ss;
123+
ss << "TCP: Failed to connect to " << host << ":" << port << " - " << error;
124+
log(LogLevel::WARNING, ss.str());
125+
}
126+
127+
void Logger::logDisconnected(const std::string &host, uint16_t port)
128+
{
129+
std::stringstream ss;
130+
ss << "TCP: Disconnected from " << host << ":" << port;
131+
log(LogLevel::INFO, ss.str());
132+
}
133+
134+
void Logger::logSendError(const std::string &error)
135+
{
136+
std::stringstream ss;
137+
ss << "TCP: Send failed - " << error;
138+
log(LogLevel::WARNING, ss.str());
139+
}
140+
141+
std::string Logger::getCurrentTimestamp()
142+
{
143+
auto now = std::chrono::system_clock::now();
144+
auto time_t = std::chrono::system_clock::to_time_t(now);
145+
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
146+
now.time_since_epoch()) %
147+
1000;
148+
149+
std::stringstream ss;
150+
ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
151+
ss << "." << std::setfill('0') << std::setw(3) << milliseconds.count();
152+
153+
return ss.str();
154+
}
155+
156+
std::string Logger::levelToString(LogLevel level)
157+
{
158+
switch (level)
159+
{
160+
case LogLevel::DEBUG:
161+
return "DEBUG";
162+
case LogLevel::INFO:
163+
return "INFO";
164+
case LogLevel::WARNING:
165+
return "WARN";
166+
case LogLevel::ERROR:
167+
return "ERROR";
168+
default:
169+
return "UNKNOWN";
170+
}
171+
}
172+
173+
bool Logger::shouldLogPerformance()
174+
{
175+
auto now = std::chrono::steady_clock::now();
176+
if (now - m_lastPerformanceLog >= m_performanceInterval)
177+
{
178+
m_lastPerformanceLog = now;
179+
return true;
180+
}
181+
return false;
182+
}

logger.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* WhatPulse External PCap Service - Logger Header
3+
*
4+
* Copyright (c) 2025 WhatPulse. All rights reserved.
5+
*
6+
* Licensed under CC BY-NC 4.0 with additional terms.
7+
* See LICENSE file for complete terms and conditions.
8+
*
9+
* NOTICE: This software integrates with WhatPulse services. Reverse engineering
10+
* the communication protocol or tampering with data transmission is prohibited.
11+
*
12+
* For licensing questions: [email protected]
13+
*/
14+
15+
#pragma once
16+
17+
#include <string>
18+
#include <fstream>
19+
#include <mutex>
20+
#include <sstream>
21+
#include <chrono>
22+
#include <iomanip>
23+
24+
enum class LogLevel
25+
{
26+
DEBUG = 0,
27+
INFO = 1,
28+
WARNING = 2,
29+
ERROR = 3
30+
};
31+
32+
class Logger
33+
{
34+
public:
35+
static Logger &getInstance();
36+
37+
void initialize(const std::string &logFile, LogLevel level = LogLevel::INFO, bool verbose = false);
38+
void setLevel(LogLevel level) { m_level = level; }
39+
void setVerbose(bool verbose) { m_verbose = verbose; }
40+
41+
void log(LogLevel level, const std::string &message);
42+
void debug(const std::string &message) { log(LogLevel::DEBUG, message); }
43+
void info(const std::string &message) { log(LogLevel::INFO, message); }
44+
void warning(const std::string &message) { log(LogLevel::WARNING, message); }
45+
void error(const std::string &message) { log(LogLevel::ERROR, message); }
46+
47+
// Performance logging with throttling
48+
void logPerformance(const std::string &interfaceName, uint64_t packetCount, uint64_t totalBytes,
49+
double seconds, size_t queueSize, bool isConnected);
50+
51+
// Connection state logging
52+
void logConnectionAttempt(const std::string &host, uint16_t port);
53+
void logConnectionSuccess(const std::string &host, uint16_t port);
54+
void logConnectionFailed(const std::string &host, uint16_t port, const std::string &error);
55+
void logDisconnected(const std::string &host, uint16_t port);
56+
void logSendError(const std::string &error);
57+
58+
private:
59+
Logger() = default;
60+
std::string getCurrentTimestamp();
61+
std::string levelToString(LogLevel level);
62+
bool shouldLogPerformance();
63+
64+
std::ofstream m_logFile;
65+
std::mutex m_mutex;
66+
LogLevel m_level = LogLevel::INFO;
67+
bool m_verbose = false;
68+
69+
// Performance logging throttling
70+
std::chrono::steady_clock::time_point m_lastPerformanceLog;
71+
std::chrono::seconds m_performanceInterval{300}; // 5 minutes default
72+
std::chrono::seconds m_verbosePerformanceInterval{10}; // 10 seconds in verbose mode
73+
};
74+
75+
// Convenience macros
76+
#define LOG_DEBUG(msg) Logger::getInstance().debug(msg)
77+
#define LOG_INFO(msg) Logger::getInstance().info(msg)
78+
#define LOG_WARNING(msg) Logger::getInstance().warning(msg)
79+
#define LOG_ERROR(msg) Logger::getInstance().error(msg)

0 commit comments

Comments
 (0)