Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ coverage:
target: 75
flags:
- azure_iot_edge
BentoML:
target: 75
flags:
- bentoml
Boundary:
target: 75
flags:
Expand Down Expand Up @@ -884,6 +888,11 @@ flags:
paths:
- azure_iot_edge/datadog_checks/azure_iot_edge
- azure_iot_edge/tests
bentoml:
carryforward: true
paths:
- bentoml/datadog_checks/bentoml
- bentoml/tests
boundary:
carryforward: true
paths:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/config/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ integration/azure_active_directory:
- azure_active_directory/**/*
integration/azure_iot_edge:
- azure_iot_edge/**/*
integration/bentoml:
- bentoml/**/*
integration/beyondtrust_identity_security_insights:
- beyondtrust_identity_security_insights/**/*
integration/beyondtrust_password_safe:
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/test-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,25 @@ jobs:
minimum-base-package: ${{ inputs.minimum-base-package }}
pytest-args: ${{ inputs.pytest-args }}
secrets: inherit
j5a8a3b3:
uses: ./.github/workflows/test-target.yml
with:
job-name: BentoML
target: bentoml
platform: linux
runner: '["ubuntu-22.04"]'
repo: "${{ inputs.repo }}"
python-version: "${{ inputs.python-version }}"
latest: ${{ inputs.latest }}
agent-image: "${{ inputs.agent-image }}"
agent-image-py2: "${{ inputs.agent-image-py2 }}"
agent-image-windows: "${{ inputs.agent-image-windows }}"
agent-image-windows-py2: "${{ inputs.agent-image-windows-py2 }}"
test-py2: ${{ inputs.test-py2 }}
test-py3: ${{ inputs.test-py3 }}
minimum-base-package: ${{ inputs.minimum-base-package }}
pytest-args: ${{ inputs.pytest-args }}
secrets: inherit
jfcf4b1a:
uses: ./.github/workflows/test-target.yml
with:
Expand Down
4 changes: 4 additions & 0 deletions bentoml/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# CHANGELOG - BentoML

<!-- towncrier release notes start -->

60 changes: 60 additions & 0 deletions bentoml/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Agent Check: BentoML

## Overview

This check monitors [BentoML][1] through the Datadog Agent.

Include a high level overview of what this integration does:
- What does your product do (in 1-2 sentences)?
- What value will customers get from this integration, and why is it valuable to them?
- What specific data will your integration monitor, and what's the value of that data?

## Setup

Follow the instructions below to install and configure this check for an Agent running on a host. For containerized environments, see the [Autodiscovery Integration Templates][3] for guidance on applying these instructions.

### Installation

The BentoML check is included in the [Datadog Agent][2] package.
No additional installation is needed on your server.

### Configuration

1. Edit the `bentoml.d/conf.yaml` file, in the `conf.d/` folder at the root of your Agent's configuration directory to start collecting your bentoml performance data. See the [sample bentoml.d/conf.yaml][4] for all available configuration options.

2. [Restart the Agent][5].

### Validation

[Run the Agent's status subcommand][6] and look for `bentoml` under the Checks section.

## Data Collected

### Metrics

See [metadata.csv][7] for a list of metrics provided by this integration.

### Events

The BentoML integration does not include any events.

### Service Checks

The BentoML integration does not include any service checks.

See [service_checks.json][8] for a list of service checks provided by this integration.

## Troubleshooting

Need help? Contact [Datadog support][9].


[1]: **LINK_TO_INTEGRATION_SITE**
[2]: https://app.datadoghq.com/account/settings/agent/latest
[3]: https://docs.datadoghq.com/containers/kubernetes/integrations/
[4]: https://github.com/DataDog/integrations-core/blob/master/bentoml/datadog_checks/bentoml/data/conf.yaml.example
[5]: https://docs.datadoghq.com/agent/configuration/agent-commands/#start-stop-and-restart-the-agent
[6]: https://docs.datadoghq.com/agent/configuration/agent-commands/#agent-status-and-information
[7]: https://github.com/DataDog/integrations-core/blob/master/bentoml/metadata.csv
[8]: https://github.com/DataDog/integrations-core/blob/master/bentoml/assets/service_checks.json
[9]: https://docs.datadoghq.com/help/
15 changes: 15 additions & 0 deletions bentoml/assets/configuration/spec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: BentoML
files:
- name: bentoml.yaml
options:
- template: init_config
options:
- template: init_config/openmetrics
- template: instances
options:
- template: instances/openmetrics
overrides:
openmetrics_endpoint.value.example: http://localhost:3000/metrics
openmetrics_endpoint.description: |
Endpoint exposing the BentoML Prometheus metrics. For more information refer to:
https://docs.bentoml.com/en/latest/build-with-bentoml/observability/metrics.html
8 changes: 8 additions & 0 deletions bentoml/assets/dashboards/placeholder.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"author_name": "Datadog",
"description": null,
"layout_type": "ordered",
"template_variables": null,
"title": "Steven's Dashboard Thu, Jul 10, 3:44:27 pm",
"widgets": []
}
2 changes: 2 additions & 0 deletions bentoml/changelog.d/21232.added
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add BentoML integration

