Skip to content

feat: add role fingerprint to system journal#614

Merged
richm merged 1 commit intolinux-system-roles:mainfrom
richm:fingerprint-journal
Apr 22, 2026
Merged

feat: add role fingerprint to system journal#614
richm merged 1 commit intolinux-system-roles:mainfrom
richm:fingerprint-journal

Conversation

@richm
Copy link
Copy Markdown
Contributor

@richm richm commented Apr 16, 2026

Feature: Add role fingerprint to system journal as the first task in the role.

Reason: The journal is often exported to reporting systems making it easy to
tell if the role is being used, and when.

Result: Users can get information in their reporting and log aggregation systems
of role usage.

Summary by Sourcery

Add a custom fingerprinting mechanism that logs role begin and success markers to the system journal for the storage system role.

New Features:

  • Introduce an sr_fingerprint Ansible module to write timestamped fingerprint messages to the system log.
  • Record begin and success fingerprint messages for the storage role execution, including Ansible and OS version metadata.

Tests:

  • Extend default role test playbook to capture start time and verify presence of begin and success fingerprints in the system journal.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 16, 2026

Reviewer's Guide

Introduces a new custom Ansible module sr_fingerprint that logs role usage messages to syslog, wires it into the storage role to emit begin/success fingerprints, and extends the default test to validate these fingerprints via journalctl, while keeping ansible-sanity ignores in sync for supported versions.

Sequence diagram for role execution with sr_fingerprint logging

sequenceDiagram
    actor Operator
    participant AnsibleController
    participant storage_role
    participant sr_fingerprint_module
    participant Syslog

    Operator ->> AnsibleController: Run playbook including storage_role
    AnsibleController ->> storage_role: Execute role tasks

    Note over storage_role: At role start (set_vars.yml)
    storage_role ->> sr_fingerprint_module: sr_message="begin system_role:storage ..."
    sr_fingerprint_module ->> Syslog: log(begin_message_with_timestamp)

    storage_role ->> storage_role: Perform storage configuration tasks

    Note over storage_role: At role end (main.yml)
    storage_role ->> sr_fingerprint_module: sr_message="success system_role:storage ..."
    sr_fingerprint_module ->> Syslog: log(success_message_with_timestamp)

    Syslog -->> Operator: Logs visible via journalctl and exports
Loading

Class diagram for the new sr_fingerprint Ansible module

classDiagram
    class sr_fingerprint_module {
        +run_module()
        +main()
        +_local_iso8601_no_microseconds()
    }

    class AnsibleModule {
    }

    sr_fingerprint_module ..> AnsibleModule : uses
Loading

File-Level Changes

Change Details Files
Add custom sr_fingerprint Ansible module to log structured role fingerprint messages to syslog without changing system state.
  • Create library/sr_fingerprint.py implementing an AnsibleModule that accepts a required sr_message string parameter.
  • Format the final log line as '<sr_message> '.
  • Use module.log to write to syslog while always reporting changed=False and supporting check mode with a descriptive message.
  • Implement a helper _local_iso8601_no_microseconds with fallbacks for older Python versions lacking datetime.timezone.
library/sr_fingerprint.py
Integrate role begin/success fingerprints into the storage role execution flow.
  • Insert a 'Record role begin fingerprint' task early in tasks/set_vars.yml to log a 'begin system_role:storage' message including Ansible version and distribution/version facts.
  • Append a 'Record role success fingerprint' task at the end of tasks/main.yml to log a corresponding 'success system_role:storage' message with the same metadata.
  • Ensure both fingerprint tasks use the sr_fingerprint module and are part of the normal role execution path.
tasks/set_vars.yml
tasks/main.yml
Extend default role test to assert that begin/success fingerprint messages are written to the system journal for the test run.
  • Add a pre-role task to capture the current date/time into __journal_start_time using ansible_facts['date_time'].
  • After running the role, add a shell-based journalctl check that searches logs since __journal_start_time for the expected 'sr_fingerprint.*begin system_role:storage' and 'sr_fingerprint.*success system_role:storage' messages.
  • Filter out noisy ' Invoked with' journal lines and make the test fail with explicit error messages if either fingerprint is missing, while marking the check as not changing state.
