Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e22a0d6
Add microsoft opentelemetry distro configuration
JacksonWeber Apr 1, 2026
732c861
Add integration tests for microsoft distro configuration
JacksonWeber Apr 1, 2026
505244e
Scope PR to Azure Monitor configuration only
JacksonWeber Apr 1, 2026
a8284a8
Simplify to pure Azure Monitor delegation
JacksonWeber Apr 1, 2026
912a248
Remove unused constants, utils, and re-exports
JacksonWeber Apr 1, 2026
d6c7d4c
Update changelog to reflect Azure Monitor only scope
JacksonWeber Apr 1, 2026
2f0c66b
Remove duplicated configuration logic from microsoft distro
JacksonWeber Apr 2, 2026
56df7a6
Do not warn on no connection string, as this could be intentional if …
JacksonWeber Apr 3, 2026
e5024d2
Move files for import support.
JacksonWeber Apr 3, 2026
4bc99d7
Update pyproject.toml
JacksonWeber Apr 3, 2026
9b0591a
Final cleanup based on PR comments.
JacksonWeber Apr 3, 2026
272c019
Merge origin/main, resolve pyproject.toml testpaths conflict
JacksonWeber Apr 3, 2026
350711d
Fix CI: remove hard azure-monitor imports, fix lint issues
JacksonWeber Apr 3, 2026
cb806ba
Add opentelemetry-sdk to test deps, include microsoft/tests in CI lint
JacksonWeber Apr 3, 2026
566effe
Rename enable_* kwargs to disable_* per reviewer feedback
JacksonWeber Apr 3, 2026
6bf63f3
Fix CI: mock azure modules via sys.modules, fix pylint config
JacksonWeber Apr 3, 2026
a99504d
Move remap_disable_to_enable to _utils/configurations.py
JacksonWeber Apr 3, 2026
d44c0e6
Move tests into tests/, remove microsoft/ directory
JacksonWeber Apr 3, 2026
795842d
Document all configure_azure_monitor kwargs in docstring and README
JacksonWeber Apr 3, 2026
72b5a6f
Use connection_string directly, remove azure_monitor_connection_strin…
JacksonWeber Apr 3, 2026
69508c0
Default disable_azure_monitor_exporter to False, simplify logic
JacksonWeber Apr 3, 2026
c7316bd
Remove Azure-specific sampling kwargs from documented API
JacksonWeber Apr 3, 2026
e6354e2
Document supported OTel samplers and env var configuration
JacksonWeber Apr 3, 2026
0354385
Fix black formatting for CI compatibility, pin black version
JacksonWeber Apr 3, 2026
7776f71
Update line-length to 120 to match upstream main
JacksonWeber Apr 3, 2026
cd1f8ea
Address Hector's review: rename to use_microsoft_opentelemetry, remov…
JacksonWeber Apr 5, 2026
f8d1f89
Fix CI: lazy import for azure monitor, Black formatting on src/azure/
JacksonWeber Apr 5, 2026
7e7aa9e
Fix lint: exclude vendored src/azure/ from pylint, remove unused import
JacksonWeber Apr 5, 2026
8de4175
Restructure namespace from azure.monitor to microsoft.azureMonitor
JacksonWeber Apr 6, 2026
bd89d45
Add Azure Monitor tests under tests/azureMonitor/
JacksonWeber Apr 6, 2026
bbfdea1
Prefix Azure Monitor kwargs with azure_monitor_, rename disable to en…
JacksonWeber Apr 6, 2026
9eef006
Update docs: CHANGELOG, PLANNING, and README link fixes
JacksonWeber Apr 6, 2026
6ac84d1
Merge remote-tracking branch 'upstream/main' into jacksonweber/add-ms…
JacksonWeber Apr 6, 2026
aa32760
Merge remote-tracking branch 'upstream/main' into jacksonweber/add-ms…
JacksonWeber Apr 6, 2026
142ce50
Merge branch 'jacksonweber/add-ms-distro-config' of https://github.co…
JacksonWeber Apr 6, 2026
8c0a1b7
Update pyproject.toml
JacksonWeber Apr 6, 2026
0789ad6
Fix CI: configure mypy namespace packages, add py.typed marker, type …
JacksonWeber Apr 6, 2026
97d23af
Exclude src/microsoft/azureMonitor from pyright
JacksonWeber Apr 6, 2026
6b49694
Add proper deps, use per-module linter overrides instead of exclusions
JacksonWeber Apr 6, 2026
cc1f580
Remove empty src/microsoft/opentelemetry/_utils/ directory
JacksonWeber Apr 6, 2026
2bfe24b
Fix mypy: add import overrides for azure.core and opentelemetry.instr…
JacksonWeber Apr 6, 2026
34efa48
Fix pyright: ignore azureMonitor source for type checking
JacksonWeber Apr 6, 2026
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@

