메트릭 제출: DogStatsD
StatsD는 메트릭만 받아들이지만, DogStatsD는 Datadog의 세 가지 주요 데이터 타입인 메트릭, 이벤트, 서비스 체크(service check)를 모두 받아들여요. 이 문서에서는 메트릭 타입별로 나눈 DogStatsD의 대표적인 사용 사례와, DogStatsD에 특화된 샘플링 비율(Sample Rate) 및 메트릭 태깅 옵션을 소개해요.
출처: 문서
본문
StatsD는 메트릭만 받아들이지만, DogStatsD는 Datadog의 세 가지 주요 데이터 타입인 메트릭(metrics), 이벤트(events), 서비스 체크(service checks)를 모두 받아들여요. 이 섹션에서는 메트릭 타입별로 나눈 전형적인 사용 사례를 보여주고, DogStatsD에 특화된 샘플링 비율과 메트릭 태깅 옵션을 소개해요.
COUNT, GAUGE, SET 메트릭 타입은 StatsD 사용자에게 익숙할 거예요. StatsD의 TIMER는 DogStatsD에서 HISTOGRAM의 하위 집합이에요. 또한 DogStatsD를 사용해 HISTOGRAM과 DISTRIBUTION 메트릭 타입도 제출할 수 있어요.
참고: 사용하는 제출 방법에 따라 Datadog에 저장되는 실제 메트릭 타입이 제출 메트릭 타입과 다를 수 있어요. DogStatsD를 통해 RATE 메트릭을 얻으려면 COUNT 또는 HISTOGRAM 메트릭을 제출하세요. Count 메트릭 값과 <HISTOGRAM>.count 값은 StatsD flush 기간 동안 메트릭 값의 시간 정규화된 델타예요.
함수
DogStatsD를 설치한 후에는 메트릭 타입에 따라 메트릭을 Datadog에 제출하기 위한 다음 함수들을 사용할 수 있어요. 함수들은 다음과 같은 공통 파라미터를 가져요.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
<METRIC_NAME> |
String | 예 | 제출할 메트릭의 이름이에요. |
<METRIC_VALUE> |
Double | 예 | 메트릭과 연관된 값이에요. |
<SAMPLE_RATE> |
Double | 아니요 | 메트릭에 적용할 샘플링 비율이에요. 0(전부 샘플링되어 아무것도 전송 안 함)부터 1(샘플링 없음) 사이의 값을 가져요. 자세한 내용은 Sample Rate 섹션을 참고하세요. |
<TAGS> |
List of strings | 아니요 | 메트릭에 적용할 태그 목록이에요. 자세한 내용은 Metric Tagging 섹션을 참고하세요. |
<CARDINALITY> |
Enum | 아니요 | 이 메트릭에 할당할 태그의 카디널리티(cardinality)예요. |
COUNT
{% dl %}
{% dt %}
increment(<METRIC_NAME>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY> )
{% /dt %}
{% dd %}
COUNT 메트릭을 증가시키는 데 사용해요. Datadog에서 RATE 타입으로 저장돼요. 저장된 타임시리즈의 각 값은 StatsD flush 기간 동안 메트릭 값의 시간 정규화된 델타예요.
{% /dd %}
{% dt %}
decrement(<METRIC_NAME>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
COUNT 메트릭을 감소시키는 데 사용해요. Datadog에서 RATE 타입으로 저장돼요. 저장된 타임시리즈의 각 값은 StatsD flush 기간 동안 메트릭 값의 시간 정규화된 델타예요.
{% /dd %}
{% dt %}
count(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
임의의 Value에서 COUNT 메트릭을 증가시키는 데 사용해요. Datadog에서 RATE 타입으로 저장돼요. 저장된 타임시리즈의 각 값은 StatsD flush 기간 동안 메트릭 값의 시간 정규화된 델타예요.
{% /dd %}
{% /dl %}
참고: COUNT 타입 메트릭은 flush 간격에 대해 정규화되어 초당 단위로 보고되므로, Datadog에서 소수 값으로 표시될 수 있어요.
코드 예시
COUNT 메트릭을 — 실제로는 RATE 메트릭으로 저장되지만 — Datadog으로 전송해 보세요. COUNT 타입에 대한 자세한 내용은 메트릭 타입 문서에서 확인할 수 있어요.
아래 코드를 실행해 DogStatsD COUNT 메트릭을 Datadog에 제출해 보세요. 클라이언트를 더 이상 사용하지 않을 때는 flush/close를 호출하는 것을 잊지 마세요.
{% tab title="Python" %}
from datadog import initialize, statsd
import time
options = {
'statsd_host':'127.0.0.1',
'statsd_port':8125
}
initialize(**options)
while(1):
statsd.increment('example_metric.increment', tags=["environment:dev"])
statsd.decrement('example_metric.decrement', tags=["environment:dev"])
time.sleep(10)
참고: statsd.count는 Python에서 지원되지 않아요.
{% /tab %}
{% tab title="Ruby" %}
require 'datadog/statsd'
statsd = Datadog::Statsd.new('localhost', 8125, tags: ['environment:dev'])
while true do
statsd.increment('example_metric.increment')
statsd.increment('example_metric.increment', tags: ['another:tag'])
statsd.decrement('example_metric.decrement')
statsd.count('example_metric.count', 2)
sleep 10
end
{% /tab %}
{% tab title="Go" %}
package main
import (
"log"
"time"
"github.com/DataDog/datadog-go/v5/statsd"
)
func main() {
statsd, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
for true {
statsd.Incr("example_metric.increment", []string{"environment:dev"}, 1)
statsd.Decr("example_metric.decrement", []string{"environment:dev"}, 1)
statsd.Count("example_metric.count", 2, []string{"environment:dev"}, 1)
time.Sleep(10 * time.Second)
}
}
{% /tab %}
{% tab title="Java" %}
import com.timgroup.statsd.NonBlockingStatsDClientBuilder;
import com.timgroup.statsd.StatsDClient;
import java.util.Random;
public class DogStatsdClient {
public static void main(String[] args) throws Exception {
StatsDClient Statsd = new NonBlockingStatsDClientBuilder()
.prefix("statsd")
.hostname("localhost")
.port(8125)
.build();
while (true) {
Statsd.incrementCounter("example_metric.increment", new String[]{"environment:dev"});
Statsd.decrementCounter("example_metric.decrement", new String[]{"environment:dev"});
Statsd.count("example_metric.count", 2, new String[]{"environment:dev"});
Thread.sleep(100000);
}
}
}
{% /tab %}
{% tab title=".NET" %}
using StatsdClient;
using System;
public class DogStatsdClient
{
public static void Main()
{
var dogstatsdConfig = new StatsdConfig
{
StatsdServerName = "127.0.0.1",
StatsdPort = 8125,
};
using (var dogStatsdService = new DogStatsdService())
{
if (!dogStatsdService.Configure(dogstatsdConfig))
throw new InvalidOperationException("Cannot initialize DogstatsD. Set optionalExceptionHandler argument in the `Configure` method for more information.");
var random = new Random(0);
while (true)
{
dogStatsdService.Increment("example_metric.increment", tags: new[] {"environment:dev"}, cardinality: Cardinality.Low);
dogStatsdService.Decrement("example_metric.decrement", tags: new[] {"environment:dev"}, cardinality: Cardinality.High);
dogStatsdService.Counter("example_metric.count", 2, tags: new[] {"environment:dev"});
System.Threading.Thread.Sleep(random.Next(100000));
}
}
}
}
{% /tab %}
{% tab title="PHP" %}
<?php
require __DIR__ . '/vendor/autoload.php';
use DataDog\DogStatsd;
$statsd = new DogStatsd(
array('host' => '127.0.0.1',
'port' => 8125,
)
);
while (TRUE) {
$statsd->increment('example_metric.increment', 1, array('environment'=>'dev'), 'low');
$statsd->decrement('example_metric.decrement', 1, array('environment'=>'dev'), 'high');
sleep(10);
}
{% /tab %}
{% tab title="Node.js" %}
const tracer = require('dd-trace');
tracer.init();
tracer.dogstatsd.increment('example_metric.increment', 1, { environment: 'dev' });
tracer.dogstatsd.decrement('example_metric.decrement', 1, { environment: 'dev' });
{% /tab %}
위 코드를 실행하면 메트릭 데이터를 Datadog에서 그래프로 표현할 수 있어요.
{% image source="https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/increment_decrement.7c0ebf5d364882429c85429554d8f273.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/increment_decrement.7c0ebf5d364882429c85429554d8f273.png?auto=format&fit=max&w=850&dpr=2 2x" alt="Increment Decrement" /%}
값이 COUNT로 제출되었기 때문에 Datadog에서는 RATE로 저장돼요. Datadog에서 원시 count를 얻으려면 시리즈에 누적 합계(Cumulative Sum) 또는 적분(Integral) 같은 함수를 적용하면 돼요.
{% image source="https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/increment_decrement_cumsum.d5388005804db600db36983357b7f1a7.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/increment_decrement_cumsum.d5388005804db600db36983357b7f1a7.png?auto=format&fit=max&w=850&dpr=2 2x" alt="Increment Decrement with Cumsum" /%}
GAUGE
{% dl %}
{% dt %}
gauge(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
Datadog에서 GAUGE 타입으로 저장돼요. 저장된 타임시리즈의 각 값은 StatsD flush 기간 동안 메트릭에 제출된 마지막 gauge 값이에요.
{% /dd %}
{% /dl %}
코드 예시
GAUGE 메트릭을 — 실제로는 GAUGE 메트릭으로 저장되지만 — Datadog으로 전송해 보세요. GAUGE 타입에 대한 자세한 내용은 메트릭 타입 문서에서 확인할 수 있어요.
아래 코드를 실행해 DogStatsD GAUGE 메트릭을 Datadog에 제출해 보세요. 클라이언트를 더 이상 사용하지 않을 때는 flush/close를 호출하는 것을 잊지 마세요.
참고: 메트릭 제출 호출은 비동기적이에요. 메트릭이 확실히 제출되도록 하려면 프로그램이 종료되기 전에 flush를 호출하세요.
{% tab title="Python" %}
from datadog import initialize, statsd
import time
options = {
'statsd_host':'127.0.0.1',
'statsd_port':8125
}
initialize(**options)
i = 0
while(1):
i += 1
statsd.gauge('example_metric.gauge', i, tags=["environment:dev"], cardinality="low")
time.sleep(10)
{% /tab %}
{% tab title="Ruby" %}
require 'datadog/statsd'
statsd = Datadog::Statsd.new('localhost', 8125)
i = 0
while true do
i += 1
statsd.gauge('example_metric.gauge', i, tags: ['environment:dev'], cardinality: 'low')
sleep 10
end
{% /tab %}
{% tab title="Go" %}
package main
import (
"log"
"time"
"github.com/DataDog/datadog-go/v5/statsd"
)
func main() {
statsd, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
var i float64
for true {
i += 1
statsd.Gauge("example_metric.gauge", i, []string{"environment:dev"}, 1, CardinalityHigh)
time.Sleep(10 * time.Second)
}
}
{% /tab %}
{% tab title="Java" %}
import com.timgroup.statsd.NonBlockingStatsDClientBuilder;
import com.timgroup.statsd.StatsDClient;
import java.util.Random;
public class DogStatsdClient {
public static void main(String[] args) throws Exception {
StatsDClient Statsd = new NonBlockingStatsDClientBuilder()
.prefix("statsd").
.hostname("localhost")
.port(8125)
.build();
for (int i = 0; true; i++) {
Statsd.recordGaugeValue("example_metric.gauge", i, new String[]{"environment:dev"});
Thread.sleep(10000);
}
}
}
{% /tab %}
{% tab title=".NET" %}
using StatsdClient;
using System;
public class DogStatsdClient
{
public static void Main()
{
var dogstatsdConfig = new StatsdConfig
{
StatsdServerName = "127.0.0.1",
StatsdPort = 8125,
};
using (var dogStatsdService = new DogStatsdService())
{
if (!dogStatsdService.Configure(dogstatsdConfig))
throw new InvalidOperationException("Cannot initialize DogstatsD. Set optionalExceptionHandler argument in the `Configure` method for more information.");
var random = new Random(0);
for (int i = 0; true; i++)
{
dogStatsdService.Gauge("example_metric.gauge", i, tags: new[] {"environment:dev"}, cardinality: Cardinality.High);
System.Threading.Thread.Sleep(100000);
}
}
}
}
{% /tab %}
{% tab title="PHP" %}
<?php
require __DIR__ . '/vendor/autoload.php';
use DataDog\DogStatsd;
$statsd = new DogStatsd(
array('host' => '127.0.0.1',
'port' => 8125,
)
);
$i = 0;
while (TRUE) {
$i++;
$statsd->gauge('example_metric.gauge', $i, array('environment'=>'dev'), 'low');
sleep(10);
}
{% /tab %}
{% tab title="Node.js" %}
const tracer = require('dd-trace');
tracer.init();
let i = 0;
while(true) {
i++;
tracer.dogstatsd.gauge('example_metric.gauge', i, { environment: 'dev' });
}
{% /tab %}
위 코드를 실행하면 메트릭 데이터를 Datadog에서 그래프로 표현할 수 있어요.
{% image source="https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/gauge.b434e5f1bee65274bd4f694b8f1c4cb4.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/gauge.b434e5f1bee65274bd4f694b8f1c4cb4.png?auto=format&fit=max&w=850&dpr=2 2x" alt="Gauge" /%}
SET
{% dl %}
{% dt %}
set(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
Datadog에서 GAUGE 타입으로 저장돼요. 저장된 타임시리즈의 각 값은 flush 기간 동안 StatsD에 제출된 메트릭의 고유 값 개수예요.
{% /dd %}
{% /dl %}
코드 예시
SET 메트릭을 — 실제로는 GAUGE 메트릭으로 저장되지만 — Datadog으로 전송해 보세요.
아래 코드를 실행해 DogStatsD SET 메트릭을 Datadog에 제출해 보세요. 클라이언트를 더 이상 사용하지 않을 때는 flush/close를 호출하는 것을 잊지 마세요.
{% tab title="Python" %}
from datadog import initialize, statsd
import time
import random
options = {
'statsd_host':'127.0.0.1',
'statsd_port':8125
}
initialize(**options)
i = 0
while(1):
i += 1
statsd.set('example_metric.set', i, tags=["environment:dev"])
time.sleep(random.randint(0, 10))
{% /tab %}
{% tab title="Ruby" %}
require 'datadog/statsd'
statsd = Datadog::Statsd.new('localhost', 8125)
i = 0
while true do
i += 1
statsd.set('example_metric.gauge', i, tags: ['environment:dev'])
sleep rand 10
end
{% /tab %}
{% tab title="Go" %}
package main
import (
"fmt"
"log"
"math/rand"
"time"
"github.com/DataDog/datadog-go/v5/statsd"
)
func main() {
statsd, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
var i float64
for true {
i += 1
statsd.Set("example_metric.set", fmt.Sprintf("%f", i), []string{"environment:dev"}, 1)
time.Sleep(time.Duration(rand.Intn(10)) * time.Second)
}
}
{% /tab %}
{% tab title="Java" %}
import com.timgroup.statsd.NonBlockingStatsDClientBuilder;
import com.timgroup.statsd.StatsDClient;
import java.util.Random;
public class DogStatsdClient {
public static void main(String[] args) throws Exception {
StatsDClient Statsd = new NonBlockingStatsDClientBuilder()
.prefix("statsd").
.hostname("localhost")
.port(8125)
.build();
for (int i = 0; true; i++) {
Statsd.recordSetValue("example_metric.set", i, new String[]{"environment:dev"});
Thread.sleep(random.NextInt(10000));
}
}
}
{% /tab %}
{% tab title=".NET" %}
using StatsdClient;
using System;
public class DogStatsdClient
{
public static void Main()
{
var dogstatsdConfig = new StatsdConfig
{
StatsdServerName = "127.0.0.1",
StatsdPort = 8125,
};
using (var dogStatsdService = new DogStatsdService())
{
if (!dogStatsdService.Configure(dogstatsdConfig))
throw new InvalidOperationException("Cannot initialize DogstatsD. Set optionalExceptionHandler argument in the `Configure` method for more information.");
var random = new Random(0);
for (int i = 0; true; i++)
{
dogStatsdService.Set("example_metric.set", i, tags: new[] {"environment:dev"});
System.Threading.Thread.Sleep(random.Next(100000));
}
}
}
}
{% /tab %}
{% tab title="PHP" %}
<?php
require __DIR__ . '/vendor/autoload.php';
use DataDog\DogStatsd;
$statsd = new DogStatsd(
array('host' => '127.0.0.1',
'port' => 8125,
)
);
$i = 0;
while (TRUE) {
$i++;
$statsd->set('example_metric.set', $i, 1, array('environment'=>'dev'), 'low');
sleep(rand(0, 10));
}
{% /tab %}
위 코드를 실행하면 메트릭 데이터를 Datadog에서 그래프로 표현할 수 있어요.
{% image source="https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/set.62e44368af8f538e464ebf16de768ad0.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/set.62e44368af8f538e464ebf16de768ad0.png?auto=format&fit=max&w=850&dpr=2 2x" alt="Set" /%}
HISTOGRAM
{% dl %}
{% dt %}
histogram(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
여러 메트릭이 제출되므로 저장되는 메트릭 타입(GAUGE, RATE)은 메트릭에 따라 달라져요. 자세한 내용은 HISTOGRAM 메트릭 타입 문서를 참고하세요.
{% /dd %}
{% /dl %}
구성
- Datadog으로 보낼 집계는 datadog.yaml 구성 파일의
histogram_aggregates파라미터로 설정해요. 기본적으로max,median,avg,count집계만 전송돼요. - Datadog으로 보낼 백분위 집계는 datadog.yaml 구성 파일의
histogram_percentiles파라미터로 설정해요. 기본적으로95pc백분위만 전송돼요.
코드 예시
HISTOGRAM 메트릭 타입은 DogStatsD에만 있는 타입이에요. HISTOGRAM 메트릭을 — GAUGE와 RATE 메트릭으로 저장되지만 — Datadog으로 전송해 보세요. HISTOGRAM 타입에 대한 자세한 내용은 메트릭 타입 문서에서 확인할 수 있어요.
아래 코드를 실행해 DogStatsD HISTOGRAM 메트릭을 Datadog에 제출해 보세요. 클라이언트를 더 이상 사용하지 않을 때는 flush/close를 호출하는 것을 잊지 마세요.
{% tab title="Python" %}
from datadog import initialize, statsd
import time
import random
options = {
'statsd_host':'127.0.0.1',
'statsd_port':8125
}
initialize(**options)
while(1):
statsd.histogram('example_metric.histogram', random.randint(0, 20), tags=["environment:dev"])
time.sleep(2)
{% /tab %}
{% tab title="Ruby" %}
require 'datadog/statsd'
statsd = Datadog::Statsd.new('localhost', 8125)
while true do
statsd.histogram('example_metric.histogram', rand 20, tags: ['environment:dev'])
sleep 2
end
{% /tab %}
{% tab title="Go" %}
package main
import (
"log"
"math/rand"
"time"
"github.com/DataDog/datadog-go/v5/statsd"
)
func main() {
statsd, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
for true {
statsd.Histogram("example_metric.histogram", float64(rand.Intn(20)), []string{"environment:dev"}, 1)
time.Sleep(2 * time.Second)
}
}
{% /tab %}
{% tab title="Java" %}
import com.timgroup.statsd.NonBlockingStatsDClientBuilder;
import com.timgroup.statsd.StatsDClient;
import java.util.Random;
public class DogStatsdClient {
public static void main(String[] args) throws Exception {
StatsDClient Statsd = new NonBlockingStatsDClientBuilder()
.prefix("statsd").
.hostname("localhost")
.port(8125)
.build();
while (true) {
Statsd.recordHistogramValue("example_metric.histogram", new Random().nextInt(20), new String[]{"environment:dev"});
Thread.sleep(2000);
}
}
}
{% /tab %}
{% tab title=".NET" %}
using StatsdClient;
using System;
public class DogStatsdClient
{
public static void Main()
{
var dogstatsdConfig = new StatsdConfig
{
StatsdServerName = "127.0.0.1",
StatsdPort = 8125,
};
using (var dogStatsdService = new DogStatsdService())
{
if (!dogStatsdService.Configure(dogstatsdConfig))
throw new InvalidOperationException("Cannot initialize DogstatsD. Set optionalExceptionHandler argument in the `Configure` method for more information.");
var random = new Random(0);
while (true)
{
dogStatsdService.Histogram("example_metric.histogram", random.Next(20), tags: new[] {"environment:dev"}, Cardinality: Cardinality.High);
System.Threading.Thread.Sleep(2000);
}
}
}
}
{% /tab %}
{% tab title="PHP" %}
<?php
require __DIR__ . '/vendor/autoload.php';
use DataDog\DogStatsd;
$statsd = new DogStatsd(
array('host' => '127.0.0.1',
'port' => 8125,
)
);
while (TRUE) {
$statsd->histogram('example_metric.histogram', rand(0, 20), 1, array('environment'=>'dev'), 'low');
sleep(2);
}
{% /tab %}
위 계측은 다음과 같은 메트릭을 생성해요.
| 메트릭 | 설명 |
|---|---|
example_metric.histogram.count |
이 메트릭이 샘플링된 횟수 |
example_metric.histogram.avg |
샘플링된 값의 평균 |
example_metric.histogram.median |
샘플링된 값의 중앙값 |
example_metric.histogram.max |
샘플링된 값의 최댓값 |
example_metric.histogram.95percentile |
95번째 백분위 샘플링 값 |
위 코드를 실행하면 메트릭 데이터를 Datadog에서 그래프로 표현할 수 있어요.
{% image source="https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/histogram.e9eda7db9deafde4720b0a22393c697f.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/histogram.e9eda7db9deafde4720b0a22393c697f.png?auto=format&fit=max&w=850&dpr=2 2x" alt="Histogram" /%}
TIMER
DogStatsD의 TIMER 메트릭 타입은 HISTOGRAM 메트릭 타입의 구현이에요(표준 StatsD의 타이머와 혼동하지 마세요). 코드의 한 섹션이 실행되는 데 걸린 시간 같은 타이밍 데이터만 측정해요.
{% dl %}
{% dt %}
timed(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
여러 메트릭이 제출되므로 저장되는 메트릭 타입(GAUGE, RATE)은 메트릭에 따라 달라져요. 자세한 내용은 HISTOGRAM 메트릭 타입 문서를 참고하세요.
{% /dd %}
{% /dl %}
구성
TIMER의 경우 HISTOGRAM 구성 규칙이 적용돼요.
코드 예시
TIMER 메트릭을 — GAUGE와 RATE 메트릭으로 저장되지만 — Datadog으로 전송해 보세요. HISTOGRAM 타입에 대한 자세한 내용은 메트릭 타입 문서에서 확인할 수 있어요. 클라이언트를 더 이상 사용하지 않을 때는 flush/close를 호출하는 것을 잊지 마세요.
{% tab title="Python" %} Python에서는 데코레이터로 타이머를 만든답니다.
from datadog import initialize, statsd
import time
import random
options = {
'statsd_host':'127.0.0.1',
'statsd_port':8125
}
initialize(**options)
@statsd.timed('example_metric.timer', tags=["environment:dev,function:my_function"])
def my_function():
time.sleep(random.randint(0, 10))
while(1):
my_function()
또는 컨텍스트 매니저를 사용해 만들 수도 있어요.
from datadog import statsd
import time
import random
def my_function():
# First some stuff you don't want to time
sleep(1)
# Now start the timer
with statsd.timed('example_metric.timer', tags=["environment:dev"]):
# do something to be measured
sleep(random.randint(0, 10))
while(1):
my_function()
{% /tab %}
{% tab title="PHP" %}
<?php
require __DIR__ . '/vendor/autoload.php';
use DataDog\DogStatsd;
$statsd = new DogStatsd(
array('host' => '127.0.0.1',
'port' => 8125,
)
);
function runfunction() {
sleep(rand(0, 20));
}
while (TRUE) {
$start_time = microtime(TRUE);
runfunction();
$statsd->microtiming('example_metric.timer', microtime(TRUE) - $start_time);
}
{% /tab %}
DogStatsD가 타이머 메트릭 데이터를 받으면 렌더링 시간의 통계적 분포를 계산해 다음 메트릭을 Datadog으로 전송해요.
| 메트릭 | 설명 |
|---|---|
example_metric.timer.count |
이 메트릭이 샘플링된 횟수 |
example_metric.timer.avg |
샘플링된 값의 평균 시간 |
example_metric.timer.median |
샘플링된 값의 중앙값 |
example_metric.timer.max |
샘플링된 값의 최댓값 |
example_metric.timer.95percentile |
95번째 백분위 샘플링 값 |
DogStatsD는 TIMER를 HISTOGRAM 메트릭으로 취급해요. TIMER나 HISTOGRAM 메트릭 타입 중 어느 것을 사용하든 Datadog에 같은 데이터를 보내는 거예요. 위 코드를 실행하면 메트릭 데이터를 Datadog에서 그래프로 표현할 수 있어요.
{% image source="https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/timer.0e38d350a03747f960f1ee0c9f08f2f5.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/metrics/custom_metrics/dogstatsd_metrics_submission/timer.0e38d350a03747f960f1ee0c9f08f2f5.png?auto=format&fit=max&w=850&dpr=2 2x" alt="Timer" /%}
DISTRIBUTION
{% dl %}
{% dt %}
distribution(<METRIC_NAME>, <METRIC_VALUE>, <TAGS>, <CARDINALITY>)
{% /dt %}
{% dd %}
Datadog에서 DISTRIBUTION 타입으로 저장돼요. 자세한 내용은 전용 Distribution 문서를 참고하세요.
{% /dd %}
{% /dl %}
코드 예시
DISTRIBUTION 메트릭 타입은 DogStatsD에만 있는 타입이에요. DISTRIBUTION 메트릭을 — 실제로는 DISTRIBUTION 메트릭으로 저장되지만 — Datadog으로 전송해 보세요. DISTRIBUTION 타입에 대한 자세한 내용은 메트릭 타입 문서에서 확인할 수 있어요.
아래 코드를 실행해 DogStatsD DISTRIBUTION 메트릭을 Datadog에 제출해 보세요. 클라이언트를 더 이상 사용하지 않을 때는 flush/close를 호출하는 것을 잊지 마세요.
{% tab title="Python" %}
from datadog import initialize, statsd
import time
import random
options = {
'statsd_host':'127.0.0.1',
'statsd_port':8125
}
initialize(**options)
while(1):
statsd.distribution('example_metric.distribution', random.randint(0, 20), tags=["environment:dev"])
time.sleep(2)
{% /tab %}
{% tab title="Ruby" %}
require 'datadog/statsd'
statsd = Datadog::Statsd.new('localhost', 8125)
while true do
statsd.distribution('example_metric.distribution', rand 20, tags: ['environment:dev'])
sleep 2
end
{% /tab %}
{% tab title="Go" %}
package main
import (
"log"
"math/rand"
"time"
"github.com/DataDog/datadog-go/v5/statsd"
)
func main() {
statsd, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
for true {
statsd.Distribution("example_metric.distribution", float64(rand.Intn(20)), []string{"environment:dev"}, 1)
time.Sleep(2 * time.Second)
}
}
{% /tab %}
{% tab title="Java" %}
import com.timgroup.statsd.NonBlockingStatsDClientBuilder;
import com.timgroup.statsd.StatsDClient;
import java.util.Random;
public class DogStatsdClient {
public static void main(String[] args) throws Exception {
StatsDClient Statsd = new NonBlockingStatsDClientBuilder()
.prefix("statsd").
.hostname("localhost")
.port(8125)
.build();
while (true) {
Statsd.recordDistributionValue("example_metric.distribution", new Random().nextInt(20), new String[]{"environment:dev"});
Thread.sleep(2000);
}
}
}
{% /tab %}
{% tab title=".NET" %}
using StatsdClient;
using System;
public class DogStatsdClient
{
public static void Main()
{
var dogstatsdConfig = new StatsdConfig
{
StatsdServerName = "127.0.0.1",
StatsdPort = 8125,
};
using (var dogStatsdService = new DogStatsdService())
{
if (!dogStatsdService.Configure(dogstatsdConfig))
throw new InvalidOperationException("Cannot initialize DogstatsD. Set optionalExceptionHandler argument in the `Configure` method for more information.");
var random = new Random(0);
while (true)
{
dogStatsdService.Distribution("example_metric.distribution", random.Next(20), tags: new[] {"environment:dev"});
System.Threading.Thread.Sleep(2000);
}
}
}
}
{% /tab %}
{% tab title="PHP" %}
<?php
require __DIR__ . '/vendor/autoload.php';
use DataDog\DogStatsd;
$statsd = new DogStatsd(
array('host' => '127.0.0.1',
'port' => 8125,
)
);
while (TRUE) {
$statsd->distribution('example_metric.distribution', rand(0, 20), 1, array('environment'=>'dev'), 'high');
sleep(2);
}
{% /tab %}
{% tab title="Node.js" %}
const tracer = require('dd-trace');
tracer.init();
while(true) {
tracer.dogstatsd.distribution('example_metric.distribution', Math.random() * 20, { environment: 'dev' });
await new Promise(r => setTimeout(r, 2000));
}
{% /tab %}
위 계측은 sum, count, average, minimum, maximum, 50th percentile(중앙값), 75th percentile, 90th percentile, 95th percentile, 99th percentile을 계산해요. Distribution은 업로드된 파일의 크기나 클래스 시험 점수처럼 어떤 유형의 값 분포든 측정하는 데 사용할 수 있어요.
메트릭 제출 옵션
샘플링 비율(Sample Rate)
UDP 패킷을 보내는 오버헤드는 성능이 중요한 일부 코드 경로에서 너무 클 수 있어서, DogStatsD 클라이언트는 샘플링(메트릭을 일정 비율로만 전송)을 지원해요. 많은 메트릭을 샘플링하고 DogStatsD 클라이언트가 DogStatsD 서버와 다른 호스트에 있을 때 유용하죠. 트레이드오프는 트래픽을 줄이는 대신 정밀도와 세분성이 다소 떨어진다는 거예요.
샘플링 비율 1은 메트릭을 100%의 시간 동안 전송하고, 샘플링 비율 0은 0%의 시간 동안만 전송해요.
Datadog에 메트릭을 보내기 전에 DogStatsD는 <SAMPLE_RATE>를 사용해 메트릭 타입에 따라 메트릭 값을 보정해요(샘플링 없이 값을 추정하기 위해).
| 메트릭 타입 | 샘플링 비율 보정 |
|---|---|
COUNT |
수신된 값에 (1/<SAMPLE_RATE>)를 곱해요. 수신된 하나의 datapoint에 대해 1/<SAMPLE_RATE>만큼이 실제로 같은 값으로 샘플링되었다고 가정하는 게 합리적이에요. |
GAUGE |
보정 없음. 수신된 값을 그대로 유지해요. |
SET |
보정 없음. 수신된 값을 그대로 유지해요. |
HISTOGRAM |
histogram.count 통계는 COUNT 메트릭이며 위에 설명한 보정을 받아요. 나머지 통계는 gauge 메트릭이라 "보정"되지 않아요. |
DISTRIBUTION |
수신된 값에 (1/<SAMPLE_RATE>)를 곱해 계산해요. 수신된 하나의 datapoint에 대해 1/<SAMPLE_RATE>만큼이 실제로 같은 값으로 샘플링되었다고 가정하는 게 합리적이에요. |
코드 예시
다음 코드는 절반의 시간 동안만 포인트를 전송해요.
{% tab title="Python" %}
statsd.increment('loop.count', sample_rate=0.5)
{% /tab %}
{% tab title="Ruby" %}
statsd.increment('loop.count', :sample_rate => 0.5)
{% /tab %}
{% tab title="Go" %}
statsd.Incr("example_metric.increment", []string{}, 0.5)
{% /tab %}
{% tab title="Java" %}
Statsd.incrementCounter("example_metric.increment", sampleRate=0.5);
{% /tab %}
{% tab title=".NET" %}
dogStatsdService.Increment("example_metric.increment", sampleRate: 0.5);
{% /tab %}
{% tab title="PHP" %}
<? php
$statsd->increment('example_metric.increment', $sampleRate->0.5);
{% /tab %}
메트릭 태깅(Metric Tagging)
DogStatsD로 보내는 모든 메트릭에 tags 파라미터로 태그를 추가할 수 있어요.
코드 예시
다음 코드는 example_metric.increment 메트릭에 environment:dev와 account:local 태그만 추가해요.
{% tab title="Python" %}
statsd.increment('example_metric.increment', tags=["environment:dev","account:local"])
{% /tab %}
{% tab title="Ruby" %}
statsd.increment('example_metric.increment', tags: ['environment:dev','account:local'])
{% /tab %}
{% tab title="Go" %}
statsd.Incr("example_metric.increment", []string{"environment:dev","account:local"}, 1)
{% /tab %}
{% tab title="Java" %}
Statsd.incrementCounter("example_metric.increment", new String[]{"environment:dev","account:local"});
{% /tab %}
{% tab title=".NET" %}
dogStatsdService.Increment("example_metric.increment", tags: new[] {"environment:dev","account:local"})
{% /tab %}
{% tab title="PHP" %}
tags 인수는 문자열이 될 수 있어요.
$statsd->increment('example_metric.increment', 1.0, "environment:dev,account:local");
또는 배열이 될 수 있어요.
<?php
$statsd->increment('example_metric.increment', 1.0, array('environment' => 'dev', 'account' => 'local'));
{% /tab %}
{% tab title="Node.js" %}
tracer.dogstatsd.increment('example_metric.increment', 1, { environment: 'dev', account: 'local' });
{% /tab %}
호스트 태그(Host Tag)
호스트 태그는 메트릭을 집계하는 Datadog Agent가 자동으로 할당해요. Agent의 호스트 이름과 일치하지 않는 호스트 태그로 제출된 메트릭은 원래 호스트에 대한 참조를 잃게 돼요. 제출된 호스트 태그는 Agent에서 수집하거나 구성한 호스트 이름을 덮어씁니다.
더 알아보기 (Learn more)
추가로 도움이 되는 문서, 링크, 글: