mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-01-29 00:51:29 -05:00
DOCS+FE+BE: cleaner versioning retrieval, ICMP, plugin debug docs
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Troubleshooting plugins
|
||||
|
||||
> [!TIP]
|
||||
> Before troubleshooting, please ensure you have the right [Debugging and LOG_LEVEL set](./DEBUG_TIPS.md).
|
||||
> Before troubleshooting, please ensure you have the right [Debugging and LOG_LEVEL set](./DEBUG_TIPS.md) in Settings.
|
||||
|
||||
## High-level overview
|
||||
|
||||
@@ -22,10 +22,25 @@ For a more in-depth overview on how plugins work check the [Plugins development
|
||||
|
||||
#### Incorrect input data
|
||||
|
||||
Input data from the plugin might cause mapping issues in specific edge cases. Look for a corresponding section in the `app.log` file, for example notice the first line of the execution run of the `PIHOLE` plugin below:
|
||||
Input data from the plugin might cause mapping issues in specific edge cases. Look for a corresponding section in the `app.log` file, and search for `[Scheduler] run for PLUGINNAME: YES`, so for ICMP you would look for `[Scheduler] run for ICMP: YES`. You can find examples of useful logs below. If your issue is related to a plugin, and you don't include a log section with this data, we can't help you to resolve your issue.
|
||||
|
||||
##### ICMP log example
|
||||
|
||||
```
|
||||
17:31:05 [Scheduler] - Scheduler run for PIHOLE: YES
|
||||
20:39:04 [Scheduler] run for ICMP: YES
|
||||
20:39:04 [ICMP] fping skipping 192.168.1.124 : [2], timed out (NaN avg, 100% loss)
|
||||
20:39:04 [ICMP] adding 192.168.1.123 from 192.168.1.123 : [2], 64 bytes, 20.1 ms (8.22 avg, 0% loss)
|
||||
20:39:04 [ICMP] fping skipping 192.168.1.157 : [1], timed out (NaN avg, 100% loss)
|
||||
20:39:04 [ICMP] adding 192.168.1.79 from 192.168.1.79 : [2], 64 bytes, 48.3 ms (60.9 avg, 0% loss)
|
||||
20:39:04 [ICMP] fping skipping 192.168.1.128 : [2], timed out (NaN avg, 100% loss)
|
||||
20:39:04 [ICMP] fping skipping 192.168.1.129 : [2], timed out (NaN avg, 100% loss)
|
||||
```
|
||||
|
||||
|
||||
##### PIHOLE log example
|
||||
|
||||
```
|
||||
17:31:05 [Scheduler] run for PIHOLE: YES
|
||||
17:31:05 [Plugin utils] ---------------------------------------------
|
||||
17:31:05 [Plugin utils] display_name: PiHole (Device sync)
|
||||
17:31:05 [Plugins] CMD: SELECT n.hwaddr AS Object_PrimaryID, {s-quote}null{s-quote} AS Object_SecondaryID, datetime() AS DateTime, na.ip AS Watched_Value1, n.lastQuery AS Watched_Value2, na.name AS Watched_Value3, n.macVendor AS Watched_Value4, {s-quote}null{s-quote} AS Extra, n.hwaddr AS ForeignKey FROM EXTERNAL_PIHOLE.Network AS n LEFT JOIN EXTERNAL_PIHOLE.Network_Addresses AS na ON na.network_id = n.id WHERE n.hwaddr NOT LIKE {s-quote}ip-%{s-quote} AND n.hwaddr is not {s-quote}00:00:00:00:00:00{s-quote} AND na.ip is not null
|
||||
@@ -60,7 +75,7 @@ Input data from the plugin might cause mapping issues in specific edge cases. Lo
|
||||
17:31:05 [API] Update API starting
|
||||
17:31:06 [API] Updating table_plugins_history.json file in /api
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The debug output between the 🔻red arrows🔺 is important for debugging (arrows added only to highlight the section on this page, they are not available in the actual debug log)
|
||||
|
||||
In the above output notice the section logging how many events are produced by the plugin:
|
||||
@@ -80,12 +95,11 @@ These values, if formatted correctly, will also show up in the UI:
|
||||
|
||||

|
||||
|
||||
|
||||
### Sharing application state
|
||||
|
||||
Sometimes specific log sections are needed to debug issues. The Devices and CurrentScan table data is sometimes needed to figure out what's wrong.
|
||||
|
||||
1. Please set `LOG_LEVEL` to `trace` (Disable it once you have the info as this produces big log files).
|
||||
1. Please set `LOG_LEVEL` to `trace` in the Settings (Disable it once you have the info as this produces big log files).
|
||||
2. Wait for the issue to occur.
|
||||
3. Search for `================ DEVICES table content ================` in your logs.
|
||||
4. Search for `================ CurrentScan table content ================` in your logs.
|
||||
|
||||
@@ -42,7 +42,9 @@ ARPSCAN_DURATION=30
|
||||
|
||||
### ✅ Add ICMP (Ping) Scanning
|
||||
|
||||
Enable the `ICMP` scan plugin to complement ARP detection. ICMP is often more reliable for detecting active hosts, especially when ARP fails.
|
||||
Enable the `ICMP` scan plugin to complement ARP detection. ICMP is often more reliable for detecting active hosts, especially when ARP fails.
|
||||
|
||||
> [!IMPORTANT] If using AdGuard/Pi-hole: If devices still show offline after enabling ICMP, temporarily disable your content blocker. If the issue disappears, whitelist the NetAlertX host IP in your blocker's settings to prevent pings from being dropped.
|
||||
|
||||
### ✅ Use Multiple Detection Methods
|
||||
|
||||
@@ -52,7 +54,7 @@ A combined approach greatly improves detection robustness:
|
||||
* `ICMP` (ping)
|
||||
* `NMAPDEV` (nmap)
|
||||
|
||||
This hybrid strategy increases reliability, especially for down detection and alerting. See [other plugins](./PLUGINS.md) that might be compatible with your setup. See benefits and drawbacks of individual scan methods in their respective docs.
|
||||
This hybrid strategy increases reliability, especially for down detection and alerting. See [other plugins](./PLUGINS.md) that might be compatible with your setup. See benefits and drawbacks of individual scan methods in their respective docs.
|
||||
|
||||
## Results
|
||||
|
||||
@@ -76,4 +78,4 @@ After increasing the ARP timeout and adding ICMP scanning (on select IP ranges),
|
||||
|
||||
Let us know in the [NetAlertX Discussions](https://github.com/jokob-sk/NetAlertX/discussions) if you have further feedback or edge cases.
|
||||
|
||||
See also [Remote Networks](./REMOTE_NETWORKS.md) for more advanced setups.
|
||||
See also [Remote Networks](./REMOTE_NETWORKS.md) for more advanced setups.
|
||||
@@ -57,7 +57,7 @@
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
<script src="lib/chart.js/Chart.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
||||
<script src="lib/chart.js/Chart.js"></script>
|
||||
<!-- presence chart -->
|
||||
<?php
|
||||
require 'php/components/graph_online_history.php';
|
||||
|
||||
@@ -128,14 +128,31 @@ class NetAlertXStateManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle state update from SSE
|
||||
* Handle state update from SSE or Polling
|
||||
*/
|
||||
handleStateUpdate(appState) {
|
||||
try {
|
||||
if (document.getElementById("state")) {
|
||||
const cleanState = appState["currentState"].replaceAll('"', "");
|
||||
document.getElementById("state").innerHTML = cleanState;
|
||||
// 1. Update the main status text
|
||||
if (appState["currentState"]) {
|
||||
const cleanState = appState["currentState"].replace(/"/g, "");
|
||||
$("#state").html(cleanState);
|
||||
}
|
||||
|
||||
// 2. Update Version placeholders
|
||||
const version = appState["appVersion"] || "UNKNOWN";
|
||||
$('[data-plc="version"]')
|
||||
.html(version)
|
||||
.attr('data-version', version);
|
||||
|
||||
// 3. Update Build Timestamp placeholders
|
||||
const buildTime = appState["buildTimestamp"] !== undefined ? appState["buildTimestamp"] : "";
|
||||
const displayTime = (buildTime === 0) ? "UNKNOWN" : buildTime;
|
||||
|
||||
$('[data-plc="build-timestamp"]')
|
||||
.html(displayTime)
|
||||
.attr('data-build-time', buildTime);
|
||||
|
||||
console.log("[NetAlertX State] UI updated via jQuery");
|
||||
} catch (e) {
|
||||
console.error("[NetAlertX State] Failed to update state display:", e);
|
||||
}
|
||||
|
||||
@@ -66,21 +66,24 @@ $db->close();
|
||||
<a href="https://docs.netalertx.com/VERSIONS" target="_blank"> <span><i class="fa fa-circle-question"></i></a></span>
|
||||
</div>
|
||||
<div class="db_info_table_cell">
|
||||
<div class="version" id="version" data-build-time="<?php echo file_get_contents( "buildtimestamp.txt");?>">
|
||||
<?php echo '<span id="new-version-text" class="myhidden"><i class="fa-solid fa-rocket fa-beat"></i> ' .lang('Maintenance_new_version').'</span>'.'<span id="current-version-text" class="myhidden">' .lang('Maintenance_current_version').'</span>';?>
|
||||
<div class="version" id="version" data-build-time="">
|
||||
<span id="new-version-text" class="myhidden"><i class="fa-solid fa-rocket fa-beat"></i>
|
||||
<?php echo lang('Maintenance_new_version');?> </span> <span id="current-version-text" class="myhidden">
|
||||
<?php echo lang('Maintenance_current_version') ;?> </span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_info_table_cell" style="min-width: 140px"><?= lang('Maintenance_built_on');?></div>
|
||||
<div class="db_info_table_cell">
|
||||
<?php echo date("Y-m-d", ((int)file_get_contents( "buildtimestamp.txt")));?>
|
||||
<span data-plc="build-timestamp"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_info_table_cell" style="min-width: 140px"><?= lang('Maintenance_Running_Version');?></div>
|
||||
<div class="db_info_table_cell">
|
||||
<?php include 'php/templates/version.php'; ?>
|
||||
<span data-plc="version"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
#---------------------------------------------------------------------------------#
|
||||
# NetAlertX #
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector #
|
||||
# #
|
||||
# build.php - Templates module Template to display the current build version #
|
||||
#---------------------------------------------------------------------------------#
|
||||
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3 #
|
||||
# jokob-sk 2022 jokob.sk@gmail.com GNU GPLv3 #
|
||||
# leiweibau 2022 https://github.com/leiweibau GNU GPLv3 #
|
||||
# cvc90 2023 https://github.com/cvc90 GNU GPLv3 #
|
||||
#---------------------------------------------------------------------------------#
|
||||
|
||||
$file = "/app/front/buildtimestamp.txt";
|
||||
if (file_exists($file)) {
|
||||
echo date("Y-m-d", ((int)file_get_contents($file)));
|
||||
}
|
||||
else {
|
||||
echo "File not found";
|
||||
}
|
||||
?>
|
||||
@@ -32,8 +32,8 @@
|
||||
| <a href="https://docs.netalertx.com/" class="pointer" target="_blank" title="Documentation"><i class="fa fa-book"></i></a>
|
||||
| <a href="https://github.com/jokob-sk/NetAlertX/issues" class="pointer" target="_blank"><i class="fa fa-bug" title="Report a bug"></i></a>
|
||||
| <a href="https://discord.com/invite/NczTUTWyRr" class="pointer" target="_blank"><i class="fa-brands fa-discord" title="Join Discord"></i></a>
|
||||
| <?= lang('Maintenance_built_on');?>: <?php include 'php/templates/build.php'; ?>
|
||||
| Version: <?php include 'php/templates/version.php'; ?>
|
||||
| <?= lang('Maintenance_built_on');?>: <span data-plc="build-timestamp"></span>
|
||||
| Version: <span data-plc="version"></span>
|
||||
|
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -13,7 +13,7 @@ INSTALL_PATH = os.getenv("NETALERTX_APP", "/app")
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from logger import mylog # noqa: E402 [flake8 lint suppression]
|
||||
from helper import get_setting_value, get_env_setting_value # noqa: E402 [flake8 lint suppression]
|
||||
from helper import get_setting_value, get_env_setting_value, getBuildTimeStampAndVersion # noqa: E402 [flake8 lint suppression]
|
||||
from db.db_helper import get_date_from_period # noqa: E402 [flake8 lint suppression]
|
||||
from app_state import updateState # noqa: E402 [flake8 lint suppression]
|
||||
|
||||
@@ -1809,6 +1809,9 @@ def start_server(graphql_port, app_state):
|
||||
)
|
||||
thread.start()
|
||||
|
||||
# Pass Application "VERSION" into the app_state
|
||||
buildTimestamp, newBuildVersion = getBuildTimeStampAndVersion()
|
||||
|
||||
# Update the state to indicate the server has started
|
||||
app_state = updateState("Process: Idle", None, None, None, 1)
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ class app_state_class:
|
||||
graphQLServerStarted=0,
|
||||
processScan=False,
|
||||
pluginsStates=None,
|
||||
appVersion=None
|
||||
appVersion=None,
|
||||
buildTimestamp=None
|
||||
):
|
||||
"""
|
||||
Initialize the application state, optionally overwriting previous values.
|
||||
@@ -59,6 +60,7 @@ class app_state_class:
|
||||
processScan (bool, optional): Initial processScan flag.
|
||||
pluginsStates (dict, optional): Initial plugin states to merge with previous state.
|
||||
appVersion (str, optional): Application version.
|
||||
buildTimestamp (str, optional): ABuild timestamp.
|
||||
"""
|
||||
# json file containing the state to communicate with the frontend
|
||||
stateFile = apiPath + "app_state.json"
|
||||
@@ -86,6 +88,7 @@ class app_state_class:
|
||||
self.currentState = previousState.get("currentState", "Init")
|
||||
self.pluginsStates = previousState.get("pluginsStates", {})
|
||||
self.appVersion = previousState.get("appVersion", "")
|
||||
self.buildTimestamp = previousState.get("buildTimestamp", "")
|
||||
else: # init first time values
|
||||
self.settingsSaved = 0
|
||||
self.settingsImported = 0
|
||||
@@ -97,6 +100,7 @@ class app_state_class:
|
||||
self.currentState = "Init"
|
||||
self.pluginsStates = {}
|
||||
self.appVersion = ""
|
||||
self.buildTimestamp = ""
|
||||
|
||||
# Overwrite with provided parameters if supplied
|
||||
if settingsSaved is not None:
|
||||
@@ -127,6 +131,8 @@ class app_state_class:
|
||||
self.pluginsStates[plugin] = state
|
||||
if appVersion is not None:
|
||||
self.appVersion = appVersion
|
||||
if buildTimestamp is not None:
|
||||
self.buildTimestamp = buildTimestamp
|
||||
# check for new version every hour and if currently not running new version
|
||||
if self.isNewVersion is False and self.isNewVersionChecked + 3600 < int(
|
||||
timeNow().timestamp()
|
||||
@@ -154,7 +160,13 @@ class app_state_class:
|
||||
|
||||
# Broadcast state change via SSE if available
|
||||
try:
|
||||
broadcast_state_update(self.currentState, self.settingsImported, timestamp=self.lastUpdated)
|
||||
broadcast_state_update(
|
||||
self.currentState,
|
||||
self.settingsImported,
|
||||
timestamp=self.lastUpdated,
|
||||
appVersion=self.appVersion,
|
||||
buildTimestamp=self.buildTimestamp
|
||||
)
|
||||
except Exception as e:
|
||||
mylog("none", [f"[app_state] SSE broadcast: {e}"])
|
||||
|
||||
@@ -170,7 +182,8 @@ def updateState(newState = None,
|
||||
graphQLServerStarted = None,
|
||||
processScan = None,
|
||||
pluginsStates=None,
|
||||
appVersion=None):
|
||||
appVersion=None,
|
||||
buildTimestamp=None):
|
||||
"""
|
||||
Convenience method to create or update the app state.
|
||||
|
||||
@@ -183,6 +196,7 @@ def updateState(newState = None,
|
||||
processScan (bool, optional): Flag indicating if a scan is active.
|
||||
pluginsStates (dict, optional): Plugin state updates.
|
||||
appVersion (str, optional): Application version.
|
||||
buildTimestamp (str, optional): Build timestamp.
|
||||
|
||||
Returns:
|
||||
app_state_class: Updated state object.
|
||||
@@ -195,7 +209,8 @@ def updateState(newState = None,
|
||||
graphQLServerStarted,
|
||||
processScan,
|
||||
pluginsStates,
|
||||
appVersion
|
||||
appVersion,
|
||||
buildTimestamp
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -715,7 +715,7 @@ def importConfigs(pm, db, all_plugins):
|
||||
# settingsImported = None (timestamp),
|
||||
# showSpinner = False (1/0),
|
||||
# graphQLServerStarted = 1 (1/0))
|
||||
updateState("Config imported", conf.lastImportedConfFile, conf.lastImportedConfFile, False, 1, None, None, new_version)
|
||||
updateState("Config imported", conf.lastImportedConfFile, conf.lastImportedConfFile, False, 1, None, None, new_version, buildTimestamp)
|
||||
|
||||
msg = '[Config] Imported new settings config'
|
||||
mylog('minimal', msg)
|
||||
|
||||
Reference in New Issue
Block a user