Skip to content

Commit 5201ac9

Browse files
ci: add memory history plot to readme
Save history of ram and flash usage and link to readme. Signed-off-by: Giacomo Dematteis <giacomo.dematteis@nordicsemi.no>
1 parent 6c2fb4d commit 5201ac9

4 files changed

Lines changed: 151 additions & 23 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
[![Power Consumption Badge](https://img.shields.io/endpoint?url=https://nrfconnect.github.io/Asset-Tracker-Template/power_badge.json)](https://nrfconnect.github.io/Asset-Tracker-Template/power_measurements_plot.html)
99

1010

11-
[![RAM Usage thingy91x](https://img.shields.io/endpoint?url=https://nrfconnect.github.io/Asset-Tracker-Template/ram_badge.json)](https://github.com/nrfconnect/Asset-Tracker-Template/actions/workflows/build-and-target-test.yml)
12-
[![Flash Usage thingy91x](https://img.shields.io/endpoint?url=https://nrfconnect.github.io/Asset-Tracker-Template/flash_badge.json)](https://github.com/nrfconnect/Asset-Tracker-Template/actions/workflows/build-and-target-test.yml)
11+
[![RAM Usage thingy91x](https://img.shields.io/endpoint?url=https://nrfconnect.github.io/Asset-Tracker-Template/ram_badge.json)](https://nrfconnect.github.io/Asset-Tracker-Template/ram_history_plot.html)
12+
[![Flash Usage thingy91x](https://img.shields.io/endpoint?url=https://nrfconnect.github.io/Asset-Tracker-Template/flash_badge.json)](https://nrfconnect.github.io/Asset-Tracker-Template/flash_history_plot.html)
1313

1414
## Overview
1515

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env python3
2+
3+
import pandas as pd
4+
import plotly.express as px
5+
from datetime import datetime
6+
import os
7+
import sys
8+
9+
def append_to_memory_csv(filename, used, total, current_date, output_dir):
10+
"""Append memory data to a CSV file."""
11+
data = {'Date': current_date, 'Used (B)': used, 'Total (B)': total, 'Usage (%)': (used/total)*100}
12+
df = pd.DataFrame([data])
13+
14+
csv_path = os.path.join(output_dir, filename)
15+
16+
if os.path.exists(csv_path):
17+
print(f"CSV exists at {csv_path}, appending data")
18+
# Read existing data
19+
existing_df = pd.read_csv(csv_path)
20+
print(f"Existing data:\n{existing_df}")
21+
22+
# Combine existing and new data
23+
combined_df = pd.concat([existing_df, df], ignore_index=True)
24+
print(f"Combined data:\n{combined_df}")
25+
26+
# Write back the complete dataset
27+
combined_df.to_csv(csv_path, index=False)
28+
else:
29+
print(f"Creating new CSV at {csv_path}")
30+
df.to_csv(csv_path, index=False)
31+
32+
def append_to_csv(ram_used, ram_total, flash_used, flash_total, output_dir):
33+
"""Append memory usage data to CSV files with timestamps."""
34+
current_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
35+
36+
# Ensure output directory exists
37+
os.makedirs(output_dir, exist_ok=True)
38+
39+
# Append to RAM and Flash CSVs
40+
append_to_memory_csv("ram_history.csv", ram_used, ram_total, current_date, output_dir)
41+
append_to_memory_csv("flash_history.csv", flash_used, flash_total, current_date, output_dir)
42+
43+
def generate_memory_plots(output_dir):
44+
"""Generate HTML plots from the CSV data."""
45+
# Ensure output directory exists
46+
os.makedirs(output_dir, exist_ok=True)
47+
48+
# RAM Plot
49+
ram_csv = os.path.join(output_dir, "ram_history.csv")
50+
if os.path.exists(ram_csv):
51+
df_ram = pd.read_csv(ram_csv)
52+
df_ram['Date'] = pd.to_datetime(df_ram['Date'])
53+
54+
# Calculate y-axis range for RAM
55+
y_min_ram = 0 # Start from 0
56+
y_max_ram = df_ram['Total (B)'].max() * 1.1 # 10% margin above max total
57+
58+
fig_ram = px.scatter(df_ram, x='Date', y=['Used (B)', 'Total (B)'],
59+
title='RAM Usage History - Asset Tracker Template',
60+
labels={'value': 'Bytes', 'variable': 'Metric'})
61+
# Add markers
62+
fig_ram.update_traces(mode='markers', marker=dict(size=10))
63+
# Set y-axis range
64+
fig_ram.update_layout(yaxis=dict(range=[y_min_ram, y_max_ram]))
65+
fig_ram.write_html(os.path.join(output_dir, "ram_history_plot.html"))
66+
67+
# Flash Plot
68+
flash_csv = os.path.join(output_dir, "flash_history.csv")
69+
if os.path.exists(flash_csv):
70+
df_flash = pd.read_csv(flash_csv)
71+
df_flash['Date'] = pd.to_datetime(df_flash['Date'])
72+
73+
# Calculate y-axis range for Flash
74+
y_min_flash = 0 # Start from 0
75+
y_max_flash = df_flash['Total (B)'].max() * 1.1 # 10% margin above max total
76+
77+
fig_flash = px.scatter(df_flash, x='Date', y=['Used (B)', 'Total (B)'],
78+
title='Flash Usage History - Asset Tracker Template',
79+
labels={'value': 'Bytes', 'variable': 'Metric'})
80+
# Add markers
81+
fig_flash.update_traces(mode='markers', marker=dict(size=10))
82+
# Set y-axis range
83+
fig_flash.update_layout(yaxis=dict(range=[y_min_flash, y_max_flash]))
84+
fig_flash.write_html(os.path.join(output_dir, "flash_history_plot.html"))
85+
86+
if __name__ == "__main__":
87+
if len(sys.argv) != 2:
88+
print(f"Usage: {sys.argv[0]} <output_directory>")
89+
sys.exit(1)
90+
output_dir = sys.argv[1]
91+
generate_memory_plots(output_dir)

tests/on_target/scripts/parse_memory_stats.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import json
66
import os
7+
from memory_plot_generator import append_to_csv, generate_memory_plots
78

89
def format_size(size_in_bytes):
910
"""Format size in bytes to a human-readable string with appropriate unit."""
@@ -26,7 +27,7 @@ def create_badge_json(label, used, total, percent, output_file):
2627
with open(output_file, 'w') as f:
2728
json.dump(badge_data, f, indent=4)
2829

29-
def parse_memory_stats(log_file):
30+
def parse_memory_stats(log_file, output_dir=None):
3031
with open(log_file, 'r') as f:
3132
content = f.read()
3233

@@ -51,23 +52,30 @@ def parse_memory_stats(log_file):
5152
ram_percent = float(match.group(6))
5253

5354
# Create badge JSON files
54-
badge_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
55-
ram_badge_file = os.path.join(badge_dir, "ram_badge.json")
56-
flash_badge_file = os.path.join(badge_dir, "flash_badge.json")
55+
if output_dir is None:
56+
output_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
57+
ram_badge_file = os.path.join(output_dir, "ram_badge.json")
58+
flash_badge_file = os.path.join(output_dir, "flash_badge.json")
5759

5860
create_badge_json("RAM Usage thingy91x", ram_used, ram_total, ram_percent, ram_badge_file)
5961
create_badge_json("Flash Usage thingy91x", flash_used, flash_total, flash_percent, flash_badge_file)
6062

6163
print("Memory Usage Statistics:")
6264
print(f"FLASH: {flash_used:,} B / {flash_total:,} B ({flash_percent:.2f}%)")
6365
print(f"RAM: {ram_used:,} B / {ram_total:,} B ({ram_percent:.2f}%)")
66+
# Append data to CSV files and generate plots
67+
append_to_csv(ram_used, ram_total, flash_used, flash_total, output_dir)
68+
generate_memory_plots(output_dir)
69+
6470
print(f"\nBadge files created:")
6571
print(f"RAM Badge: {ram_badge_file}")
6672
print(f"Flash Badge: {flash_badge_file}")
73+
print(f"Memory history plots generated")
6774

6875
if __name__ == "__main__":
69-
if len(sys.argv) != 2:
70-
print(f"Usage: {sys.argv[0]} <build_output_log>")
76+
if len(sys.argv) not in [2, 3]:
77+
print(f"Usage: {sys.argv[0]} <build_output_log> [output_directory]")
7178
sys.exit(1)
7279

73-
parse_memory_stats(sys.argv[1])
80+
output_dir = sys.argv[2] if len(sys.argv) == 3 else None
81+
parse_memory_stats(sys.argv[1], output_dir)

tests/on_target/scripts/update_memory_badges.sh

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
# Define paths
44
BUILD_LOG=$1
55

6-
# Define paths to files to be committed
7-
FLASH_BADGE_FILE=tests/on_target/flash_badge.json
8-
RAM_BADGE_FILE=tests/on_target/ram_badge.json
9-
106
FLASH_BADGE_FILE_DEST=docs/flash_badge.json
117
RAM_BADGE_FILE_DEST=docs/ram_badge.json
8+
FLASH_HISTORY_CSV_DEST=docs/flash_history.csv
9+
RAM_HISTORY_CSV_DEST=docs/ram_history.csv
10+
FLASH_PLOT_HTML_DEST=docs/flash_history_plot.html
11+
RAM_PLOT_HTML_DEST=docs/ram_history_plot.html
1212

1313
if [ -z "$BUILD_LOG" ]; then
1414
echo "Error: Build log file path not provided"
@@ -21,24 +21,53 @@ handle_error() {
2121
exit 0
2222
}
2323

24-
# Generate badge files using Python script
25-
echo "Generating badge files..."
26-
./tests/on_target/scripts/parse_memory_stats.py "$BUILD_LOG" || handle_error "Failed to generate badge files"
27-
28-
2924
# Configure Git
3025
git config --global --add safe.directory "$(pwd)"
3126
git config --global user.email "github-actions@github.com"
3227
git config --global user.name "GitHub Actions"
3328

34-
# Ensure the gh-pages branch exists and switch to it
29+
# Create a temporary directory for gh-pages content
30+
TEMP_DIR=$(mktemp -d)
31+
32+
# Fetch existing CSV files from gh-pages branch
3533
git fetch origin gh-pages
34+
35+
echo "Fetching existing CSV files..."
36+
if git show origin/gh-pages:docs/ram_history.csv > "$TEMP_DIR/ram_history.csv" 2>/dev/null; then
37+
echo "Found existing RAM history:"
38+
cat "$TEMP_DIR/ram_history.csv"
39+
else
40+
echo "No existing RAM history, creating new file"
41+
touch "$TEMP_DIR/ram_history.csv"
42+
fi
43+
44+
if git show origin/gh-pages:docs/flash_history.csv > "$TEMP_DIR/flash_history.csv" 2>/dev/null; then
45+
echo "Found existing Flash history:"
46+
cat "$TEMP_DIR/flash_history.csv"
47+
else
48+
echo "No existing Flash history, creating new file"
49+
touch "$TEMP_DIR/flash_history.csv"
50+
fi
51+
52+
# Generate badge files and append to existing CSV files
53+
echo "Parsing build log and generating badge files, updating csv history files and html plots..."
54+
./tests/on_target/scripts/parse_memory_stats.py "$BUILD_LOG" "$TEMP_DIR" || handle_error "Failed to update badge, csv and html files"
55+
56+
# Switch to gh-pages branch and update files
3657
git checkout gh-pages || handle_error "Not able to checkout gh-pages"
3758
git pull origin gh-pages || handle_error "Failed to pull latest gh-pages"
3859

39-
# Stage, commit, and push changes to the branch
40-
cp $FLASH_BADGE_FILE $FLASH_BADGE_FILE_DEST
41-
cp $RAM_BADGE_FILE $RAM_BADGE_FILE_DEST
42-
git add $FLASH_BADGE_FILE_DEST $RAM_BADGE_FILE_DEST
60+
# Copy all files to docs/
61+
mkdir -p docs
62+
cp "$TEMP_DIR"/*.json docs/
63+
cp "$TEMP_DIR"/*.csv docs/
64+
cp "$TEMP_DIR"/*.html docs/
65+
66+
git add $FLASH_BADGE_FILE_DEST $RAM_BADGE_FILE_DEST \
67+
$FLASH_HISTORY_CSV_DEST $RAM_HISTORY_CSV_DEST \
68+
$FLASH_PLOT_HTML_DEST $RAM_PLOT_HTML_DEST
4369
git commit -m "Update memory usage badges"
4470
git push origin gh-pages
71+
72+
# Clean up
73+
rm -rf "$TEMP_DIR"

0 commit comments

Comments
 (0)