Skip to content

Commit 37ea0e7

Browse files
authored
Openlineage integration (#263)
* Add dagster-openlineage community integration scaffold * Added dagster-openlineage integration with support for dagster 1.6.9 to lastest dagster version * Added dagster-openlineage integration with support for dagster 1.6.9 to lastest dagster version * Update README with Dagster Definitions usage and testing workflow * Update README with Dagster Definitions usage and testing workflow * reformatted sensor.py with uv run ruff format
1 parent daffb97 commit 37ea0e7

20 files changed

Lines changed: 3606 additions & 0 deletions
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
install:
2+
uv sync
3+
4+
build:
5+
uv build
6+
7+
test:
8+
uv run pytest
9+
10+
ruff:
11+
uv run ruff check --fix
12+
uv run ruff format
13+
14+
check:
15+
uv run pyright
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# dagster-openlineage
2+
3+
Dagster integration for OpenLineage for automatic metadata collection. It provides an OpenLineage sensor that tails Dagster event logs, converts events to OpenLineage metadata, and emits them to a backend.
4+
5+
## Features
6+
7+
- **Metadata tracking** for Dagster jobs & ops lifecycle
8+
- **OpenLineage sensor** for automatic event collection
9+
10+
## Requirements
11+
12+
- Python 3.10+
13+
- Dagster >=1.6.9
14+
15+
## Installation
16+
17+
```bash
18+
pip install dagster-openlineage
19+
```
20+
21+
## Quick Start
22+
23+
Add the `openlineage_sensor` to your Dagster `Definitions`:
24+
25+
```python
26+
from dagster import Definitions, job, op
27+
from dagster_openlineage import openlineage_sensor
28+
29+
@op
30+
def extract():
31+
return {"data": 1}
32+
33+
@op
34+
def transform(data):
35+
return data["data"] + 1
36+
37+
@job
38+
def my_job():
39+
transform(extract())
40+
41+
defs = Definitions(
42+
jobs=[my_job],
43+
sensors=[openlineage_sensor()]
44+
)
45+
```
46+
47+
## Usage
48+
49+
### Sensor Configuration
50+
51+
The sensor supports several configuration options:
52+
53+
| Option | Default | Description |
54+
|--------|---------|-------------|
55+
| `minimum_interval_seconds` | 300 | Minimum seconds between sensor evaluations |
56+
| `record_filter_limit` | 30 | Max number of event logs to process per evaluation |
57+
| `after_storage_id` | 0 | Starting storage ID for event processing |
58+
59+
**Custom configuration example:**
60+
61+
```python
62+
defs = Definitions(
63+
jobs=[my_job],
64+
sensors=[
65+
openlineage_sensor(
66+
minimum_interval_seconds=60,
67+
record_filter_limit=60,
68+
)
69+
]
70+
)
71+
```
72+
73+
**Resuming from a specific storage ID:**
74+
75+
Use `after_storage_id` to resume processing from a specific point in your event log. This is useful when you need to reprocess events or start from a known storage ID:
76+
77+
```python
78+
defs = Definitions(
79+
jobs=[my_job],
80+
sensors=[openlineage_sensor(after_storage_id=500)]
81+
)
82+
```
83+
84+
### Configuration
85+
86+
#### Environment Variables
87+
88+
Set the following environment variables:
89+
90+
- `OPENLINEAGE_URL` - URL of the OpenLineage backend (required)
91+
- `OPENLINEAGE_API_KEY` - Bearer token for authentication (optional)
92+
- `OPENLINEAGE_NAMESPACE` - Default namespace (optional)
93+
94+
**Where to set these:**
95+
96+
- **User Repository Deployments**: Add variables to the repository where the sensor is defined
97+
- **Otherwise**: Add variables to the Dagster Daemon
98+
99+
#### Important Notes
100+
101+
- **Single sensor per instance**: Only define one OpenLineage sensor per Dagster instance. Multiple sensors will emit duplicate job runs.
102+
103+
- **Non-sharded event log storage**: Use non-sharded event log storage. Sharded storage (like default `SqliteEventLogStorage`) may prevent the cursor from updating properly.
104+
105+
106+
## Version Compatibility
107+
108+
This library supports Dagster versions `>=1.6.9`.
109+
110+
- **End users**: `pip install dagster-openlineage` respects `pyproject.toml` constraints, allowing any compatible Dagster version
111+
- **CI builds**: Uses committed `uv.lock` for reproducible builds
112+
- **Developers**: Can test specific Dagster versions by updating the lock file
113+
114+
115+
## Development
116+
117+
### Setup
118+
119+
```bash
120+
# Install dependencies
121+
uv sync
122+
123+
# Run tests
124+
make test
125+
```
126+
127+
### Testing with Different Dagster Versions
128+
129+
```bash
130+
# Install desired version
131+
uv pip install dagster==1.XX
132+
133+
# Update lock file
134+
uv lock --upgrade-package dagster==1.XX
135+
136+
# Run tests
137+
make test
138+
139+
# Revert to default
140+
uv lock
141+
make test
142+
```
143+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from dagster_openlineage.version import __version__
2+
3+
from dagster_openlineage.adapter import OpenLineageAdapter
4+
from dagster_openlineage.listener import OpenLineageEventListener
5+
from dagster_openlineage.sensor import openlineage_sensor
6+
from dagster_openlineage.utils import make_step_job_name, to_utc_iso_8601
7+
from dagster_openlineage.compat import (
8+
get_pipeline_origin,
9+
get_job_origin,
10+
get_repository_origin,
11+
)
12+
13+
import importlib.util
14+
import inspect
15+
16+
_dagster_lib_spec = importlib.util.find_spec("dagster._core.libraries")
17+
if _dagster_lib_spec is not None:
18+
from dagster._core.libraries import DagsterLibraryRegistry
19+
20+
_register_sig = inspect.signature(DagsterLibraryRegistry.register)
21+
_has_is_dagster_package = "is_dagster_package" in _register_sig.parameters
22+
23+
if _has_is_dagster_package:
24+
DagsterLibraryRegistry.register(
25+
"dagster-openlineage", __version__, is_dagster_package=False
26+
)
27+
else:
28+
DagsterLibraryRegistry.register("dagster-openlineage", __version__)
29+
30+
__all__ = [
31+
"OpenLineageAdapter",
32+
"OpenLineageEventListener",
33+
"openlineage_sensor",
34+
"make_step_job_name",
35+
"to_utc_iso_8601",
36+
"get_pipeline_origin",
37+
"get_job_origin",
38+
"get_repository_origin",
39+
]

0 commit comments

Comments
 (0)