Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #104 from lzchen/v0.4b.x
Browse files Browse the repository at this point in the history
  • Loading branch information
lzchen authored Jun 29, 2020
2 parents 9eb0a82 + eb00c0f commit 7f892e8
Show file tree
Hide file tree
Showing 37 changed files with 1,417 additions and 593 deletions.
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The online documentation is available at https://opentelemetry-azure-monitor-pyt

### Trace

The **Azure Monitor Trace Exporter** allows you to export [OpenTelemetry](https://opentelemetry.io/) traces to [Azure Monitor](https://docs.microsoft.com/azure/azure-monitor/).
The **Azure Monitor Span Exporter** allows you to export [OpenTelemetry](https://opentelemetry.io/) traces to [Azure Monitor](https://docs.microsoft.com/azure/azure-monitor/).

This example shows how to send a span "hello" to Azure Monitor.

Expand All @@ -33,17 +33,13 @@ from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

trace.set_tracer_provider(TracerProvider())

# We tell OpenTelemetry who it is that is creating spans. In this case, we have
# no real name (no setup.py), so we make one up. If we had a version, we would
# also specify it here.
tracer = trace.get_tracer(__name__)

# SpanExporter receives the spans and send them to the target location
exporter = AzureMonitorSpanExporter(
connection_string='InstrumentationKey=<your-ikey-here>',
)

# SpanExporter receives the spans and send them to the target location.
span_processor = BatchExportSpanProcessor(exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

Expand Down Expand Up @@ -75,12 +71,14 @@ trace.set_tracer_provider(TracerProvider())
tracer_provider = trace.get_tracer_provider()

exporter = AzureMonitorSpanExporter(
connection_string='InstrumentationKey=<your-ikey-here>',
)
connection_string='InstrumentationKey=<your-ikey-here>',
)
span_processor = BatchExportSpanProcessor(exporter)
tracer_provider.add_span_processor(span_processor)

RequestsInstrumentor().instrument()

# This request will be traced
response = requests.get(url="https://azure.microsoft.com/")
```

Expand All @@ -106,6 +104,7 @@ def callback_function(envelope):
exporter = AzureMonitorSpanExporter(
connection_string='InstrumentationKey=<your-ikey-here>'
)
# This line will modify telemetry
exporter.add_telemetry_processor(callback_function)

trace.set_tracer_provider(TracerProvider())
Expand Down
14 changes: 14 additions & 0 deletions azure_monitor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

## Unreleased

## 0.4b.0
Released 2020-06-29

- Added live metrics
([#96](https://github.com/microsoft/opentelemetry-azure-monitor-python/pull/96))
- Remove dependency metrics from auto-collection
([#99](https://github.com/microsoft/opentelemetry-azure-monitor-python/pull/99))
- Change default local storage directory
([#100](https://github.com/microsoft/opentelemetry-azure-monitor-python/pull/100))
- Implement proxies in exporter configuration
([#101](https://github.com/microsoft/opentelemetry-azure-monitor-python/pull/101))
- Remove request failed per second metrics from auto-collection
([#102](https://github.com/microsoft/opentelemetry-azure-monitor-python/pull/102))

## 0.3b.1
Released 2020-05-21

Expand Down
25 changes: 16 additions & 9 deletions azure_monitor/examples/metrics/auto_collector.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from opentelemetry import metrics
from opentelemetry import metrics, trace
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export.controller import PushController
from opentelemetry.sdk.trace import TracerProvider

from azure_monitor import AzureMonitorMetricsExporter
from azure_monitor.sdk.auto_collection import AutoCollection
from azure_monitor.sdk.auto_collection import (
AutoCollection,
AzureMetricsSpanProcessor,
)

# Add Span Processor to get metrics about traces
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer_provider().get_tracer(__name__)
span_processor = AzureMetricsSpanProcessor()
trace.get_tracer_provider().add_span_processor(span_processor)

metrics.set_meter_provider(MeterProvider())
meter = metrics.get_meter(__name__)
exporter = AzureMonitorMetricsExporter(
connection_string="InstrumentationKey=<INSTRUMENTATION KEY HERE>"
)
controller = PushController(meter, exporter, 5)

testing_label_set = {"environment": "testing"}

# Automatically collect standard metrics
auto_collection = AutoCollection(meter=meter, labels=testing_label_set)
auto_collection = AutoCollection(
meter=meter, labels=testing_label_set, span_processor=span_processor
)

# To configure a separate export interval specific for standard metrics
# meter_standard = metrics.get_meter(__name__ + "_standard")
# controller _standard = PushController(meter_standard, exporter, 30)
# _auto_collection = AutoCollection(meter=meter_standard, label_set=testing_label_set)
metrics.get_meter_provider().start_pipeline(meter, exporter, 2)

input("Press any key to exit...")
7 changes: 4 additions & 3 deletions azure_monitor/examples/metrics/observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
# Licensed under the MIT License.
import psutil
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export.controller import PushController
from opentelemetry.sdk.metrics import MeterProvider, UpDownSumObserver

from azure_monitor import AzureMonitorMetricsExporter

Expand All @@ -12,7 +11,7 @@
exporter = AzureMonitorMetricsExporter(
connection_string="InstrumentationKey=<INSTRUMENTATION KEY HERE>"
)
controller = PushController(meter=meter, exporter=exporter, interval=2)
metrics.get_meter_provider().start_pipeline(meter, exporter, 2)


# Callback to gather cpu usage
Expand All @@ -28,6 +27,7 @@ def get_cpu_usage_callback(observer):
description="per-cpu usage",
unit="1",
value_type=float,
observer_type=UpDownSumObserver,
label_keys=("cpu_number",),
)

Expand All @@ -44,6 +44,7 @@ def get_ram_usage_callback(observer):
description="RAM memory usage",
unit="1",
value_type=float,
observer_type=UpDownSumObserver,
label_keys=(),
)

Expand Down
3 changes: 1 addition & 2 deletions azure_monitor/examples/metrics/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# Licensed under the MIT License.
from opentelemetry import metrics
from opentelemetry.sdk.metrics import Counter, MeterProvider
from opentelemetry.sdk.metrics.export.controller import PushController

from azure_monitor import AzureMonitorMetricsExporter

Expand All @@ -11,7 +10,7 @@
exporter = AzureMonitorMetricsExporter(
connection_string="InstrumentationKey=<INSTRUMENTATION KEY HERE>"
)
controller = PushController(meter, exporter, 5)
metrics.get_meter_provider().start_pipeline(meter, exporter, 5)

requests_counter = meter.create_metric(
name="requests",
Expand Down
5 changes: 3 additions & 2 deletions azure_monitor/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ classifiers =
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8

[options]
python_requires = >=3.4
package_dir=
=src
packages=find_namespace:
install_requires =
opentelemetry-api ~= 0.7b1
opentelemetry-sdk ~= 0.7b1
opentelemetry-api == 0.10b0
opentelemetry-sdk == 0.10b0
psutil >= 5.6.3
requests ~= 2.0

Expand Down
21 changes: 18 additions & 3 deletions azure_monitor/src/azure_monitor/export/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
import logging
import typing
from enum import Enum
from urllib.parse import urlparse

import requests
from opentelemetry.sdk.metrics.export import MetricsExportResult
from opentelemetry.sdk.trace.export import SpanExportResult
from opentelemetry.sdk.util import ns_to_iso_str
from opentelemetry.trace import Span, SpanKind
from opentelemetry.trace.status import StatusCanonicalCode

from azure_monitor import protocol, utils
from azure_monitor.options import ExporterOptions
from azure_monitor.protocol import Envelope
from azure_monitor.storage import LocalFileStorage
Expand Down Expand Up @@ -90,15 +95,16 @@ def _transmit_from_storage(self) -> None:
# give a few more seconds for blob lease operation
# to reduce the chance of race (for perf consideration)
if blob.lease(self.options.timeout + 5):
envelopes = blob.get() # TODO: handle error
envelopes = blob.get()
result = self._transmit(envelopes)
if result == ExportResult.FAILED_RETRYABLE:
blob.lease(1)
else:
blob.delete(silent=True)
blob.delete()

# pylint: disable=too-many-branches
# pylint: disable=too-many-nested-blocks
# pylint: disable=too-many-return-statements
def _transmit(self, envelopes: typing.List[Envelope]) -> ExportResult:
"""
Transmit the data envelopes to the ingestion service.
Expand All @@ -116,9 +122,18 @@ def _transmit(self, envelopes: typing.List[Envelope]) -> ExportResult:
"Content-Type": "application/json; charset=utf-8",
},
timeout=self.options.timeout,
proxies=self.options.proxies,
)
except requests.Timeout:
logger.warning(
"Request time out. Ingestion may be backed up. Retrying."
)
return ExportResult.FAILED_RETRYABLE
except Exception as ex:
logger.warning("Transient client side error: %s.", ex)
logger.warning(
"Retrying due to transient client side error %s.", ex
)
# client side error (retryable)
return ExportResult.FAILED_RETRYABLE

text = "N/A"
Expand Down
33 changes: 21 additions & 12 deletions azure_monitor/src/azure_monitor/export/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
from typing import Sequence
from urllib.parse import urlparse

from opentelemetry.sdk.metrics import Counter, Metric, Observer
from opentelemetry.sdk.metrics import (
Counter,
SumObserver,
UpDownCounter,
UpDownSumObserver,
ValueObserver,
ValueRecorder,
)
from opentelemetry.sdk.metrics.export import (
MetricRecord,
MetricsExporter,
Expand Down Expand Up @@ -66,20 +73,22 @@ def _metric_to_envelope(
)
envelope.name = "Microsoft.ApplicationInsights.Metric"
value = 0
metric = metric_record.metric
if isinstance(metric, Counter):
value = metric_record.aggregator.checkpoint
elif isinstance(metric, Observer):
metric = metric_record.instrument
if isinstance(metric, ValueObserver):
# mmscl
value = metric_record.aggregator.checkpoint.last
if not value:
value = 0
elif isinstance(metric, ValueRecorder):
# mmsc
value = metric_record.aggregator.checkpoint.count
else:
# TODO: What do measure aggregations look like in AI?
logger.warning("Measure metric recorded.")

# sum or lv
value = metric_record.aggregator.checkpoint
if value is None:
logger.warning("Value is none. Default to 0.")
value = 0
data_point = protocol.DataPoint(
ns=metric_record.metric.description,
name=metric_record.metric.name,
ns=metric.description,
name=metric.name,
value=value,
kind=protocol.DataPointType.MEASUREMENT.value,
)
Expand Down
Loading

0 comments on commit 7f892e8

Please sign in to comment.