FaaS Telemetric Reporter - Job Execution Metrics Library
Project description
Telemetric Reporter - FaaS Job Execution Metrics Library
A Python library for Google Cloud Functions that provides automatic instrumentation, exception handling, and atomic persistence of execution metrics and payloads to Firestore.
Features
- Auto-Instrumentation: Automatic timing and memory tracking
- Exception Handling: Comprehensive error handling with correlation context
- Atomic Persistence: Batch writes to
pipeline_logsandpipeline_dataFirestore collections - Data Sanitization: Automatic conversion of dates to ISO 8601 UTC and metrics to floats
- Hexagonal Architecture: Swappable storage backends via ports and adapters
- Correlation Tracking: Distributed tracing via
correlation_idandjob_id
Installation
pip install faaspectre
Quick Start
from faaspectre import create_job_execution_reporter, ExecutionContext
# Create context from workflow payload
context = ExecutionContext.from_workflow_payload(workflow_payload)
# Use factory function with defaults
with create_job_execution_reporter(context, "ANALYZE_SENTIMENT") as reporter:
# Your business logic here
result = my_worker_function(**kwargs)
# Save execution payload (optional)
reporter.save_execution_payload(result)
Configuration
Environment Variables
The library uses environment variables for configuration:
TELEMETRIC_STORAGE_BACKEND: Storage backend (firestore|bigquery|postgres). Default:firestorePIPELINE_LOGS_COLLECTION: Firestore collection name for metrics. Default:pipeline_logsPIPELINE_DATA_COLLECTION: Firestore collection name for payloads. Default:pipeline_dataGC_PROJECT_ID: Google Cloud project ID (required for Firestore)
Custom Configuration
from faaspectre import TelemetricConfig, create_job_execution_reporter
# Create custom config
config = TelemetricConfig(
storage_backend="firestore",
pipeline_logs_collection="my_logs",
pipeline_data_collection="my_data",
project_id="my-project-id"
)
# Use with factory function
with create_job_execution_reporter(context, "STEP_NAME", config=config) as reporter:
# Your code here
pass
Architecture
The library follows Hexagonal Architecture (Ports & Adapters) pattern:
- Domain Layer: Business models and rules (
ExecutionContext,ExecutionMetrics,ExecutionPayload) - Application Layer: Use cases and ports (interfaces)
- Infrastructure Layer: Adapters (Firestore, Psutil implementations)
This design allows easy swapping of storage backends without changing application code.
Usage Examples
Basic Usage
from faaspectre import create_job_execution_reporter, ExecutionContext
def my_worker_function(context: ExecutionContext, **kwargs):
"""Your business logic here."""
# Process data
result = {"processed": True, "count": 100}
return result
# In your Cloud Function
def cloud_function_handler(request):
context = ExecutionContext.from_workflow_payload(request.json)
with create_job_execution_reporter(context, "PROCESS_DATA") as reporter:
result = my_worker_function(context, **request.json)
reporter.save_execution_payload(result)
return result
Custom Storage and Instrumentation
from faaspectre import (
create_job_execution_reporter,
FirestoreMetricStorage,
PsutilInstrumentation,
TelemetricConfig
)
config = TelemetricConfig.from_env()
storage = FirestoreMetricStorage(config)
instrumentation = PsutilInstrumentation()
with create_job_execution_reporter(
context,
"STEP_NAME",
storage=storage,
instrumentation=instrumentation
) as reporter:
# Your code here
pass
Error Handling
The library automatically handles exceptions and saves them with FAILED status:
with create_job_execution_reporter(context, "STEP_NAME") as reporter:
try:
# Your code that might raise exceptions
result = risky_operation()
reporter.save_execution_payload(result)
except Exception:
# Exception is automatically logged and saved with FAILED status
# Exception is re-raised for orchestrator retry
raise
Data Models
ExecutionContext
Context from workflow payload:
@dataclass
class ExecutionContext:
correlation_id: str # UUID-v4, Global Trace ID
job_id: str # Unique ID for this execution
step_name: str # Human-readable stage name
triggered_by: str # Source: "ETL_WORKFLOW" | "USER:email"
prev_job_id: Optional[str] # Parent job_id if not start of chain
ExecutionMetrics
Metrics saved to pipeline_logs collection:
@dataclass
class ExecutionMetrics:
doc_id: str # Matches Firestore Document ID
correlation_id: str # UUID-v4
job_id: str
step_name: str
triggered_by: str
created_at: str # ISO 8601 UTC
start_time_epoch: float
status: str # "PENDING" | "SUCCESS" | "FAILED"
end_time_epoch: Optional[float]
duration_ms: Optional[float]
memory_mb: Optional[float]
error_summary: Optional[str]
ExecutionPayload
Payload saved to pipeline_data collection:
@dataclass
class ExecutionPayload:
doc_id: str # Matches Log ID
correlation_id: str # UUID-v4
payload: Dict[str, Any] # Flexible structure
Firestore Collections
pipeline_logs
Operational metrics for dashboard insights:
- Document ID:
job_id - Fields:
correlation_id,job_id,step_name,status,start_time_epoch,end_time_epoch,duration_ms,memory_mb,error_summary, etc.
pipeline_data
Business data for detailed audit trails:
- Document ID:
job_id(matchespipeline_logsdoc_id) - Fields:
correlation_id,payload(flexible structure)
Error Handling Strategy
The library follows a log-and-re-raise pattern:
- Business Logic Errors: Logged → Saved with
FAILEDstatus → Re-raised for orchestrator retry - Validation Errors: Logged → Re-raised (programming error, fix code)
- Storage Errors: Logged → Re-raised (orchestrator handles retries)
- Instrumentation Errors: Logged as warnings → Continue without instrumentation (graceful degradation)
No retry logic in the library - The orchestrator (Google Cloud Workflows) handles retries.
Exception Hierarchy
TelemetricError (base)
├── ConfigurationError
├── ValidationError
├── StorageError
│ └── AtomicWriteError
└── InstrumentationError
All exceptions include correlation_id and job_id for distributed tracing.
Thread Safety
The library assumes single-threaded FaaS execution (Google Cloud Functions). Each JobExecutionReporter instance tracks its own metrics. See Thread Safety Documentation for details.
Testing
Setup
Install development dependencies:
pip install -r requirements-dev.txt
pip install -e .[faasjob]
Or use Make:
make install-dev
Running Tests
Run all tests:
pytest tests/
Or use Make:
make test
Run tests with coverage:
make test-coverage
Test Structure
Tests are organized to mirror the source code structure:
tests/faasjob/domain/- Domain model teststests/faasjob/application/- Application layer teststests/faasjob/infrastructure/- Infrastructure adapter teststests/faasjob/utils/- Utility function tests
See TEST_CASES.md for comprehensive test scenarios.
Development
Make Commands
make help # Show all available commands
make install # Install package with faasjob dependencies
make install-dev # Install all development dependencies
make test # Run tests
make test-coverage # Run tests with coverage report
make lint # Run linters (pylint, mypy)
make format # Format code with black
make verify # Run all verification checks (tests + linting)
make clean # Clean build artifacts
Dependencies
Production dependencies (installed with pip install .[faasjob]):
google-cloud-firestore==2.4.0: Firestore clientpsutil>=5.8.0: Memory trackingmarshmallow-dataclass==8.3.2: Data validation
Development dependencies (see requirements-dev.txt):
pytest>=7.0.0: Testing frameworkpytest-cov>=4.0.0: Coverage reportingpytest-mock>=3.10.0: Mocking supportpylint>=2.15.0: Code qualityblack>=22.0.0: Code formattingmypy>=1.0.0: Type checking
Migration from FaasJobManager
If migrating from the old FaasJobManager:
- Replace
FaasJobManagerwithcreate_job_execution_reporter() - Replace
TaskContextwithExecutionContext - Use
save_execution_payload()instead ofsave_business_data() - Update collection names if different from defaults
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file faaspectre-0.0.1.tar.gz.
File metadata
- Download URL: faaspectre-0.0.1.tar.gz
- Upload date:
- Size: 36.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a0339f592518070bdf3ffc707466b010a249b18bab77362061e36a596682084
|
|
| MD5 |
96693e220d3870a00771a26b627dacf6
|
|
| BLAKE2b-256 |
43795d734613205934b934ebe4337c015cfec5ce62a8766625fbdf32d28befcd
|
File details
Details for the file faaspectre-0.0.1-py3-none-any.whl.
File metadata
- Download URL: faaspectre-0.0.1-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77666c0f46fe2a90de0f64c042a6c46126a5ec170055bb1a74e04545ec22afe5
|
|
| MD5 |
d33913bfe6f6fab26bb956dcac4b8a56
|
|
| BLAKE2b-256 |
075e34f750a352a5907bf688be7cb2297779e441ffaa08a5e24238d690c8f572
|