Skip to content

Commit

Permalink
Begin work on datadog metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Stella committed Dec 7, 2020
1 parent f312ad0 commit 920bea2
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"""
# pylint: disable=import-error

from .exporter import DatadogSpanExporter
from .exporter import DatadogMetricsExporter, DatadogSpanExporter
from .spanprocessor import DatadogExportSpanProcessor

__all__ = ["DatadogExportSpanProcessor", "DatadogSpanExporter"]
__all__ = ["DatadogExportSpanProcessor", "DatadogMetricsExporter", "DatadogSpanExporter"]
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,22 @@

import logging
import os
import re
from typing import Optional, Sequence
from urllib.parse import urlparse

from datadog import DogStatsd
from ddtrace.ext import SpanTypes as DatadogSpanTypes
from ddtrace.internal.writer import AgentWriter
from ddtrace.span import Span as DatadogSpan

from opentelemetry.metrics import Counter, UpDownCounter, ValueRecorder
from opentelemetry.sdk.metrics.export import (
ExportRecord,
MetricsExporter,
MetricsExportResult,
)

import opentelemetry.trace as trace_api
from opentelemetry.sdk.trace import sampling
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
Expand Down Expand Up @@ -301,6 +311,7 @@ def _parse_tags_str(tags_str):
return parsed_tags



def _extract_tags_from_resource(resource):
"""Parse tags from resource.attributes, except service.name which
has special significance within datadog"""
Expand All @@ -315,3 +326,66 @@ def _extract_tags_from_resource(resource):
else:
tags[attribute_key] = attribute_value
return [tags, service_name]


class DatadogMetricsExporter(MetricsExporter):
"""
Args:
tags: list of strings
"""

def __init__(self, host=None, port=None, tags: Optional[Sequence[str]] = None, prefix: str = ""):
self._statsd = None
self._host = host or os.environ.get("DD_AGENT_HOST", "localhost")
self._port = int(port or os.environ.get("DD_DOGSTATSD_PORT", 8125))
self._prefix = prefix

self._tags = tags or os.environ.get("DD_TAGS")

self._non_letters_nor_digits_re = re.compile(
r"[^\w]", re.UNICODE | re.IGNORECASE
)

@property
def statsd(self):
if not self._statsd:
self._statsd = DogStatsd(host = self._host,
port = self._port,
constant_tags = self._tags)
return self._statsd


def export(self, export_records: Sequence[ExportRecord]) -> MetricsExportResult:
for export_record in export_records:

# handle labels/tags
tags = list(':'.join(tag) for tag in dict(export_record.labels).items())

# handle name
metric_name = ""
if self._prefix != "":
metric_name = self._prefix + "_"
metric_name += self._sanitize(export_record.instrument.name)

if isinstance(export_record.instrument, (Counter, UpDownCounter)):
self.statsd.increment(metric_name,
value = export_record.aggregator.checkpoint,
tags = tags)

elif isinstance(export_record.instrument, ValueRecorder):
self.statsd.gauge(metric_name,
value = export_record.aggregator.checkpoint,
tags = tags)

else:
logger.warning(
"Unsupported metric type, %s", type(export_record.instrument)
)

return MetricsExportResult.SUCCESS

def _sanitize(self, key: str) -> str:
"""sanitize the given metric name or label according to DataDog rules.
Replace all characters other than [A-Za-z0-9_] with '_'.
"""
return self._non_letters_nor_digits_re.sub("_", key)

0 comments on commit 920bea2

Please sign in to comment.