Skip to content

Detect the revision, hostname and platform in the package - #277

Merged
unflxw merged 4 commits into
send-app-path-and-ignore-logsfrom
port-agent-autodetection
Aug 27, 2026
Merged

Detect the revision, hostname and platform in the package#277
unflxw merged 4 commits into
send-app-path-and-ignore-logsfrom
port-agent-autodetection

Conversation

@unflxw

@unflxw unflxw commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #271.
Fixes #272.
Fixes #274.

Stacked on #276.

Detect the revision from the platform

The agent reads these same variables, but only for the data it reports
itself. In collector mode the package puts the revision in a resource
attribute instead, and the collector cannot read it from the
environment, because it runs as its own process and usually on another
host.

Prefer the dyno name for the hostname

The agent falls back to the dyno name when it detects the hostname, but
the package's value reaches it first as _APPSIGNAL_HOSTNAME, so that
step never ran. In collector mode there is nothing to fall back on at
all, because the collector runs as its own process and usually on
another host.

Detect the platform and send it

The agent detects the platform the same way, but only for the data it
reports itself. In collector mode the package has to put it in a
resource attribute, and the collector cannot detect it, because
DOKKU_ROOT and DYNO are set in the application's environment while
the collector runs as its own process, usually on another host.

There is no config option for the platform. The detected value reaches
the agent through the private environment variable that its own
detection already reads first.

Keep detected values when an option is None

The options passed to the client merge last, so a None among them
replaces what the system source detected: the app path, the hostname,
the revision and the platform. A None carries no value, so it now leaves
those alone. It still overrides a default, which is how
request_headers=None turns off request header collection.

The unreleased changeset for reporting unknown when the host name is
set to None goes with it, because that case now reports the detected
host name instead.

@backlog-helper

backlog-helper Bot commented Aug 25, 2026

Copy link
Copy Markdown

✔️ All good!

New issue guide | Backlog management | Rules | Feedback

Comment thread .changesets/detect-the-platform.md Outdated
type: change
---

On Heroku, report the name of the dyno as the hostname. Before, the hostname of the container that the dyno runs in was reported, so applications running on Heroku will see their data reported under a new host name.

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.

Suggested change
On Heroku, report the name of the dyno as the hostname. Before, the hostname of the container that the dyno runs in was reported, so applications running on Heroku will see their data reported under a new host name.
When running in collector mode on Heroku, report the name of the dyno as the hostname. Before, the hostname of the container that the dyno runs in was reported, so applications running on Heroku in collector mode will see their data reported under a new host name.

(The agent mode logic already did this, right?)

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 left this one as it was, because agent mode did not already do this.

The package always sets a hostname, from HOSTNAME or socket.gethostname(), and passes it to the agent as _APPSIGNAL_HOSTNAME. The agent reads that variable as the first step of determine_hostname, before its own DYNO fallback. So on Heroku the agent received the container hostname from the package, and never reached the step that would have reported the dyno name.

That is why the changeset is not scoped to collector mode. Applications on Heroku will see a new host name in both modes.

@unflxw
unflxw force-pushed the send-app-path-and-ignore-logs branch from b5dda91 to 754e0d3 Compare August 25, 2026 16:08
@unflxw
unflxw force-pushed the port-agent-autodetection branch from 8a91b77 to 0ee996d Compare August 25, 2026 16:08
@unflxw
unflxw force-pushed the send-app-path-and-ignore-logs branch from 754e0d3 to bb004b7 Compare August 25, 2026 16:17
@unflxw
unflxw force-pushed the port-agent-autodetection branch from 0ee996d to 93e3e75 Compare August 25, 2026 16:17
@unflxw unflxw added the enhancement An improvement to an existing feature. label Aug 25, 2026
@unflxw
unflxw requested a lite review from Copilot August 25, 2026 16:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This pull request ports parts of the agent’s environment-based autodetection into the Python package so collector mode can report revision/hostname/platform correctly (and avoids None options wiping detected values).

Changes:

  • Add revision autodetection fallback chain (Heroku/Render/Kamal/Scalingo) and platform autodetection (Dokku/Heroku) to Config.load_from_system.
  • Prefer the Heroku dyno name (DYNO) over container hostname for hostname detection.
  • Prevent None passed via initializer options from overriding system-detected values; propagate platform via private env and OpenTelemetry resource attributes; expand tests and changesets accordingly.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/appsignal/config.py Adds platform + revision detection and filters initializer None overrides against system-detected values; exports _APPSIGNAL_PLATFORM.
src/appsignal/opentelemetry.py Adds appsignal.config.platform attribute to the OpenTelemetry Resource.
tests/test_config.py Adds coverage for hostname/dyno preference, revision/platform detection, and None override behavior; updates existing expectations.
.changesets/report-host-name-when-set-to-none.md Removes now-obsoleted changeset due to updated None handling behavior.
.changesets/prefer-the-dyno-name-for-the-hostname.md Documents the hostname behavior change for Heroku.
.changesets/keep-detected-values-when-an-option-is-none.md Documents the new None-override behavior.
.changesets/detect-the-revision-from-the-platform.md Documents revision autodetection via platform-provided environment variables.
Suppressed comments (1)

