This guide covers setting up a development environment, building from source, and contributing to UltraLog.
Table of Contents
- Development Setup
- Building
- Project Structure
- Architecture Overview
- Adding New ECU Support
- Code Style
- Testing
- CI/CD
- Contributing
Development Setup
Prerequisites
- Rust - Latest stable version
- Git - For version control
- Platform build tools - See below
Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
# Verify installation
rustc --version
cargo --version
Platform-Specific Dependencies
Linux (Ubuntu/Debian):
sudo apt-get update
sudo apt-get install -y \
build-essential \
libxcb-render0-dev \
libxcb-shape0-dev \
libxcb-xfixes0-dev \
libxkbcommon-dev \
libssl-dev \
libgtk-3-dev \
libglib2.0-dev \
libatk1.0-dev \
libcairo2-dev \
libpango1.0-dev \
libgdk-pixbuf2.0-dev
Linux (Fedora):
sudo dnf install -y \
gcc \
libxcb-devel \
libxkbcommon-devel \
openssl-devel \
gtk3-devel \
glib2-devel \
atk-devel \
cairo-devel \
pango-devel \
gdk-pixbuf2-devel
macOS:
xcode-select --install
Windows:
- Install Visual Studio Build Tools
- Select "Desktop development with C++"
Clone the Repository
git clone https://github.com/SomethingNew71/UltraLog.git
cd UltraLog
Building
Development Build
Faster compile time, slower runtime, includes debug symbols:
cargo build
Release Build
Slower compile time, optimized runtime:
cargo build --release
Run the Application
# Debug mode
cargo run
# Release mode
cargo run --release
Run the Parser Test Utility
cargo run --bin test_parser -- path/to/logfile.csv
Project Structure
UltraLog/
├── src/
│ ├── main.rs # Application entry point
│ ├── lib.rs # Library module exports
│ ├── app.rs # Main UltraLogApp struct (934 lines)
│ │ # - Application state management
│ │ # - File loading pipeline
│ │ # - eframe::App implementation
│ ├── state.rs # Core data types (206 lines)
│ │ # - LoadedFile, SelectedChannel
│ │ # - Color palettes
│ │ # - Loading states
│ ├── units.rs # Unit conversion system (278 lines)
│ ├── normalize.rs # Field name normalization (500 lines)
│ ├── parsers/
│ │ ├── mod.rs # Parser module exports
│ │ ├── types.rs # Core parser traits & enums
│ │ │ # - Log, Channel, Value, Meta
│ │ │ # - Parseable trait
│ │ │ # - EcuType enumeration
│ │ ├── haltech.rs # Haltech CSV parser (547 lines)
│ │ ├── ecumaster.rs # ECUMaster CSV parser (366 lines)
│ │ └── speeduino.rs # Speeduino MLG parser (542 lines)
│ ├── ui/
│ │ ├── mod.rs # UI module exports
│ │ ├── sidebar.rs # File list & view options
│ │ ├── channels.rs # Channel selection panel
│ │ ├── chart.rs # Main chart & LTTB algorithm
│ │ ├── timeline.rs # Playback controls
│ │ ├── menu.rs # Menu bar & units UI
│ │ ├── tab_bar.rs # Chrome-style tabs
│ │ ├── toast.rs # Notification system
│ │ ├── icons.rs # Icon drawing utilities
│ │ ├── export.rs # PNG/PDF export
│ │ ├── normalization_editor.rs # Custom field mapping UI
│ │ ├── scatter_plot.rs # XY scatter visualization
│ │ └── tool_switcher.rs # Tool selection UI
│ └── bin/
│ └── test_parser.rs # CLI parser testing utility
├── assets/
│ ├── icons/ # Platform-specific app icons
│ ├── Outfit-Regular.ttf # Custom font
│ └── Outfit-Bold.ttf # Custom font (bold)
├── exampleLogs/ # Test data
├── .github/
│ └── workflows/
│ ├── ci.yml # CI pipeline
│ └── release.yml # Release automation
├── build.rs # Windows icon embedding
├── Cargo.toml # Project manifest
└── README.md # Documentation
Lines of Code
- Core app: 934 lines
- UI modules: ~3,148 lines
- Parsers: ~1,667 lines
- Supporting: ~1,108 lines
- Total: ~6,857 lines
Architecture Overview
Data Flow
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Log File │───►│ Parser │───►│ Log Struct │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Display │◄───│ LTTB Down- │◄───│ Selected │
│ (egui) │ │ sample │ │ Channels │
└─────────────┘ └──────────────┘ └─────────────┘
Key Components
UltraLogApp (app.rs)
- Main application state
- Implements
eframe::Apptrait - Manages file loading, tabs, playback
Parsers (parsers/)
- Each ECU format has its own parser
- All implement the
Parseabletrait - Convert ECU-specific data to common
Logstruct
UI Modules (ui/)
- Each UI section is a separate module
- Uses egui's immediate mode paradigm
- Renders from application state each frame
State Management
pub struct UltraLogApp {
// Files and tabs
files: Vec<LoadedFile>,
tabs: Vec<Tab>,
active_tab: Option<usize>,
// Playback
cursor_time: Option<f64>,
is_playing: bool,
playback_speed: f64,
// Settings
unit_preferences: UnitPreferences,
color_blind_mode: bool,
field_normalization: bool,
// UI state
loading_state: LoadingState,
downsample_cache: HashMap<...>,
}
Adding New ECU Support
Step 1: Add ECU Type
In src/parsers/types.rs:
#[derive(Debug, Clone, PartialEq)]
pub enum EcuType {
Haltech,
EcuMaster,
Speeduino,
NewEcu, // Add your ECU type
}
Step 2: Create Parser Module
Create src/parsers/newecu.rs:
use super::types::{Channel, Log, Meta, Parseable, Value};
use anyhow::Result;
pub struct NewEcuParser;
impl Parseable for NewEcuParser {
fn parse(&self, data: &str) -> Result<Log> {
// Parse your ECU format here
let channels = vec![
Channel {
name: "RPM".to_string(),
unit: Some("rpm".to_string()),
..Default::default()
},
// ... more channels
];
let data = vec![
vec![Value::Float(3500.0), /* ... */],
// ... more records
];
let times = vec!["0.000".to_string(), /* ... */];
Ok(Log {
meta: Meta::default(),
channels,
times,
data,
})
}
}
Step 3: Register Parser
In src/parsers/mod.rs:
pub mod newecu;
pub use newecu::NewEcuParser;
Step 4: Add Format Detection
In src/app.rs, add detection logic in the file loading function:
fn detect_format(content: &str) -> Option<EcuType> {
if content.starts_with("NewECU Header") {
return Some(EcuType::NewEcu);
}
// ... existing detection
}
Step 5: Add to Format Handler
match ecu_type {
EcuType::NewEcu => NewEcuParser.parse(&content),
// ... existing handlers
}
Step 6: Add Field Normalizations
In src/normalize.rs, add mappings for your ECU's channel names:
("newecu_rpm", "Engine RPM"),
("newecu_map", "Manifold Pressure"),
// ... more mappings
Code Style
Formatting
Use rustfmt for consistent formatting:
cargo fmt
Linting
Use clippy with warnings as errors:
cargo clippy -- -D warnings
Naming Conventions
render_*- UI rendering methodsstart_*- Async operationsget_*/set_*- AccessorsSCREAMING_SNAKE_CASE- ConstantsPascalCase- Types and traitssnake_case- Functions and variables
Error Handling
- Use
anyhowfor parser errors - Use
thiserrorfor custom error types - Show user-friendly errors via toast notifications
Testing
Run Tests
cargo test
Test Parser
cargo run --bin test_parser -- path/to/logfile.csv
Example Log Files
The exampleLogs/ directory contains sample files:
haltech/- Haltech CSV samplesecumaster/- ECUMaster CSV samplesspeeduino/- Speeduino MLG samplesrusefi/- rusEFI MLG samples
CI/CD
CI Pipeline (ci.yml)
Runs on every push and pull request:
- Check - Compile check on all platforms
- Test - Run test suite
- Clippy - Lint for issues
- Format - Verify code formatting
Release Pipeline (release.yml)
Triggered by version tags (v*):
- Build - Create binaries for all platforms
- Release - Create GitHub release with binaries
Creating a Release
# Update version in Cargo.toml
# Commit changes
git add .
git commit -m "Release v1.0.0"
# Create and push tag
git tag v1.0.0
git push origin v1.0.0
Contributing
How to Contribute
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
Pull Request Guidelines
- Keep PRs focused on a single change
- Update documentation if needed
- Add tests for new functionality
- Ensure CI passes
- Write clear commit messages
Commit Message Format
type: short description
Longer description if needed.
Fixes #123
Types:
feat- New featurefix- Bug fixdocs- Documentationrefactor- Code refactoringtest- Testschore- Maintenance
Areas for Contribution
- New ECU formats - Add support for more ECUs
- Features - Implement roadmap items
- Bug fixes - Fix reported issues
- Documentation - Improve wiki and comments
- Performance - Optimize parsing or rendering
- Accessibility - Improve accessibility features
Roadmap
Planned Features
- MegaSquirt format support
- AEM format support
- MaxxECU format support
- MoTeC format support
- Link ECU format support
- Data export to CSV/Excel
- Advanced statistical analysis
- Data filtering and smoothing
- Custom formula channels
- Persistent settings storage
- Multi-log comparison tools
Feature Requests
Open an issue on GitHub to request features.
Resources
Dependencies Documentation
- egui - GUI framework
- eframe - egui framework
- egui_plot - Plotting
- serde - Serialization
- anyhow - Error handling
Related Links
Next Steps
- Getting Started - User introduction
- Supported ECU Formats - Current ECU support
- Troubleshooting - Common issues
From the GitHub wiki. Edit this page