### Other Changes
- Added `azure-monitor-opentelemetry` package source for Azure Monitor OpenTelemetry distro integration.
- Added `microsoft.opentelemetry` distro configuration with `use_microsoft_opentelemetry()` entry point for Azure Monitor.
- Added `azure_monitor_enable_live_metrics` and `azure_monitor_enable_performance_counters` kwargs passed directly to `configure_azure_monitor()`.
- Renamed `disable_azure_monitor_exporter` kwarg to `enable_azure_monitor` (inverted, defaults to True).
- Prefixed Azure Monitor-specific kwargs with `azure_monitor_` (e.g. `azure_monitor_connection_string`, `azure_monitor_exporter_credential`).
- Project metadata, license, and documentation
69 changes: 57 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,67 @@ The target package should reduce fragmented setup across multiple observability
Intended API shape:

```python
from microsoft.opentelemetry import configure_microsoft_opentelemetry
from microsoft.opentelemetry import use_microsoft_opentelemetry

configure_microsoft_opentelemetry(
use_microsoft_opentelemetry(
azure_monitor_connection_string="InstrumentationKey=...;IngestionEndpoint=...",
enable_otlp_export=True,
enable_genai_openai_instrumentation=True,
)
```

### Available Configuration Options

| Keyword argument | Type | Default | Description |
|---|---|---|---|
| `enable_azure_monitor` | `bool` | `True` | Enable Azure Monitor export. |
| `azure_monitor_connection_string` | `str` | `None` | Connection string for Application Insights. Also read from `APPLICATIONINSIGHTS_CONNECTION_STRING` env var. |
| `azure_monitor_exporter_credential` | `TokenCredential` | `None` | Azure AD token credential for authentication. |
| `azure_monitor_enable_live_metrics` | `bool` | `True` | Enable live metrics collection. |
| `azure_monitor_enable_performance_counters` | `bool` | `True` | Enable performance counter collection. |
| `azure_monitor_exporter_disable_offline_storage` | `bool` | `False` | Disable offline retry storage for failed telemetry. |
| `azure_monitor_exporter_storage_directory` | `str` | `None` | Custom directory for offline telemetry storage. |
| `azure_monitor_browser_sdk_loader_config` | `dict` | `None` | Browser SDK loader configuration. |
| `disable_logging` | `bool` | `False` | Disable the logging pipeline. |
Comment thread
JacksonWeber marked this conversation as resolved.
| `disable_tracing` | `bool` | `False` | Disable the tracing pipeline. |
| `disable_metrics` | `bool` | `False` | Disable the metrics pipeline. |
| `resource` | `Resource` | auto | OpenTelemetry Resource. |
| `span_processors` | `list` | `[]` | Additional span processors. |
| `log_record_processors` | `list` | `[]` | Additional log record processors. |
| `metric_readers` | `list` | `[]` | Additional metric readers. |
| `views` | `list` | `[]` | Metric views. |
| `logger_name` | `str` | `None` | Logger name for log collection. |
| `logging_formatter` | `Formatter` | `None` | Formatter for collected logs. |
| `instrumentation_options` | `dict` | `None` | Per-library instrumentation enable/disable options. |
| `enable_trace_based_sampling_for_logs` | `bool` | `False` | Enable trace-based sampling for logs. |

### Sampling Configuration

Sampling is configured via standard OpenTelemetry environment variables:

| Environment variable | Description |
|---|---|
| `OTEL_TRACES_SAMPLER` | Sampler type to use (see supported values below). |
| `OTEL_TRACES_SAMPLER_ARG` | Argument for the sampler (e.g. sample ratio or traces per second). |

**Supported sampler values for `OTEL_TRACES_SAMPLER`:**

| Value | Description |
|---|---|
| `always_on` | Sample every trace. |
| `always_off` | Drop every trace. |
| `trace_id_ratio` | Sample a fixed percentage based on trace ID. Set ratio with `OTEL_TRACES_SAMPLER_ARG` (0–1). |
| `parentbased_always_on` | Parent-based, defaults to always on. |
| `parentbased_always_off` | Parent-based, defaults to always off. |
| `parentbased_trace_id_ratio` | Parent-based with trace ID ratio fallback. |
| `microsoft.fixed_percentage` | Azure Monitor fixed-percentage sampler. Set ratio with `OTEL_TRACES_SAMPLER_ARG` (0–1). |
| `microsoft.rate_limited` | Azure Monitor rate-limited sampler. Set target with `OTEL_TRACES_SAMPLER_ARG` (traces per second, default 5). |

**Example:**

```bash
export OTEL_TRACES_SAMPLER=trace_id_ratio
export OTEL_TRACES_SAMPLER_ARG=0.1
```

