SensorLogger Architecture
The sensor logger bridges sensors and file I/O, providing automated data collection with daily file organization and pluggable output formats.
Why This Design?
This design allows you to: - Separate data collection logic from file format concerns - Switch output formats (CSV, JSON, Parquet) without changing logging code - Organize data automatically into daily directories with metadata - Handle errors gracefully without stopping the logging process - Reuse the same logger with different storage strategies
Core Components
classDiagram
%% Core classes
class SensorLogger {
-sensor: Sensor
-tags: List~ReadTag~
-interval_seconds: int
-output_path: Path
-writer: WriterStrategy
-metadata_saver: SaverStrategy
-_current_date: date
-_metadata_written: bool
-_first_write_today: bool
+log()
-_get_daily_dir() Path
-_write_metadata_if_needed(daily_dir)
-_validate_interval()
}
class Sensor {
+read(tags) dict~ReadTag, Any~
+get_valid_tags() List~ReadTag~
}
class ReadTag {
<<abstract>>
+metadata: ReadTagMetadata
}
class WriterStrategy {
<<interface>>
+write(filepath, data_point, is_first)
+get_extension() str
}
class SaverStrategy {
<<interface>>
+save_logger_metadata(filepath, date, interval, sensor_type, tags)
+get_extension() str
}
%% Concrete implementations
class CSVWriter {
+write(filepath, data_point, is_first)
+get_extension() str
}
class JSONMetadataSaver {
+save_logger_metadata(filepath, date, interval, sensor_type, tags)
+get_extension() str
}
%% Relationships
SensorLogger o-- Sensor : reads from
Sensor --o ReadTag : exposes
SensorLogger o-- WriterStrategy : formats data with
SensorLogger o-- SaverStrategy : stores metadata with
WriterStrategy <|.. CSVWriter : implements
SaverStrategy <|.. JSONMetadataSaver : implements
How It Works
Logging Flow
When you call logger.log():
- Daily Directory Management
- Creates or accesses directory for current date (YYYYMMDD format)
-
Checks if this is the first log of a new day
-
Metadata Handling
- If first log of the day, writes metadata file using
SaverStrategy -
Metadata includes: date, interval, sensor type, tag information
-
Data Collection
- Reads all configured tags from the sensor
- Adds timestamp to create a data point
-
Formats:
{timestamp: ISO8601, TagName1: value1, TagName2: value2, ...} -
Data Writing
- Writes data point using
WriterStrategy -
Strategy handles file creation, headers, and appending
-
Error Handling
- Any exceptions are caught and logged to
errors.log - Logging continues on next call despite errors
Strategy Pattern
The SensorLogger uses the Strategy pattern for flexible I/O operations:
Writer Strategy
Controls how data is written:
from atmospyre.loggers.strategies.writers import CSVWriter
class CustomParquetWriter:
def write(self, filepath: Path, data_point: dict, is_first: bool):
# Custom implementation for Parquet format
...
def get_extension(self) -> str:
return 'parquet'
# Use custom writer
logger = SensorLogger(
sensor=sensor,
tags=[CO2, TEMPERATURE],
interval_seconds=60,
output_path='./data',
writer=CustomParquetWriter() # Plug in your strategy
)
Saver Strategy
Controls how metadata is stored:
from atmospyre.loggers.strategies.savers import JSONMetadataSaver
class YAMLMetadataSaver:
def save_logger_metadata(self, filepath, date, interval_seconds, sensor_type, tags):
# Custom implementation for YAML format
...
def get_extension(self) -> str:
return 'yaml'
# Use custom saver
logger = SensorLogger(
sensor=sensor,
tags=[CO2, TEMPERATURE],
interval_seconds=60,
output_path='./data',
metadata_saver=YAMLMetadataSaver()
)
Default Strategies
If no strategy is provided, defaults are used:
- Writer: CSVWriter - comma-separated values with headers
- Saver: JSONMetadataSaver - JSON formatted metadata