tests/tests_default.yml
Maintain Ansible sanity ignore configuration files for multiple Ansible versions.
  • Touch/update .sanity-ansible-ignore-2.x.txt files to ensure they are present and aligned with the addition of the custom library module for the full range of supported Ansible versions.
.sanity-ansible-ignore-2.9.txt
.sanity-ansible-ignore-2.10.txt
.sanity-ansible-ignore-2.11.txt
.sanity-ansible-ignore-2.12.txt
.sanity-ansible-ignore-2.13.txt
.sanity-ansible-ignore-2.14.txt
.sanity-ansible-ignore-2.15.txt
.sanity-ansible-ignore-2.16.txt
.sanity-ansible-ignore-2.17.txt
.sanity-ansible-ignore-2.18.txt
.sanity-ansible-ignore-2.19.txt
.sanity-ansible-ignore-2.20.txt
.sanity-ansible-ignore-2.21.txt
.sanity-ansible-ignore-2.22.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@richm richm marked this pull request as draft April 16, 2026 21:05
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The sr_fingerprint module always reports changed=True, but the role immediately overrides this with changed_when: false; consider making the module itself report changed=False (or configurable via a parameter) so its behavior is consistent and consumers don’t need to override it.
  • In sr_fingerprint.run_module, you might want to validate that sr_message is non-empty/meaningful (e.g., not just whitespace) before logging, to avoid writing accidental empty fingerprints to syslog.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `sr_fingerprint` module always reports `changed=True`, but the role immediately overrides this with `changed_when: false`; consider making the module itself report `changed=False` (or configurable via a parameter) so its behavior is consistent and consumers don’t need to override it.
- In `sr_fingerprint.run_module`, you might want to validate that `sr_message` is non-empty/meaningful (e.g., not just whitespace) before logging, to avoid writing accidental empty fingerprints to syslog.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 0% with 33 lines in your changes missing coverage. Please review.
✅ Project coverage is 10.16%. Comparing base (59fd1c6) to head (4ca81eb).
⚠️ Report is 136 commits behind head on main.

Files with missing lines Patch % Lines
library/sr_fingerprint.py 0.00% 33 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (59fd1c6) and HEAD (4ca81eb). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (59fd1c6) HEAD (4ca81eb)
sanity 1 0
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #614      +/-   ##
==========================================
- Coverage   16.54%   10.16%   -6.39%     
==========================================
  Files           2        9       +7     
  Lines         284     2056    +1772     
  Branches       79        0      -79     
==========================================
+ Hits           47      209     +162     
- Misses        237     1847    +1610     
Flag Coverage Δ
sanity ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@richm richm force-pushed the fingerprint-journal branch from f72d6b5 to 4cc798d Compare April 16, 2026 21:57
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 16, 2026

[citest]

@richm richm force-pushed the fingerprint-journal branch from 4cc798d to 01ba9b2 Compare April 16, 2026 22:16
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 16, 2026

[citest]

@richm richm self-assigned this Apr 16, 2026
Comment thread tasks/main.yml Outdated
---
- name: Record storage role fingerprint in syslog
sr_fingerprint:
sr_message: "system_role:storage"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking about other useful info to be added with the fingerprint.
We can add timestamp in the message.
Also, maybe print Ansible version and platform for simplicity. Yes we can probably script getting this info from sos report content other than this line, but having it on the same line with the role fingerprint would make things easier, WDYT?
Would be interesting to see how many nodes ansible inventory had, I guess we can get this info on managed nodes by counting ansible_play_hosts.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking about other useful info to be added with the fingerprint. We can add timestamp in the message.

This is what the message looks like in the journal:

Apr 17 10:38:55 hostname.domain.com python3.12[5169]: ansible-sr_fingerprint system_role:storage