## Planned Scope

- Azure Monitor exporter support
Expand Down Expand Up @@ -56,13 +108,6 @@ The POC also describes this execution model:
6. Enable Microsoft-specific observability instrumentations
7. Enable GenAI contrib instrumentations

## Current Repository Layout

- `src/` package source
- `tests/` test suite
- `pyproject.toml` project metadata and dependencies
- `PLANNING.md` implementation plan and open questions

## Development

Create an environment and install the project with test dependencies:
Expand Down Expand Up @@ -93,4 +138,4 @@ This project may contain trademarks or logos for projects, products, or services

## License

[MIT](LICENSE)
[MIT](LICENSE)
41 changes: 40 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ version = "0.1.0"
description = "Minimal template for the Microsoft OpenTelemetry distro for Python"
readme = "README.md"
requires-python = ">=3.10"
dependencies = []
dependencies = [
"opentelemetry-sdk>=1.0",
"opentelemetry-api>=1.0",
"opentelemetry-instrumentation>=0.40b0",
"azure-monitor-opentelemetry-exporter>=1.0.0b21",
"azure-core>=1.28.0",
]

[project.optional-dependencies]
test = [
Expand All @@ -27,13 +33,15 @@ package-dir = {"" = "src"}

[tool.setuptools.packages.find]
where = ["src"]
namespaces = true

[tool.black]
line-length = 120
Comment thread
JacksonWeber marked this conversation as resolved.
target-version = ["py310"]

[tool.pylint.main]
py-version = "3.10"
ignore-paths = ["tests/azureMonitor"]

[tool.pylint.format]
max-line-length = 120
Comment thread
JacksonWeber marked this conversation as resolved.
Expand All @@ -42,17 +50,48 @@ max-line-length = 120
disable = [
"missing-function-docstring",
"missing-module-docstring",
"missing-class-docstring",
"import-outside-toplevel",
"import-error",
"no-name-in-module",
"duplicate-code",
"too-few-public-methods",
"too-many-arguments",
"too-many-positional-arguments",
"too-many-locals",
"wrong-import-order",
"ungrouped-imports",
"unknown-option-value",
"fixme",
"invalid-name",
]

[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
namespace_packages = true
explicit_package_bases = true
mypy_path = "src"

[[tool.mypy.overrides]]
module = "microsoft.azureMonitor.*"
disallow_untyped_defs = false
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = [
"django.*",
"azure.core.*",
"opentelemetry.instrumentation.*",
]
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]

[tool.pyright]
pythonVersion = "3.10"
typeCheckingMode = "basic"
ignore = ["src/microsoft/azureMonitor", "tests/azureMonitor"]
4 changes: 2 additions & 2 deletions samples/langchain/sample_opentelemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

configure_azure_monitor() # Replace with the opentelemetry distro

# configure_microsoft_opentelemetry(
# connection_string="InstrumentationKey=...",
# use_microsoft_opentelemetry(
# azure_monitor_connection_string="InstrumentationKey=...",
# enable_genai_langchain=True,
# )

Expand Down
18 changes: 18 additions & 0 deletions src/microsoft/azureMonitor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License in the project root for
# license information.
# -------------------------------------------------------------------------

# Extend path so the exporter subpackage (azure-monitor-opentelemetry-exporter)
# is discoverable when this package is installed in editable/development mode.
__path__ = __import__("pkgutil").extend_path(__path__, __name__)

from microsoft.azureMonitor._configure import configure_azure_monitor

from ._version import VERSION

__all__ = [
"configure_azure_monitor",
]
__version__ = VERSION
5 changes: 5 additions & 0 deletions src/microsoft/azureMonitor/_autoinstrumentation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License in the project root for
# license information.
# -------------------------------------------------------------------------
69 changes: 69 additions & 0 deletions src/microsoft/azureMonitor/_autoinstrumentation/configurator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License in the project root for
# license information.
# --------------------------------------------------------------------------


from os import environ
from warnings import warn

from opentelemetry.environment_variables import (
OTEL_LOGS_EXPORTER,
OTEL_METRICS_EXPORTER,
OTEL_TRACES_EXPORTER,
)
from opentelemetry.sdk._configuration import _OTelSDKConfigurator

from azure.monitor.opentelemetry.exporter import ( # pylint: disable=import-error,no-name-in-module
ApplicationInsightsSampler,
)
from azure.monitor.opentelemetry.exporter._utils import ( # pylint: disable=import-error,no-name-in-module
_is_attach_enabled,
)
from microsoft.azureMonitor._constants import (
_PREVIEW_ENTRY_POINT_WARNING,
LOG_EXPORTER_NAMES_ARG,
METRIC_EXPORTER_NAMES_ARG,
SAMPLER_ARG,
TRACE_EXPORTER_NAMES_ARG,
)
from microsoft.azureMonitor._diagnostics.diagnostic_logging import (
AzureDiagnosticLogging,
_ATTACH_FAILURE_CONFIGURATOR,
_ATTACH_SUCCESS_CONFIGURATOR,
)
from microsoft.azureMonitor._diagnostics.status_logger import (
AzureStatusLogger,
)


class AzureMonitorConfigurator(_OTelSDKConfigurator):
def _configure(self, **kwargs):
if not _is_attach_enabled():
warn(_PREVIEW_ENTRY_POINT_WARNING)
try:
if environ.get(OTEL_TRACES_EXPORTER, "").lower().strip() != "none":
kwargs.setdefault(TRACE_EXPORTER_NAMES_ARG, ["azure_monitor_opentelemetry_exporter"])
try:
sample_rate = float(environ.get("OTEL_TRACES_SAMPLER_ARG", 1.0))
except ValueError:
sample_rate = 1.0
kwargs.setdefault(SAMPLER_ARG, ApplicationInsightsSampler(sample_rate))
if environ.get(OTEL_METRICS_EXPORTER, "").lower().strip() != "none":
kwargs.setdefault(METRIC_EXPORTER_NAMES_ARG, ["azure_monitor_opentelemetry_exporter"])
if environ.get(OTEL_LOGS_EXPORTER, "").lower().strip() != "none":
kwargs.setdefault(LOG_EXPORTER_NAMES_ARG, ["azure_monitor_opentelemetry_exporter"])
# As of OTel SDK 1.25.0, exporters passed as kwargs will be added to those specified in env vars.
super()._configure(**kwargs)
AzureStatusLogger.log_status(True)
AzureDiagnosticLogging.info(
"Azure Monitor Configurator configured successfully.",
_ATTACH_SUCCESS_CONFIGURATOR,
)
except Exception as e:
AzureDiagnosticLogging.error( # pylint: disable=C
"Azure Monitor Configurator failed during configuration: %s" % str(e),
_ATTACH_FAILURE_CONFIGURATOR,
)
raise e
Comment thread
JacksonWeber marked this conversation as resolved.
65 changes: 65 additions & 0 deletions src/microsoft/azureMonitor/_autoinstrumentation/distro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License in the project root for
# license information.
# --------------------------------------------------------------------------
from os import environ
from warnings import warn

from opentelemetry.instrumentation.distro import ( # type: ignore
BaseDistro,
)
from opentelemetry.sdk.environment_variables import (
_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED,
OTEL_EXPERIMENTAL_RESOURCE_DETECTORS,
)

from azure.core.settings import settings
from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan
from azure.monitor.opentelemetry.exporter._utils import ( # pylint: disable=import-error,no-name-in-module
_is_attach_enabled,
)
from microsoft.azureMonitor._constants import (
_AZURE_APP_SERVICE_RESOURCE_DETECTOR_NAME,
_AZURE_SDK_INSTRUMENTATION_NAME,
_PREVIEW_ENTRY_POINT_WARNING,
)
from microsoft.azureMonitor._diagnostics.diagnostic_logging import (
AzureDiagnosticLogging,
_ATTACH_FAILURE_DISTRO,
_ATTACH_SUCCESS_DISTRO,
)
from microsoft.azureMonitor._diagnostics.status_logger import (
AzureStatusLogger,
)
from microsoft.azureMonitor._utils.configurations import (
_get_otel_disabled_instrumentations,
)


class AzureMonitorDistro(BaseDistro):
def _configure(self, **kwargs) -> None:
if not _is_attach_enabled():
warn(_PREVIEW_ENTRY_POINT_WARNING)
try:
_configure_auto_instrumentation()
AzureStatusLogger.log_status(True)
AzureDiagnosticLogging.info(
"Azure Monitor OpenTelemetry Distro configured successfully.",
_ATTACH_SUCCESS_DISTRO,
)
except Exception as e:
AzureStatusLogger.log_status(False, reason=str(e))
AzureDiagnosticLogging.error( # pylint: disable=C
"Azure Monitor OpenTelemetry Distro failed during configuration: %s" % str(e),
_ATTACH_FAILURE_DISTRO,
)
raise e
Comment thread
JacksonWeber marked this conversation as resolved.


def _configure_auto_instrumentation() -> None:
environ.setdefault(_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "true")
environ.setdefault(OTEL_EXPERIMENTAL_RESOURCE_DETECTORS, _AZURE_APP_SERVICE_RESOURCE_DETECTOR_NAME)
otel_disabled_instrumentations = _get_otel_disabled_instrumentations()
if _AZURE_SDK_INSTRUMENTATION_NAME not in otel_disabled_instrumentations:
settings.tracing_implementation = OpenTelemetrySpan
Loading
Loading