4 changes: 4 additions & 0 deletions bentoml/datadog_checks/bentoml/__about__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# (C) Datadog, Inc. 2025-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
__version__ = '0.0.1'
7 changes: 7 additions & 0 deletions bentoml/datadog_checks/bentoml/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# (C) Datadog, Inc. 2025-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
from .__about__ import __version__
from .check import BentomlCheck

__all__ = ['__version__', 'BentomlCheck']
57 changes: 57 additions & 0 deletions bentoml/datadog_checks/bentoml/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# (C) Datadog, Inc. 2025-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
from urllib.parse import urlparse, urlunparse

from datadog_checks.base import OpenMetricsBaseCheckV2
from datadog_checks.bentoml.metrics import ENDPOINT_METRICS, METRICS


class BentomlCheck(OpenMetricsBaseCheckV2):
__NAMESPACE__ = 'bentoml'
DEFAULT_METRIC_LIMIT = 0

def __init__(self, name, init_config, instances):
super(BentomlCheck, self).__init__(name, init_config, instances)
self.openmetrics_endpoint = self.instance.get('openmetrics_endpoint')
self.base_url = self._extract_base_url(self.openmetrics_endpoint) if self.openmetrics_endpoint else None
self.tags = self.instance.get('tags', [])

def _extract_base_url(self, endpoint):
parsed = urlparse(endpoint)
path = parsed.path.rstrip('/')
base_path = path.rsplit('/', 1)[0] if '/' in path else ''
return urlunparse(parsed._replace(path=base_path or '/'))

def get_default_config(self):
return {
'openmetrics_endpoint': self.openmetrics_endpoint,
'metrics': [METRICS],
}

def check(self, instance):
super(BentomlCheck, self).check(instance)
if self.base_url:
self.check_health_endpoint()

def check_health_endpoint(self):
for endpoint_path, metric_name in ENDPOINT_METRICS.items():
try:
url = f"{self.base_url}{endpoint_path}"
response = self.http.get(url)
response.raise_for_status()

tags = [*self.tags, f"status_code:{response.status_code}"]
self.gauge(metric_name, 1, tags=tags)
self.log.debug("Successfully checked %s at %s", metric_name, url)
except Exception as e:
status_code = None
if hasattr(e, 'response') and e.response is not None:
status_code = getattr(e.response, 'status_code', None)

tags = [*self.tags]
if status_code is not None:
tags.append(f"status_code:{status_code}")

self.log.debug("Failed to check %s at %s: %s", metric_name, url, str(e))
self.gauge(metric_name, 0, tags=tags)
24 changes: 24 additions & 0 deletions bentoml/datadog_checks/bentoml/config_models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# (C) Datadog, Inc. 2025-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

# This file is autogenerated.
# To change this file you should edit assets/configuration/spec.yaml and then run the following commands:
# ddev -x validate config -s <INTEGRATION_NAME>
# ddev -x validate models -s <INTEGRATION_NAME>

from .instance import InstanceConfig
from .shared import SharedConfig


class ConfigMixin:
_config_model_instance: InstanceConfig
_config_model_shared: SharedConfig

@property
def config(self) -> InstanceConfig:
return self._config_model_instance

@property
def shared_config(self) -> SharedConfig:
return self._config_model_shared
132 changes: 132 additions & 0 deletions bentoml/datadog_checks/bentoml/config_models/defaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# (C) Datadog, Inc. 2025-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

# This file is autogenerated.
# To change this file you should edit assets/configuration/spec.yaml and then run the following commands:
# ddev -x validate config -s <INTEGRATION_NAME>
# ddev -x validate models -s <INTEGRATION_NAME>


def shared_skip_proxy():
return False


def shared_timeout():
return 10


def instance_allow_redirects():
return True


def instance_auth_type():
return 'basic'


def instance_cache_metric_wildcards():
return True


def instance_cache_shared_labels():
return True


def instance_collect_counters_with_distributions():
return False


def instance_collect_histogram_buckets():
return True


def instance_disable_generic_tags():
return False


def instance_empty_default_hostname():
return False


def instance_enable_health_service_check():
return True


def instance_histogram_buckets_as_distributions():
return False


def instance_ignore_connection_errors():
return False


def instance_kerberos_auth():
return 'disabled'


def instance_kerberos_delegate():
return False


def instance_kerberos_force_initiate():
return False


def instance_log_requests():
return False


def instance_min_collection_interval():
return 15


def instance_non_cumulative_histogram_buckets():
return False


def instance_persist_connections():
return False


def instance_request_size():
return 16


def instance_skip_proxy():
return False


def instance_tag_by_endpoint():
return True


def instance_telemetry():
return False


def instance_timeout():
return 10


def instance_tls_ignore_warning():
return False


def instance_tls_use_host_header():
return False


def instance_tls_verify():
return True


def instance_use_latest_spec():
return False


def instance_use_legacy_auth_encoding():
return True


def instance_use_process_start_time():
return False
Loading
Loading