Uh oh!
There was an error while loading. Please reload this page.
Add tracking of triggering user to Dag runs - #51738
Conversation
jscheffl
commented
Jun 14, 2025
Note: Marking as DRAFT as I assume some pytests fail and need to be adjusted. |
21f2921 to
53e8254Comparepotiuk
commented
Jun 15, 2025
nice! Highly requested feature. |
Uh oh!
There was an error while loading. Please reload this page.
3ebb1ad to
2390c87CompareJust for reference, in Airflow 3, retrieving the triggering user from event logs requires the following approach. I've encapsulated the access_token handling within the That said, there may be scenarios where the logical date does not align as expected, which introduces additional complexity—particularly in our unit tests where we need to mock API responses. Given that over 50% of our DAGs rely on this functionality, its absence could significantly delay our adoption of Airflow 3. I hope this concern is understandable and that accommodating this request is feasible. I truly appreciate your consideration. def_find_owner_v3(dag_run=None) ->str|None:
""" This is only for Airflow3, use the Airflow Client API to fetch the event logs """# Only run for manual runsifdag_run.run_type.name.upper() !='MANUAL':
logger.error(f"Not manually triggered. run_type: {dag_run.run_type}")
return# Cant co-relate if logical date is missing for dag runifnotdag_run.logical_date:
logger.error(f"No logical date available for this run, cant find owner")
returnlogical_date=dag_run.logical_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] +'Z'importairflow_client.clientfromairflow_client.client.restimportApiExceptionfromcustom.api.utilsimportget_airflow_client_configurationconfiguration=get_airflow_client_configuration()
# Enter a context with an instance of the API clientwithairflow_client.client.ApiClient(configuration) asapi_client:
# Create an instance of the API classapi_instance=airflow_client.client.EventLogApi(api_client)
event='trigger_dag_run'try:
logger.info("#################################################")
logger.info(f"DAG ID: {dag_run.dag_id}")
logger.info(f"RUN ID: {dag_run.run_id}")
logger.info(f"Logical Date: {logical_date}")
logger.info("#################################################")
# Get Event Logsapi_response=api_instance.get_event_logs(dag_id=dag_run.dag_id, event=event)
ifnotapi_response:
logger.error("No trigger events found!")
returnforeventinreversed(api_response.event_logs):
logger.info(event)
ifevent.extra:
event_info= {}
event_info=json.loads(event.extra)
if"logical_date"inevent_info:
iflogical_date==event_info["logical_date"]:
logger.info(f"Matching Event: {event}")
logger.info(f"Dag triggered by: {event.owner}")
returnevent.ownerexceptExceptionase:
raiseAirflowException("Exception when calling EventLogApi->get_event_logs: %s\n"%e) |
pierrejeambrun
left a comment
There was a problem hiding this comment.
Just a few nits, questions, but looks good to me.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
2390c87 to
1ad52d8Compareashb
commented
Jul 1, 2025
That's because it's not about adding a column/it's not about what the code itself but how we do the feature, and it's about what is the most sustainable way to develop Airflow for the long term; is this short term approach right (which we will likely have in place for years), or should we spend more time to build a longer term and more generic approach. |
potiuk
commented
Jul 1, 2025
I think we are all well aware of that. And we have different views what would be more generic way and apparently slightly different design assumptions. Nobody who wants to add user here does it because they think it's "short term gain" - the arguments here are that this is a good design decision. There are clearly voices that audit log is a differen thing than data model of the app and they should not be mixed. That's one of the design views here. I think we should jointly make a dcieison based on those different design assumptions. IMHO design where 'triggering user" is part of the task instance model is a good design decision. |
ashb
commented
Jul 1, 2025
@potiuk Are you though? I don't really think you are, else you wouldn't have insulted my intentions by saying I was bike-shedding and having a pointless discussion. My point was not about what color to paint a bike shed, but if we should build a bike shed or a train station. |
potiuk
commented
Jul 1, 2025
Indeed too many discussions - 4 people approving. several having doubts, and complaints about bikesheddint. Let's just merge and move on. |
jscheffl
commented
Jul 1, 2025
Thanks for merging. Please calm down the argumentation. I was waiting before merge if there are real objections. I think the current PR was not a workaround and yes there could be cleaner and nicer solutions. I am open for somebody to change and clean-up but the additional field actually is not rocket science. So welcoming other PRs to make a real cool solution but we should focus our energy on the real critical items, I think there are sufficient other places to improve as well. |
(from https://github.com/apache/airflow/tree/python-client/3.1.0rc1) ## New Features: - Add `map_index` filter to TaskInstance API queries ([#55614](apache/airflow#55614)) - Add `has_import_errors` filter to Core API GET /dags endpoint ([#54563](apache/airflow#54563)) - Add `dag_version` filter to get_dag_runs endpoint ([#54882](apache/airflow#54882)) - Implement pattern search for event log endpoint ([#55114](apache/airflow#55114)) - Add asset-based filtering support to DAG API endpoint ([#54263](apache/airflow#54263)) - Add Greater Than and Less Than range filters to DagRuns and Task Instance list ([#54302](apache/airflow#54302)) - Add `try_number` as filter to task instances ([#54695](apache/airflow#54695)) - Add filters to Browse XComs endpoint ([#54049](apache/airflow#54049)) - Add Filtering by DAG Bundle Name and Version to API routes ([#54004](apache/airflow#54004)) - Add search filter for DAG runs by triggering user name ([#53652](apache/airflow#53652)) - Enable multi sorting (AIP-84) ([#53408](apache/airflow#53408)) - Add `run_on_latest_version` support for backfill and clear operations ([#52177](apache/airflow#52177)) - Add `run_id_pattern` search for Dag Run API ([#52437](apache/airflow#52437)) - Add tracking of triggering user to Dag runs ([#51738](apache/airflow#51738)) - Expose DAG parsing duration in the API ([#54752](apache/airflow#54752)) ## New API Endpoints: - Add Human-in-the-Loop (HITL) endpoints for approval workflows ([#52868](apache/airflow#52868), [#53373](apache/airflow#53373), [#53376](apache/airflow#53376), [#53885](apache/airflow#53885), [#53923](apache/airflow#53923), [#54308](apache/airflow#54308), [#54310](apache/airflow#54310), [#54723](apache/airflow#54723), [#54773](apache/airflow#54773), [#55019](apache/airflow#55019), [#55463](apache/airflow#55463), [#55525](apache/airflow#55525), [#55535](apache/airflow#55535), [#55603](apache/airflow#55603), [#55776](apache/airflow#55776)) - Add endpoint to watch dag run until finish ([#51920](apache/airflow#51920)) - Add TI bulk actions endpoint ([#50443](apache/airflow#50443)) - Add Keycloak Refresh Token Endpoint ([#51657](apache/airflow#51657)) ## Deprecations: - Mark `DagDetailsResponse.concurrency` as deprecated ([#55150](apache/airflow#55150)) ## Bug Fixes: - Fix dag import error modal pagination ([#55719](apache/airflow#55719))
(from https://github.com/apache/airflow/tree/python-client/3.1.0rc1) ## New Features: - Add `map_index` filter to TaskInstance API queries ([#55614](apache/airflow#55614)) - Add `has_import_errors` filter to Core API GET /dags endpoint ([#54563](apache/airflow#54563)) - Add `dag_version` filter to get_dag_runs endpoint ([#54882](apache/airflow#54882)) - Implement pattern search for event log endpoint ([#55114](apache/airflow#55114)) - Add asset-based filtering support to DAG API endpoint ([#54263](apache/airflow#54263)) - Add Greater Than and Less Than range filters to DagRuns and Task Instance list ([#54302](apache/airflow#54302)) - Add `try_number` as filter to task instances ([#54695](apache/airflow#54695)) - Add filters to Browse XComs endpoint ([#54049](apache/airflow#54049)) - Add Filtering by DAG Bundle Name and Version to API routes ([#54004](apache/airflow#54004)) - Add search filter for DAG runs by triggering user name ([#53652](apache/airflow#53652)) - Enable multi sorting (AIP-84) ([#53408](apache/airflow#53408)) - Add `run_on_latest_version` support for backfill and clear operations ([#52177](apache/airflow#52177)) - Add `run_id_pattern` search for Dag Run API ([#52437](apache/airflow#52437)) - Add tracking of triggering user to Dag runs ([#51738](apache/airflow#51738)) - Expose DAG parsing duration in the API ([#54752](apache/airflow#54752)) ## New API Endpoints: - Add Human-in-the-Loop (HITL) endpoints for approval workflows ([#52868](apache/airflow#52868), [#53373](apache/airflow#53373), [#53376](apache/airflow#53376), [#53885](apache/airflow#53885), [#53923](apache/airflow#53923), [#54308](apache/airflow#54308), [#54310](apache/airflow#54310), [#54723](apache/airflow#54723), [#54773](apache/airflow#54773), [#55019](apache/airflow#55019), [#55463](apache/airflow#55463), [#55525](apache/airflow#55525), [#55535](apache/airflow#55535), [#55603](apache/airflow#55603), [#55776](apache/airflow#55776)) - Add endpoint to watch dag run until finish ([#51920](apache/airflow#51920)) - Add TI bulk actions endpoint ([#50443](apache/airflow#50443)) - Add Keycloak Refresh Token Endpoint ([#51657](apache/airflow#51657)) ## Deprecations: - Mark `DagDetailsResponse.concurrency` as deprecated ([#55150](apache/airflow#55150)) ## Bug Fixes: - Fix dag import error modal pagination ([#55719](apache/airflow#55719))
This PR adds a feature to Airflow that trigering user is tracked on the Dag run level. So far if you have usages where users trigger manual you needed to find-out which user it was by looking into audit log.
The user is tracked with unix user name when using CLI or airflowctl, in web UI or REST cases the authenticated user is used.
In case a backfill is started via UI the user who started the backfill propagates the runs of Dags.
FYI @clellmann@wolfdn@AutomationDev85