I guess we could add an ISO 8601 format timestamp since the default doesn't have year or timezone:

Apr 17 10:38:55 hostname.domain.com python3.12[5169]:  ansible-sr_fingerprint system_role:storage 2026-04-17T08:42:40-06:00

Also, maybe print Ansible version and platform for simplicity. Yes we can probably script getting this info from sos report content other than this line, but having it on the same line with the role fingerprint would make things easier, WDYT? Would be interesting to see how many nodes ansible inventory had, I guess we can get this info on managed nodes by counting ansible_play_hosts.

ok - I'll add ansible version and os-major.minor

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

problem with adding platform: {{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }} - since this runs as the first task in the role, this runs before fact gathering - so these facts are not available - if we add the fingerprint after fact gathering, we don't get the benefit of having the fingerprint before everything else

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the output with timestamp and ansible version:

Apr 17 11:33:12 hostname.domain.com python3.12[4732]: ansible-sr_fingerprint system_role:storage ansible_version=2.20.5rc1 2026-04-17T11:33:12-04:00

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

problem with adding platform: {{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }} - since this runs as the first task in the role, this runs before fact gathering - so these facts are not available - if we add the fingerprint after fact gathering, we don't get the benefit of having the fingerprint before everything else

To me, adding the fingerprint as the first thing is not really useful because it shows all attempts to run the role. If someone runs a role, fails, and never tries sysroles again, we still count them as our users.
I'd say let's add the fingerprint at the very end of a successful role run.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add fingerprint at the very beginning?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add fingerprint at the very beginning?

I thought it would be useful to know any and all role invocations at the very beginning, to see exactly when someone invoked the role.

Pros:

  • know when someone invoked the role - can easily correlate this with other logs
  • have a record of an attempt to invoke the role, even if the role fails or errors out

Cons:

  • no facts available until after fact gathering - so not much available fingerprint metadata
  • don't know if the role invocation was successful

I suppose we could combine the approaches - have a fingerprint at the beginning and at the end - the problem of doing it at the end is if you want to emit the fingerprint upon success or failure or error with the role result - yes, we could refactor the roles so that we run the role in a block/rescue/always - but there are some issues:

  • if you use a rescue, you need to "re-raise" the error, but you cannot reconstruct the exact same ansible_failed_result to re-raise
  • if you only use an always, I guess we could set a variable as the last task in the block to indicate that the role completed successfully, so we could report success or failure/error, but we couldn't report the exact error

Copy link
Copy Markdown
Contributor

@spetrosi spetrosi Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, well if we do two fingerprints for init and success, the absence of the success fingerprint indicates that the role failed. So no need to introduce rescue blocks everywhere.
Maybe still include the init fingerprint after collecting facts to provide platform?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, well if we do two fingerprints for init and success, the absence of the success fingerprint indicates that the role failed. So no need to introduce rescue blocks everywhere. Maybe still include the init fingerprint after collecting facts to provide platform?

ok - I can add the init fingerprint just after fact gathering, and add the success fingerprint as the last task in tasks/main.yml

@richm richm force-pushed the fingerprint-journal branch from 01ba9b2 to 079d844 Compare April 17, 2026 15:42
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 17, 2026

[citest]

@richm richm force-pushed the fingerprint-journal branch from 079d844 to 800953f Compare April 17, 2026 22:14
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 17, 2026

[citest]

@richm richm force-pushed the fingerprint-journal branch from 800953f to 5699b5b Compare April 17, 2026 23:38
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 17, 2026

[citest]

@richm richm force-pushed the fingerprint-journal branch from 5699b5b to 2d2c283 Compare April 18, 2026 00:54
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 18, 2026

[citest]

@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 18, 2026

[citest_bad]

@richm richm force-pushed the fingerprint-journal branch from 2d2c283 to 7c55be8 Compare April 20, 2026 15:03
@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 20, 2026

@spetrosi new implementation - here is what gets logged:

