Skip to content

Commit 2c886ef

Browse files
semperventMacFarland, MidgiemidgemacfjGaboardisempervent
authored
Release/1.2.0 (#24)
# Summary - NTP Probe Support - Docker Images - some bug fixes --------- Co-authored-by: MacFarland, Midgie <macfarlandmj@ornl.gov> Co-authored-by: Midgie MacFarland <160664522+midgemacf@users.noreply.github.com> Co-authored-by: James Gaboardi <jgaboardi@gmail.com> Co-authored-by: sempervent <jngrant9+git@gmail.com> Co-authored-by: Grant, Josh <grantjn@ornl.gov>
1 parent 8e3d5a9 commit 2c886ef

122 files changed

Lines changed: 8446 additions & 1575 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/lint.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ jobs:
1212
ruff-lint:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- uses: actions/checkout@v4
16-
- uses: astral-sh/ruff-action@v3
17-
with:
18-
version: "0.12.12"
19-
args: check
20-
- uses: astral-sh/ruff-action@v3
21-
with:
22-
args: format --check
15+
- uses: actions/checkout@v6
2316
- name: Install uv
24-
uses: astral-sh/setup-uv@v5
17+
uses: astral-sh/setup-uv@v7
2518
with:
2619
version: "0.7.3"
2720
- name: Set up Python
2821
run: uv python install
2922
- name: Sync project, including dev dependencies
3023
run: uv sync --all-extras
24+
- uses: astral-sh/ruff-action@v3
25+
with:
26+
version: "0.12.12"
27+
args: check
28+
- uses: astral-sh/ruff-action@v3
29+
with:
30+
args: format --check
3131
- name: Build static content
3232
run: |
3333
uv run python ./scripts/gen_api_docs.py

.github/workflows/publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jobs:
1818
runs-on: ubuntu-latest
1919
steps:
2020
- name: Checkout
21-
uses: actions/checkout@v3
21+
uses: actions/checkout@v6
2222
- name: Install uv
23-
uses: astral-sh/setup-uv@v5
23+
uses: astral-sh/setup-uv@v7
2424
with:
2525
version: "0.7.3"
2626
- name: Set up Python

.github/workflows/static.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ jobs:
2020
runs-on: ubuntu-latest
2121
steps:
2222
- name: Checkout
23-
uses: actions/checkout@v3
23+
uses: actions/checkout@v6
2424
- name: Install uv
25-
uses: astral-sh/setup-uv@v5
25+
uses: astral-sh/setup-uv@v7
2626
with:
2727
version: "0.7.3"
2828
- name: Set up Python
@@ -36,7 +36,7 @@ jobs:
3636
- name: Setup Pages
3737
uses: actions/configure-pages@v5
3838
- name: Upload artifact
39-
uses: actions/upload-pages-artifact@v3
39+
uses: actions/upload-pages-artifact@v4
4040
with:
4141
path: 'site'
4242
- name: Deploy to GitHub Pages

.github/workflows/tests.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@v6
1818

1919
- name: Install uv
20-
uses: astral-sh/setup-uv@v6
20+
uses: astral-sh/setup-uv@v7
21+
22+
- name: Install PostgreSQL and PostGIS tooling
23+
run: |
24+
sudo apt-get update
25+
sudo apt-get install -y postgresql-16 postgresql-client-16 postgresql-16-postgis-3 postgresql-16-postgis-3-scripts
26+
echo "/usr/lib/postgresql/16/bin" >> "$GITHUB_PATH"
2127
2228
- name: Install the project
2329
run: uv sync --all-extras --dev
2430

2531
- name: Run tests
26-
run: uv run pytest tests/
32+
run: uv run pytest tests/

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# OpenSAMPL data paths
2+
archive/
3+
ntp-snapshots/
14
# Byte-compiled / optimized / DLL files
25
__pycache__/
36
*.py[cod]

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,31 @@ This project adheres to [Semantic Versioning](https://semver.org/).
3737
*Unreleased* versions radiate potential—-and dread. Once you merge an infernal PR, move its bullet under a new version heading with the actual release date.*
3838
3939
-->
40+
## [1.2.0] - 2026-04-29
41+
### Added
42+
- 🔥 First-class NTP vendor and probe support using the existing OpenSAMPL extension model
43+
- 🔥 Local and remote NTP collection paths, including `ntp_metadata` loading behavior
44+
- 🔥 NTP-focused metrics such as jitter, delay, stratum, reachability, root delay, root dispersion, poll interval, and sync health
45+
- 🔥 Additional NTP metadata handling for collector/target probe relationships and reference-backed loading
46+
- 🔥 Compact reference/source metadata views in dashboards to improve interpretation of NTP-backed timing data
47+
- 🔥 Documentation covering the NTP extension path, collection semantics, and geolocation behavior
48+
- 🔥 Additional unit and integration-style tests for NTP collection, loading, geolocation helpers, and seeded database defaults
49+
- 🔥 Moved alembic migration code into openSAMPL along with Docker image information
50+
- 🔥 Moved backend api code into openSAMPL along with Docker image information
51+
- 🔥 Docker-compose for developers which installs openSAMPL as editable on backend image
52+
53+
### Changed
54+
- ⚡ Hardened dashboard queries and variables to avoid brittle empty-filter handling and varchar-versus-UUID failures
55+
- ⚡ Updated timing dashboards and wording to use reference-safe terminology for NTP-backed demo paths
56+
- ⚡ Reworked integration-style tests to use the project MockDB harness instead of requiring a locally spawned PostgreSQL instance
57+
- ⚡ Updated CI to install PostgreSQL/PostGIS tooling so the workflow can support `pytest-postgresql`-style environments when needed
58+
59+
### Fixed
60+
- 🩹 Seeded default metric UUID handling in the MockDB test harness now points to the UNKNOWN metric as intended
61+
- 🩹 Bug which caused random data duration to always be 1 hour
62+
- 🩹 Issue with CI order causing linting to fail
63+
- 🩹 Fixed variable assignment for mkdocs-click integration
64+
4065
## [1.1.5] - 2025-09-22
4166
### Fixed
4267
- 🩹 More durable timestamp extrapolation in time data insertion

README.md

Lines changed: 83 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -20,143 +20,153 @@
2020
</div>
2121

2222

23-
OpenSAMPL was created to provide a set of Python tools for managing clock data in a TimescaleDB database, specifically designed for synchronization analytics and monitoring.
24-
This project came out of [**CAST**](https://cast.ornl.gov), the **C**enter for **A**lternative **S**yncrhonization and **T**iming, a research group at Oak Ridge National Laboratory (ORNL).
25-
The name OpenSAMPL stands for **O**pen **S**ynchronization **A**nalytics and **M**onitoring **PL**atform, and provides the code and logic for uploading, managing, and visualizing clock data from various sources, including ADVA probes and Microchip TWST data files,
26-
with the goal of this project being to provide a comprehensive and open-source solution for clock data management and analysis.
27-
Visualizations are provided via [grafana](https://grafana.com/), and the data is stored in a [TimescaleDB](https://www.timescale.com/) database, which is a time-series database built on PostgreSQL.
23+
OpenSAMPL provides Python tools for collecting, loading, and visualizing clock data in a
24+
TimescaleDB-backed synchronization analytics stack.
25+
This project came out of [**CAST**](https://cast.ornl.gov), the **C**enter for
26+
**A**lternative **S**ynchronization and **T**iming at Oak Ridge National Laboratory (ORNL).
27+
The name OpenSAMPL stands for **O**pen **S**ynchronization **A**nalytics and
28+
**M**onitoring **PL**atform.
29+
30+
The current codebase supports loading and analysis workflows for ADVA, Microchip TWST,
31+
Microchip TP4100, and NTP-derived probe data. Visualization is provided through
32+
[Grafana](https://grafana.com/), and the data is stored in
33+
[TimescaleDB](https://www.timescale.com/), which is built on PostgreSQL.
2834

2935

3036
### (**O**pen **S**ynchronization **A**nalytics and **M**onitoring **PL**atform)
3137

32-
python tools for adding clock data to a timescale db.
38+
Python tools for adding clock and timing data to a TimescaleDB database.
3339

34-
## CLI TOOL
40+
## Installation
3541

36-
### Installation
42+
1. Ensure you have Python 3.10 or higher installed.
43+
2. Install the latest release:
3744

38-
1. Ensure you have Python 3.9 or higher installed
39-
2. Pip install the latest version of opensampl:
4045
```bash
4146
pip install opensampl
4247
```
4348

4449
### Development Setup
50+
4551
```bash
4652
uv venv
47-
uv sync --extra all
53+
uv sync --all-extras --dev
4854
source .venv/bin/activate
4955
```
50-
This will create a virtual environment and install the development dependencies.
56+
This creates a virtual environment and installs the development dependencies.
5157

5258
### Environment Setup
5359

54-
The tool requires several environment variables. Create a `.env` file in your project root:
60+
The CLI reads configuration from environment variables or a local `.env` file.
5561

56-
When routing through a backend:
62+
When routing through a backend service:
5763
```bash
58-
ROUTE_TO_BACKEND=true # Set to true if using backend service
59-
BACKEND_URL=http://localhost:8000 # Only needed if ROUTE_TO_BACKEND is true
64+
ROUTE_TO_BACKEND=true
65+
BACKEND_URL=http://localhost:8000
6066

61-
# Archive configuration
62-
ARCHIVE_PATH=/path/to/archive # Where processed files are stored
67+
ARCHIVE_PATH=/path/to/archive
6368
```
64-
When directly accessing db:
69+
70+
When connecting directly to PostgreSQL / TimescaleDB:
6571
```bash
66-
# Database connection
6772
DATABASE_URL=postgresql://<user>:<password>@<host>:<port>/<database>
68-
69-
# Archive configuration
70-
ARCHIVE_PATH=/path/to/archive # Where processed files are stored
73+
ARCHIVE_PATH=/path/to/archive
7174
```
7275

73-
### Basic Usage
76+
Use `opensampl config show` to inspect the current resolved configuration.
7477

75-
The CLI tool provides several commands. You can use `opensampl --help` (or, any deeper `opensampl [command] --help`) to get details
78+
## CLI
7679

77-
#### Load Probe Data
80+
The main CLI exposes `collect`, `config`, `create`, `init`, and `load`.
81+
Use `opensampl --help` and `opensampl <command> --help` for current options.
7882

79-
Load data from ADVA probes:
83+
If you plan to use the NTP, Microchip TWST, or Microchip TP4100 collectors, install the optional collection dependencies:
8084

8185
```bash
82-
# Load single file
83-
opensampl load probe adva path/to/file.txt.gz
84-
85-
# Load directory of files
86-
opensampl load probe adva path/to/directory/
86+
pip install "opensampl[collect]"
8787
```
88-
ADVA probes have all their metadata and their time data in each file, so no need to use the `-m` or `-t` options, though if you want to skip loading one or the other it becomes useful!
8988

90-
options:
91-
- `--metadata` (`-m`): Only load probe metadata
92-
- `--time-data` (`-t`): Only load time series data
93-
- `--no-archive` (`-n`): Don't archive processed files
94-
- `--archive-path` (`-a`): Override default archive directory
95-
- `--max-workers` (`-w`): Maximum number of worker threads (default: 4)
96-
- `--chunk-size` (`-c`): Number of time data entries per batch (default: 10000)
89+
### Load Probe Data
9790

98-
#### Load Direct Table Data
91+
Load data with the probe type name directly:
9992

100-
Load data directly into a database table. Format can be yaml or json. Can be a list of dictionaries or a single dictionary.
93+
```bash
94+
opensampl load ADVA path/to/file.txt.gz
95+
opensampl load ADVA path/to/directory/
96+
```
10197

102-
you do not have to specify schema, is assumed to be castdb.
98+
ADVA files bundle metadata and time-series data in a single file, so the split flags are
99+
usually not needed.
103100

104-
The --if-exists option controls how to handle conflicts:
105-
- update: Only update fields that are provided and non-default (default)
106-
- error: Raise an error if entry exists
107-
- replace: Replace all non-primary-key fields with new values
108-
- ignore: Skip if entry exists
101+
```bash
102+
opensampl load MicrochipTWST path/to/twst-output
103+
opensampl load MicrochipTP4100 path/to/tp4100-output
104+
```
105+
106+
NTP data is collected first and then loaded from the output directory:
109107

110108
```bash
111-
opensampl load table table_name path/to/data.yaml
109+
opensampl collect ntp --mode remote --server pool.ntp.org --output-path ./ntp-out
110+
opensampl load NTP ./ntp-out
112111
```
113112

114-
So, you can do things like the following
113+
Load options:
114+
115+
- `--metadata` / `-m`: load only probe metadata
116+
- `--time-data` / `-t`: load only time-series data
117+
- `--no-archive` / `-n`: skip archiving processed files
118+
- `--archive-path` / `-a`: override the archive directory
119+
- `--max-workers` / `-w`: set the worker count
120+
- `--chunk-size` / `-c`: set the batch size for time-series inserts
121+
122+
### Load Direct Table Data
123+
124+
Load YAML or JSON directly into a table:
125+
115126
```bash
116-
opensampl load table locations --if-exists replace updated_location.yaml
127+
opensampl load table locations updated_location.yaml
117128
```
118-
Where this is the updated_location
129+
130+
Conflict handling is controlled by `--if-exists`:
131+
132+
- `update`: fill null fields in an existing row
133+
- `error`: raise if the row exists
134+
- `replace`: replace non-primary-key values
135+
- `ignore`: skip existing rows
136+
137+
Example input:
138+
119139
```yaml
120140
name: EPB Chattanooga
121141
lat: 35.9311256
122142
lon: -84.3292469
123143
```
124-
And it will overwrite the existing entry for EPB Chattanooga, or create a new one if it doesn't exist yet.
125-
126144
127145
### View Configuration
128146
129-
Display current environment configuration:
130-
131147
```bash
132-
# Show all variables
133-
poetry run opensampl config show
134-
135-
# Show with descriptions
136-
poetry run opensampl config show --explain
137-
138-
# Show specific variable
139-
poetry run opensampl config show --var DATABASE_URL
148+
opensampl config show
149+
opensampl config show --explain
150+
opensampl config show --var DATABASE_URL
140151
```
141152

142153
### Set Configuration
143154

144-
Update environment variables:
145-
146155
```bash
147-
poetry run opensampl config set VARIABLE_NAME value
156+
opensampl config set VARIABLE_NAME value
148157
```
149158

150159
## File Format Support
151160

152-
The tool currently supports:
153-
154-
ADVA probe data files with the following naming convention:
155-
`<ip_address>CLOCK_PROBE-<probe_id>-YYYY-MM-DD-HH-MM-SS.txt.gz`
161+
The loaders currently support:
156162

157-
Example: `10.0.0.121CLOCK_PROBE-1-1-2024-01-02-18-24-56.txt.gz`
163+
- ADVA probe files named like
164+
`<ip_address>CLOCK_PROBE-<probe_id>-YYYY-MM-DD-HH-MM-SS.txt.gz>`
165+
- Microchip TWST and TP4100 output produced by the collector tooling
166+
- NTP snapshot output produced by `opensampl collect ntp`
158167

159-
Microchip TWST Data Files as generated by the script available.
168+
Example ADVA file:
169+
`10.0.0.121CLOCK_PROBE-1-1-2024-01-02-18-24-56.txt.gz`
160170

161171
# Contributing
162172
We welcome contributions! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to get started.
@@ -234,4 +244,3 @@ adva_mask_margin: 0 # Mask margin
234244
- Table relationships are maintained through UUID references
235245
- Geographic coordinates use WGS84 projection (SRID 4326) by default
236246
- Boolean fields (public) are optional and can be null
237-

docs/api/collect/cli.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# CLI Reference
2+
3+
This page provides documentation for our command line tools.
4+
5+
::: mkdocs-click
6+
:module: opensampl.collect.cli
7+
:command: cli
8+
:prog_name: opensampl-collect
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `opensampl.collect.microchip.tp4100.collect_4100`
2+
3+
::: opensampl.collect.microchip.tp4100.collect_4100
4+
options:
5+
show_root_heading: false
6+
show_submodules: true
7+
show_source: true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `opensampl.collect.microchip.twst.context`
2+
3+
::: opensampl.collect.microchip.twst.context
4+
options:
5+
show_root_heading: false
6+
show_submodules: true
7+
show_source: true

0 commit comments

Comments
 (0)