Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.
2 changes: 2 additions & 0 deletions contrib/opencensus-ext-azure/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Changelog

## Unreleased
- Implement connection strings
([#767](https://github.com/census-instrumentation/opencensus-python/pull/767))
- Standard metrics incoming requests per second
([#758](https://github.com/census-instrumentation/opencensus-python/pull/758))
- Standard metrics incoming requests average execution rate
Expand Down
49 changes: 29 additions & 20 deletions contrib/opencensus-ext-azure/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ The **Azure Monitor Log Handler** allows you to export Python logs to `Azure Mon
This example shows how to send a warning level log to Azure Monitor.

* Create an Azure Monitor resource and get the instrumentation key, more information can be found `here <https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource>`_.
* Put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* You can also specify the instrumentation key explicitly in the code, which will take priority over a set environment variable.
* Place your instrumentation key in a `connection string` and directly into your code.
* Alternatively, you can specify your `connection string` in an environment variable ``APPLICATIONINSIGHTS_CONNECTION_STRING``.

.. code:: python

Expand All @@ -34,15 +34,16 @@ This example shows how to send a warning level log to Azure Monitor.
from opencensus.ext.azure.log_exporter import AzureLogHandler

logger = logging.getLogger(__name__)
logger.addHandler(AzureLogHandler())
logger.addHandler(AzureLogHandler(connection_string='InstrumentationKey=<your-instrumentation_key-here>'))
logger.warning('Hello, World!')

* Alternatively, you can specify your `connection string` in an environment variable ``APPLICATIONINSIGHTS_CONNECTION_STRING``.

You can enrich the logs with trace IDs and span IDs by using the `logging integration <../opencensus-ext-logging>`_.

* Create an Azure Monitor resource and get the instrumentation key, more information can be found `here <https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource>`_.
* Install the `logging integration package <../opencensus-ext-logging>`_ using ``pip install opencensus-ext-logging``.
* Put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* You can also specify the instrumentation key explicitly in the code, which will take priority over a set environment variable.
* Place your instrumentation key in a `connection string` and directly into your code.
* Alternatively, you can specify your `connection string` in an environment variable ``APPLICATIONINSIGHTS_CONNECTION_STRING``.

.. code:: python

Expand All @@ -58,25 +59,28 @@ You can enrich the logs with trace IDs and span IDs by using the `logging integr

logger = logging.getLogger(__name__)

handler = AzureLogHandler()
handler = AzureLogHandler(connection_string='InstrumentationKey=<your-instrumentation_key-here>')
handler.setFormatter(logging.Formatter('%(traceId)s %(spanId)s %(message)s'))
logger.addHandler(handler)

tracer = Tracer(exporter=AzureExporter(), sampler=ProbabilitySampler(1.0))
tracer = Tracer(
exporter=AzureExporter(connection_string='InstrumentationKey=<your-instrumentation_key-here>'),
sampler=ProbabilitySampler(1.0)
)

logger.warning('Before the span')
with tracer.span(name='test'):
logger.warning('In the span')
logger.warning('After the span')
logger.warning('After the span')s

Metrics
~~~~~~~

The **Azure Monitor Metrics Exporter** allows you to export metrics to `Azure Monitor`_.

* Create an Azure Monitor resource and get the instrumentation key, more information can be found `here <https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource>`_.
* Put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* You can also specify the instrumentation key explicitly in the code, which will take priority over a set environment variable.
* Place your instrumentation key in a `connection string` and directly into your code.
* Alternatively, you can specify your `connection string` in an environment variable ``APPLICATIONINSIGHTS_CONNECTION_STRING``.

.. code:: python

Expand Down Expand Up @@ -105,7 +109,7 @@ The **Azure Monitor Metrics Exporter** allows you to export metrics to `Azure Mo
def main():
# Enable metrics
# Set the interval in seconds in which you want to send metrics
exporter = metrics_exporter.new_metrics_exporter()
exporter = metrics_exporter.new_metrics_exporter(connection_string='InstrumentationKey=<your-instrumentation-key-here>')
view_manager.register_exporter(exporter)

view_manager.register_view(CARROTS_VIEW)
Expand Down Expand Up @@ -138,7 +142,7 @@ The exporter also includes a set of standard metrics that are exported to Azure
# All you need is the next line. You can disable standard metrics by
# passing in enable_standard_metrics=False into the constructor of
# new_metrics_exporter()
_exporter = metrics_exporter.new_metrics_exporter()
_exporter = metrics_exporter.new_metrics_exporter(connection_string='InstrumentationKey=<your-instrumentation-key-here>')

for i in range(100):
print(psutil.virtual_memory())
Expand Down Expand Up @@ -167,26 +171,31 @@ The **Azure Monitor Trace Exporter** allows you to export `OpenCensus`_ traces t
This example shows how to send a span "hello" to Azure Monitor.

* Create an Azure Monitor resource and get the instrumentation key, more information can be found `here <https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource>`_.
* Put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* You can also specify the instrumentation key explicitly in the code, which will take priority over a set environment variable.
* Place your instrumentation key in a `connection string` and directly into your code.
* Alternatively, you can specify your `connection string` in an environment variable ``APPLICATIONINSIGHTS_CONNECTION_STRING``.

.. code:: python
.. code:: python

from opencensus.ext.azure.trace_exporter import AzureExporter
from opencensus.trace.samplers import ProbabilitySampler
from opencensus.trace.tracer import Tracer

tracer = Tracer(exporter=AzureExporter(), sampler=ProbabilitySampler(1.0))
tracer = Tracer(
exporter=AzureExporter(connection_string='InstrumentationKey=<your-instrumentation-key-here>'),
sampler=ProbabilitySampler(1.0)
)

with tracer.span(name='hello'):
print('Hello, World!')

You can also specify the instrumentation key explicitly in the code.
OpenCensus also supports several [integrations](https://github.com/census-instrumentation/opencensus-python#integration) which allows OpenCensus to integrate with third party libraries.

This example shows how to integrate with the [requests](https://2.python-requests.org/en/master/) library.

* Create an Azure Monitor resource and get the instrumentation key, more information can be found `here <https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource>`_.
* Install the `requests integration package <../opencensus-ext-requests>`_ using ``pip install opencensus-ext-requests``.
* Put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* You can also specify the instrumentation key explicitly in the code, which will take priority over a set environment variable.
* Place your instrumentation key in a `connection string` and directly into your code.
* Alternatively, you can specify your `connection string` in an environment variable ``APPLICATIONINSIGHTS_CONNECTION_STRING``.

.. code:: python

Expand Down
5 changes: 3 additions & 2 deletions contrib/opencensus-ext-azure/examples/logs/correlated.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@

logger = logging.getLogger(__name__)

# TODO: you need to specify the instrumentation key in the
# APPINSIGHTS_INSTRUMENTATIONKEY environment variable.
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
handler = AzureLogHandler()
logger.addHandler(handler)

Expand Down
5 changes: 3 additions & 2 deletions contrib/opencensus-ext-azure/examples/logs/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
from opencensus.ext.azure.log_exporter import AzureLogHandler

logger = logging.getLogger(__name__)
# TODO: you need to specify the instrumentation key in the
# APPINSIGHTS_INSTRUMENTATIONKEY environment variable.
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
logger.addHandler(AzureLogHandler())


Expand Down
5 changes: 3 additions & 2 deletions contrib/opencensus-ext-azure/examples/logs/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from opencensus.ext.azure.log_exporter import AzureLogHandler

logger = logging.getLogger(__name__)
# TODO: you need to specify the instrumentation key in the
# APPINSIGHTS_INSTRUMENTATIONKEY environment variable.
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
logger.addHandler(AzureLogHandler())
logger.warning('Hello, World!')
3 changes: 3 additions & 0 deletions contrib/opencensus-ext-azure/examples/metrics/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
def main():
# Enable metrics
# Set the interval in seconds in which you want to send metrics
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
exporter = metrics_exporter.new_metrics_exporter()
view_manager.register_exporter(exporter)

Expand Down
3 changes: 3 additions & 0 deletions contrib/opencensus-ext-azure/examples/metrics/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@


def main():
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
# All you need is the next line. You can disable standard metrics by
# passing in enable_standard_metrics=False into the constructor of
# new_metrics_exporter()
Expand Down
3 changes: 3 additions & 0 deletions contrib/opencensus-ext-azure/examples/metrics/sum.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
def main():
# Enable metrics
# Set the interval in seconds in which you want to send metrics
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
exporter = metrics_exporter.new_metrics_exporter()
view_manager.register_exporter(exporter)

Expand Down
5 changes: 3 additions & 2 deletions contrib/opencensus-ext-azure/examples/traces/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
from opencensus.trace.tracer import Tracer

config_integration.trace_integrations(['requests'])
# TODO: you need to specify the instrumentation key in the
# APPINSIGHTS_INSTRUMENTATIONKEY environment variable.
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
tracer = Tracer(exporter=AzureExporter(), sampler=ProbabilitySampler(1.0))
with tracer.span(name='parent'):
with tracer.span(name='child'):
Expand Down
3 changes: 2 additions & 1 deletion contrib/opencensus-ext-azure/examples/traces/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
tracer = Tracer(
exporter=AzureExporter(
# TODO: replace the all-zero GUID with your instrumentation key.
instrumentation_key='00000000-0000-0000-0000-000000000000',
connection_string='InstrumentationKey= \
00000000-0000-0000-0000-000000000000',
),
sampler=ProbabilitySampler(rate=1.0),
)
Expand Down
3 changes: 2 additions & 1 deletion contrib/opencensus-ext-azure/examples/traces/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
'TRACE': {
'SAMPLER': 'opencensus.trace.samplers.ProbabilitySampler(rate=1.0)',
'EXPORTER': '''opencensus.ext.azure.trace_exporter.AzureExporter(
instrumentation_key='00000000-0000-0000-0000-000000000000',
connection_string=
'InstrumentationKey=00000000-0000-0000-0000-000000000000',
)''',
},
}
Expand Down
5 changes: 3 additions & 2 deletions contrib/opencensus-ext-azure/examples/traces/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
from opencensus.trace import config_integration
from opencensus.trace.samplers import ProbabilitySampler

# TODO: you need to specify the instrumentation key in the
# APPINSIGHTS_INSTRUMENTATIONKEY environment variable.
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
app = Flask(__name__)
middleware = FlaskMiddleware(
app,
Expand Down
5 changes: 3 additions & 2 deletions contrib/opencensus-ext-azure/examples/traces/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
from opencensus.trace.samplers import ProbabilitySampler
from opencensus.trace.tracer import Tracer

# TODO: you need to specify the instrumentation key in the
# APPINSIGHTS_INSTRUMENTATIONKEY environment variable.
# TODO: you need to specify the instrumentation key in a connection string
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
# environment variable.
tracer = Tracer(exporter=AzureExporter(), sampler=ProbabilitySampler(1.0))

with tracer.span(name='foo'):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,81 @@

from opencensus.ext.azure.common.protocol import BaseObject

INGESTION_ENDPOINT = 'ingestionendpoint'
INSTRUMENTATION_KEY = 'instrumentationkey'


def process_options(options):
code_cs = parse_connection_string(options.connection_string)
code_ikey = options.instrumentation_key
env_cs = parse_connection_string(
os.getenv('APPLICATIONINSIGHTS_CONNECTION_STRING'))
env_ikey = os.getenv('APPINSIGHTS_INSTRUMENTATIONKEY')

# The priority of which value takes on the instrumentation key is:
# 1. Key from explicitly passed in connection string
# 2. Key from explicitly passed in instrumentation key
# 3. Key from connection string in environment variable
# 4. Key from instrumentation key in environment variable
options.instrumentation_key = code_cs.get(INSTRUMENTATION_KEY) \
or code_ikey \
or env_cs.get(INSTRUMENTATION_KEY) \
or env_ikey
# The priority of the ingestion endpoint is as follows:
# 1. The endpoint explicitly passed in connection string
# 2. The endpoint from the connection string in environment variable
# 3. The default breeze endpoint
endpoint = code_cs.get(INGESTION_ENDPOINT) \
or env_cs.get(INGESTION_ENDPOINT) \
or 'https://dc.services.visualstudio.com'
options.endpoint = endpoint + '/v2/track'
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.

If this endpoint encoded?
Do we do canonicalization?

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.

Can you explain more about how the endpoint would be encoded?

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.

For example, do you expect the endpoint to be something like https://zh.wikipedia.org/wiki/%E6%A3%89%E5%B0%BE%E5%85%94%E5%B1%9E ?

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 do not believe that an encoded endpoint would be intentionally passed in. According to Mothra, none of the current endpoint configurations handle strings in any special way, so I believe it's safe to leave the url string as is.



def parse_connection_string(connection_string):
if connection_string is None:
return {}
try:
pairs = connection_string.split(';')
result = dict(s.split('=') for s in pairs)
# Convert keys to lower-case due to case type-insensitive checking
result = {key.lower(): value for key, value in result.items()}
except Exception:
raise ValueError('Invalid connection string')
# Validate authorization
auth = result.get('authorization')
if auth is not None and auth.lower() != 'ikey':
raise ValueError('Invalid authorization mechanism')
# Construct the ingestion endpoint if not passed in explicitly
if result.get(INGESTION_ENDPOINT) is None:
endpoint_suffix = ''
location_prefix = ''
suffix = result.get('endpointsuffix')
if suffix is not None:
endpoint_suffix = suffix
# Get regional information if provided
prefix = result.get('location')
if prefix is not None:
location_prefix = prefix + '.'
endpoint = 'https://' + location_prefix + 'dc.' + endpoint_suffix
result[INGESTION_ENDPOINT] = endpoint
else:
# Default to None if cannot construct
result[INGESTION_ENDPOINT] = None
return result


class Options(BaseObject):
def __init__(self, *args, **kwargs):
super(Options, self).__init__(*args, **kwargs)
process_options(self)

_default = BaseObject(
connection_string=None,
enable_standard_metrics=True,
endpoint='https://dc.services.visualstudio.com/v2/track',
export_interval=15.0,
grace_period=5.0,
instrumentation_key=os.getenv('APPINSIGHTS_INSTRUMENTATIONKEY', None),
instrumentation_key=None,
max_batch_size=100,
minimum_retry_interval=60, # minimum retry interval in seconds
proxy=None,
Expand Down
Loading