Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Connection Strings for Azure Exporters #767

Merged
merged 15 commits into from
Sep 25, 2019
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))

Expand Down
27 changes: 15 additions & 12 deletions contrib/opencensus-ext-azure/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ 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 into ``APPLICATIONINSIGHTS_CONNECTION_STRING`` environment variable.
* You can also put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* Alternatively, you can specify either the connection string or instrumentation key directly in your code, which will take priority over a set environment variable.

.. code:: python

Expand All @@ -40,9 +41,9 @@ This example shows how to send a warning level log to Azure Monitor.
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 into ``APPLICATIONINSIGHTS_CONNECTION_STRING`` environment variable.
Copy link
Contributor

Choose a reason for hiding this comment

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

Need a link to the definition of connection string.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I included the connection string in the example code snippet, which is the bare minimum that a user needs to get started (so it is simple). The more formal definition will be included in the TSG for CSS engineers. This will help them troubleshoot any irregularities found with a user's connection string.

* You can also put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to keep this in the doc? I guess we want to remove it from the doc, and leave the logic in the codebase until we decided to bump major version.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed, we should probably remove the method of instrumentation_key from the docs, as we do not want to keep supporting legacy methods. As well, having multiple ways to instrument is confusing to the user.

* Alternatively, you can specify either the connection string or instrumentation key directly in your code, which will take priority over a set environment variable.

.. code:: python

Expand Down Expand Up @@ -75,8 +76,9 @@ 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 into ``APPLICATIONINSIGHTS_CONNECTION_STRING`` environment variable.
* You can also put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* Alternatively, you can specify either the connection string or instrumentation key directly in your code, which will take priority over a set environment variable.

.. code:: python

Expand Down Expand Up @@ -166,8 +168,9 @@ 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 into ``APPLICATIONINSIGHTS_CONNECTION_STRING`` environment variable.
* You can also put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* Alternatively, you can specify either the connection string or instrumentation key directly in your code, which will take priority over a set environment variable.

.. code:: python

Expand All @@ -183,9 +186,9 @@ This example shows how to send a span "hello" to Azure Monitor.
You can also specify the instrumentation key explicitly in the code.

* 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 into ``APPLICATIONINSIGHTS_CONNECTION_STRING`` environment variable.
* You can also put the instrumentation key in ``APPINSIGHTS_INSTRUMENTATIONKEY`` environment variable.
* Alternatively, you can specify either the connection string or instrumentation key directly in your code, which will take priority over a set environment variable.

.. 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,73 @@

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

AUTHORIZATION = 'Authorization'
DEFAULT_BREEZE_ENDPOINT = 'https://dc.services.visualstudio.com'
lzchen marked this conversation as resolved.
Show resolved Hide resolved
ENDPOINT_SUFFIX = 'EndpointSuffix'
ENV_CONNECTION_STRING = 'APPLICATIONINSIGHTS_CONNECTION_STRING'
ENV_INSTRUMENTATION_KEY = 'APPINSIGHTS_INSTRUMENTATIONKEY'
lzchen marked this conversation as resolved.
Show resolved Hide resolved
INGESTION_ENDPOINT = 'IngestionEndpoint'
INSTRUMENTATION_KEY = 'InstrumentationKey'
LOCATION = 'Location'


def process_options(options):
code_cs = parse_connection_string(options.connection_string)
code_ikey = options.instrumentation_key
env_cs = parse_connection_string(os.getenv(ENV_CONNECTION_STRING))
env_ikey = os.getenv(ENV_INSTRUMENTATION_KEY)

options.instrumentation_key = code_cs.get(INSTRUMENTATION_KEY) \
lzchen marked this conversation as resolved.
Show resolved Hide resolved
or code_ikey \
or env_cs.get(INSTRUMENTATION_KEY) \
or env_ikey
endpoint = code_cs.get(INGESTION_ENDPOINT) \
or env_cs.get(INGESTION_ENDPOINT) \
or DEFAULT_BREEZE_ENDPOINT
options.endpoint = endpoint + '/v2/track'
Copy link
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
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
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
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)
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 = ''
if result.get(ENDPOINT_SUFFIX) is not None:
endpoint_suffix = result.get(ENDPOINT_SUFFIX)
# Get regional information if provided
if result.get(LOCATION) is not None:
location_prefix = result.get(LOCATION) + '.'
endpoint = 'https://' + location_prefix + 'dc.' + endpoint_suffix
result[INGESTION_ENDPOINT] = endpoint
else:
# Use default endpoint if cannot construct
result[INGESTION_ENDPOINT] = DEFAULT_BREEZE_ENDPOINT
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