Apr 20 10:59:43 hostname.domain.com python3.12[5596]: ansible-sr_fingerprint fingerprint begin system_role:storage ansible_version=2.20.5rc1 CentOS-10 2026-04-20T10:59:43-04:00
Apr 20 11:00:02 hostname.domain.com python3.12[7666]: ansible-sr_fingerprint fingerprint success system_role:storage ansible_version=2.20.5rc1 CentOS-10 2026-04-20T11:00:02-04:00

spetrosi
spetrosi previously approved these changes Apr 20, 2026
Copy link
Copy Markdown
Contributor

@spetrosi spetrosi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fingerprint looks very good!

@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 20, 2026

[citest]

@richm
Copy link
Copy Markdown
Contributor Author

richm commented Apr 21, 2026

[citest]

Feature: Add role fingerprint to system journal as the first task in the role.

Reason: The journal is often exported to reporting systems making it easy to
tell if the role is being used, and when.

Result: Users can get information in their reporting and log aggregation systems
of role usage.
@richm richm force-pushed the fingerprint-journal branch from f27c17c to 4ca81eb Compare April 22, 2026 15:15
@richm richm marked this pull request as ready for review April 22, 2026 16:06
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The begin/success fingerprint messages duplicate the same ansible_version and distribution formatting logic in two tasks; consider factoring this into a variable or helper so the format stays consistent if you ever need to change it.
  • The fingerprint messages hardcode system_role:storage; if this pattern is intended to be reused in other roles, it might be worth deriving the role identifier from a variable so the module use stays generic.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The begin/success fingerprint messages duplicate the same `ansible_version` and distribution formatting logic in two tasks; consider factoring this into a variable or helper so the format stays consistent if you ever need to change it.
- The fingerprint messages hardcode `system_role:storage`; if this pattern is intended to be reused in other roles, it might be worth deriving the role identifier from a variable so the module use stays generic.

## Individual Comments

### Comment 1
<location path="library/sr_fingerprint.py" line_range="80" />
<code_context>
+        sr_message=dict(type="str", required=True),
+    )
+
+    module = AnsibleModule(
+        argument_spec=module_args,
+        supports_check_mode=True,
+    )
+
+    log_message = "%s %s" % (
+        module.params["sr_message"],
+        _local_iso8601_no_microseconds(),
+    )
+
+    if module.check_mode:
+        module.exit_json(
+            changed=False,
+            message="Check mode: message not logged - [%s]" % log_message,
+        )
+
+    module.log(log_message)
+
+    # we don't actually change anything, so we're not changed - writing a log message
+    # is not considered a change
+    # also, we don't want to report changed every time the role runs
+    module.exit_json(changed=False)
+
+
</code_context>
<issue_to_address>
**suggestion:** Include the logged message in the module result to aid debugging and play recap visibility.

In the non-check path, the module currently calls `exit_json(changed=False)` with no extra data. Consider adding the final `log_message` (or at least `sr_message`) to the result, e.g. `module.exit_json(changed=False, logged_message=log_message)`, so callbacks and play recap can show what was logged without requiring syslog access.

```suggestion
    module.exit_json(changed=False, logged_message=log_message)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread library/sr_fingerprint.py
# we don't actually change anything, so we're not changed - writing a log message
# is not considered a change
# also, we don't want to report changed every time the role runs
module.exit_json(changed=False)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Include the logged message in the module result to aid debugging and play recap visibility.

In the non-check path, the module currently calls exit_json(changed=False) with no extra data. Consider adding the final log_message (or at least sr_message) to the result, e.g. module.exit_json(changed=False, logged_message=log_message), so callbacks and play recap can show what was logged without requiring syslog access.

Suggested change
module.exit_json(changed=False)
module.exit_json(changed=False, logged_message=log_message)

@richm richm merged commit 6d1266c into linux-system-roles:main Apr 22, 2026
49 of 54 checks passed
@richm richm deleted the fingerprint-journal branch April 22, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants