Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .changesets/add-helpers-for-each-kind-of-parameters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
bump: minor
type: add
---

Add the `set_request_payload`, `set_request_query_parameters` and `set_function_parameters` helpers. Each one reports a kind of parameters that collector mode keeps apart, so the option that filters that kind, and the one that suppresses it, apply to what you report:

```python
from appsignal import set_function_parameters

set_function_parameters({"user_id": 123})
```

In collector mode, the `set_params` helper is now deprecated, and it reports the request payload. It does not say which kind of parameters it is given, so use `set_request_payload`, `set_request_query_parameters` or `set_function_parameters` instead. AppSignal warns the first time it is used.

In agent mode there is one place to report parameters, so all four helpers report to it, the last one called is the one that takes effect, and `set_params` is not deprecated.
10 changes: 10 additions & 0 deletions .changesets/deprecate-the-params-options-in-collector-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
bump: patch
type: change
---

The `filter_parameters` and `send_params` configuration options are deprecated in collector mode. Use `filter_request_payload`, `filter_function_parameters` and `filter_request_query_parameters` to filter different kinds of parameters, and `send_request_payload`, `send_request_query_parameters` and `send_function_parameters` to choose which kinds of parameters to report.

AppSignal warns about the deprecated options at startup, and names the value to set for each option that replaces them.

In agent mode, `filter_parameters` and `send_params` still apply to every kind of parameter, and the new options have no effect.
8 changes: 8 additions & 0 deletions .changesets/derive-the-collector-mode-parameter-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
bump: patch
type: change
---

In collector mode, the `filter_request_payload`, `filter_function_parameters` and `filter_request_query_parameters` configuration options now fall back to the value of `filter_parameters`, and the `send_request_payload`, `send_request_query_parameters` and `send_function_parameters` options fall back to the value of `send_params`. An application that filtered parameters or turned parameter reporting off keeps doing so after it switches to a collector, without having to set the new options.

Setting one of the new options still overrides the value that would be derived for it.
8 changes: 8 additions & 0 deletions .changesets/name-a-header-the-way-the-convention-does.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
bump: patch
type: fix
---

Report a request or response header whose name is written with capital letters or underscores in the `request_headers` or `response_headers` configuration option, such as `Content-Type` or `content_type`. The collector matches these names against the ones it receives the headers under, which follow the OpenTelemetry semantic convention: the header's own name, lowercased, with its dashes kept. A name written any other way matched nothing, so the header was left out.

The `set_header` helper names a header the same way when a collector is in use.
6 changes: 6 additions & 0 deletions .changesets/name-the-source-of-each-config-option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
bump: patch
type: change
---

The `appsignal diagnose` report now names where each configuration option's value came from. An option set from more than one source lists the value from each source.
8 changes: 8 additions & 0 deletions .changesets/report-each-kind-of-parameters-separately.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
bump: patch
type: change
---

In collector mode, the Django and Flask instrumentation now reports a request's query string as query parameters rather than as a request payload. So `filter_request_query_parameters` and `send_request_query_parameters` apply to a query string, and `filter_request_payload` and `send_request_payload` apply to a Django request's body.

In agent mode, a Flask application's query parameters are now reported on their own, rather than nested under an `args` key.
6 changes: 6 additions & 0 deletions .changesets/report-the-configured-response-headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
bump: patch
type: add
---

Report the response headers listed in the `response_headers` configuration option when a collector is used.
6 changes: 6 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from appsignal.heartbeat import _heartbeat_class_warning, _heartbeat_helper_warning
from appsignal.internal_logger import _reset_logger
from appsignal.opentelemetry import METRICS_PREFERRED_TEMPORALITY, _providers
from appsignal.tracing import _set_params_warning


@pytest.fixture(scope="function", autouse=True)
Expand Down Expand Up @@ -116,6 +117,11 @@ def reset_global_client() -> Any:
_reset_client()


@pytest.fixture(scope="function", autouse=True)
def reset_set_params_warning() -> Any:
_set_params_warning.reset()


@pytest.fixture(scope="function", autouse=True)
def reset_checkins() -> Any:
yield
Expand Down
6 changes: 6 additions & 0 deletions src/appsignal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
set_category,
set_custom_data,
set_error,
set_function_parameters,
set_header,
set_name,
set_namespace,
set_params,
set_request_payload,
set_request_query_parameters,
set_root_name,
set_session_data,
set_sql_body,
Expand All @@ -38,11 +41,14 @@
"set_category",
"set_custom_data",
"set_error",
"set_function_parameters",
"set_gauge",
"set_header",
"set_name",
"set_namespace",
"set_params",
"set_request_payload",
"set_request_query_parameters",
"set_root_name",
"set_session_data",
"set_sql_body",
Expand Down
14 changes: 14 additions & 0 deletions src/appsignal/_headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from __future__ import annotations


# The OpenTelemetry SDK writes header attribute names with underscores, where
# the semantic conventions the collector compares against use dashes.
def normalize_header(name: str) -> str:
return name.lower().replace("_", "-")


def normalize_headers(names: list[str] | None) -> list[str] | None:
if names is None:
return None

return [normalize_header(name) for name in names]
26 changes: 26 additions & 0 deletions src/appsignal/_once.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import annotations

from typing import Any, Callable

from . import internal_logger as logger


class _Once:
def __init__(self, func: Callable[..., None], *args: Any, **kwargs: Any) -> None:
self.called = False
self.func = func
self.args = args
self.kwargs = kwargs

def __call__(self) -> None:
if not self.called:
self.called = True
self.func(*self.args, **self.kwargs)

def reset(self) -> None:
self.called = False


def _warn_logger_and_stdout(msg: str) -> None:
logger.warning(msg)
print(f"appsignal WARNING: {msg}")
25 changes: 22 additions & 3 deletions src/appsignal/cli/diagnose.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
from argparse import ArgumentParser
from pathlib import Path
from sys import stderr
from typing import Any
from typing import Any, cast

from ..__about__ import __version__
from ..agent import Agent
from ..config import Config
from ..config import SOURCE_ORDER, Config
from ..push_api_key_validator import PushApiKeyValidator
from ..transmitter import transmit
from .command import AppsignalCLICommand
Expand Down Expand Up @@ -311,12 +311,31 @@ def _configuration_information(self) -> None:
print("Configuration")

for key in self.config.options:
print(f" {key}: {self.config.options[key]!r}") # type: ignore
value = self.config.options[key] # type: ignore
print(f" {key}: {value!r}{self._config_sources_label(key)}")

print()
print("Read more about how the diagnose config output is rendered")
print("https://docs.appsignal.com/python/command-line/diagnose.html")

def _config_sources_label(self, option: str) -> str:
sources = cast(dict, self.config.sources)
names = [name for name in SOURCE_ORDER if option in sources[name]]

if names == ["default"]:
return ""

if len(names) == 1:
return f" (Loaded from: {names[0]})"

width = max(len(name) for name in names) + 1
lines = ["", " Sources:"]
for name in names:
label = f"{name}:".ljust(width)
lines.append(f" {label} {sources[name][option]!r}")

return "\n".join(lines)

def _validation_information(self) -> None:
validation_report: Any = self.report["validation"]
print("Validation")
Expand Down
Loading
Loading