tests/test_config.py:141

  • The revision tests (e.g. test_system_source_revision_reads_variables_in_order) assume no higher-priority revision env vars are already present (like HEROKU_SLUG_COMMIT or APP_REVISION). To avoid environment-dependent failures, explicitly pop all PLATFORM_REVISION_ENVIRONMENT_VARIABLES and APP_REVISION before setting the variables under test.
def test_system_source_revision_reads_variables_in_order():
    os.environ["RENDER_GIT_COMMIT"] = "from-render"
    os.environ["KAMAL_VERSION"] = "from-kamal"
    config = Config()

    assert config.option("revision") == "from-render"


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


Replies from @unflxw, added with copilot-loop. Copilot's review above is unchanged.

tests/test_config.py:141 — Addressed. tests/test_config.py now has an autouse fixture that clears every environment variable the system source reads, including APP_REVISION and the four platform revision variables, so these tests no longer depend on what happens to be set where they run.

Comment thread src/appsignal/config.py Outdated
Comment thread src/appsignal/opentelemetry.py
Comment thread tests/test_config.py
Comment thread tests/test_config.py
Comment thread .changesets/keep-detected-values-when-an-option-is-none.md Outdated
@unflxw
unflxw force-pushed the send-app-path-and-ignore-logs branch from bb004b7 to 723fc30 Compare August 25, 2026 16:30
unflxw added 4 commits August 25, 2026 18:30
The agent reads these same variables, but only for the data it reports
itself. In collector mode the package puts the revision in a resource
attribute instead, and the collector cannot read it from the
environment, because it runs as its own process and usually on another
host.
The agent falls back to the dyno name when it detects the hostname, but
the package's value reaches it first as _APPSIGNAL_HOSTNAME, so that
step never ran. In collector mode there is nothing to fall back on at
all, because the collector runs as its own process and usually on
another host.
The agent detects the platform the same way, but only for the data it
reports itself. In collector mode the package has to put it in a
resource attribute, and the collector cannot detect it, because
DOKKU_ROOT and DYNO are set in the application's environment while the
collector runs as its own process, usually on another host.

There is no config option for the platform. The detected value reaches
the agent through the private environment variable that its own
detection already reads first.
The options passed to the client merge last, so a None among them
replaces what the system source detected: the app path, the hostname,
the revision and the platform. A None carries no value, so it now leaves
those alone. It still overrides a default, which is how
`request_headers=None` turns off request header collection.

The unreleased changeset for reporting `unknown` when the host name is
set to `None` goes with it, because that case now reports the detected
host name instead.
@unflxw
unflxw force-pushed the port-agent-autodetection branch from 93e3e75 to a5d153f Compare August 25, 2026 16:31
@unflxw
unflxw requested a lite review from Copilot August 25, 2026 16:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Comment thread tests/test_config.py
Comment thread tests/test_config.py
Comment thread src/appsignal/config.py
@unflxw
unflxw marked this pull request as ready for review August 25, 2026 18:48
@unflxw
unflxw requested a review from lipskis August 25, 2026 18:48
@unflxw
unflxw merged commit 29b3ff1 into send-app-path-and-ignore-logs Aug 27, 2026
12 checks passed
unflxw added a commit that referenced this pull request Aug 27, 2026
* Send the app path to the collector

The processor strips the app path from each backtrace line, and decides
whether a frame belongs to the application by checking that its path is
relative. Without the app path, every frame keeps its absolute path, so
no line is recognized as the application's own.

* Add the ignore_logs option

Collector mode sends log records, and the collector filters out the ones
matching this option when the resource carries it. The package had no
option for it because agent mode sends no logs at all, which is also why
it is not passed on to the agent.

* Detect the revision, hostname and platform in the package (#277)

* Detect the revision from the platform

The agent reads these same variables, but only for the data it reports
itself. In collector mode the package puts the revision in a resource
attribute instead, and the collector cannot read it from the
environment, because it runs as its own process and usually on another
host.

* Prefer the dyno name for the hostname

The agent falls back to the dyno name when it detects the hostname, but
the package's value reaches it first as _APPSIGNAL_HOSTNAME, so that
step never ran. In collector mode there is nothing to fall back on at
all, because the collector runs as its own process and usually on
another host.

* Detect the platform and send it

The agent detects the platform the same way, but only for the data it
reports itself. In collector mode the package has to put it in a
resource attribute, and the collector cannot detect it, because
DOKKU_ROOT and DYNO are set in the application's environment while the
collector runs as its own process, usually on another host.

There is no config option for the platform. The detected value reaches
the agent through the private environment variable that its own
detection already reads first.

* Keep detected values when an option is None

The options passed to the client merge last, so a None among them
replaces what the system source detected: the app path, the hostname,
the revision and the platform. A None carries no value, so it now leaves
those alone. It still overrides a default, which is how
`request_headers=None` turns off request header collection.

The unreleased changeset for reporting `unknown` when the host name is
set to `None` goes with it, because that case now reports the detected
host name instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement An improvement to an existing feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants