Skip to content

Instantly share code, notes, and snippets.

@patbl
Last active November 5, 2022 15:38
Show Gist options
  • Save patbl/cb73d9865c330d2df426a0661b7c5204 to your computer and use it in GitHub Desktop.
Save patbl/cb73d9865c330d2df426a0661b7c5204 to your computer and use it in GitHub Desktop.
Script to add custom tag groups to all StatsD-reported Datadog metrics. Don't run it unless you understand what it does. Tags in `TAGS_TO_EXCLUDE` are excluded from the custom tag groups.
# frozen_string_literal: true
require 'datadog_api_client'
require 'json'
class AddCustomTagGroups
ALL_METRICS_FILE = "metrics.txt"
METRIC_TYPES_FILE = "metric_types.json"
METRIC_TAGS_FILE = "metric_tags.json"
TAGS_TO_EXCLUDE = [
# Put the names of tags you want to exclude here! Otherwise this script won't be useful.
]
def call
statsd_metric_types.each_key.with_index do |metric, i|
puts "#{metric} #{i} of #{statsd_metric_types.size}"
tags_for_metric = metric_tags[metric]
if tags_for_metric.nil? || tags_for_metric.empty?
puts "no tags for metric #{metric.inspect}"
next
end
tags_to_keep = tags_for_metric.to_a - TAGS_TO_EXCLUDE
body = DatadogAPIClient::V2::MetricTagConfigurationCreateRequest.new(
{
data: DatadogAPIClient::V2::MetricTagConfigurationCreateData.new(
{
id: metric,
type: DatadogAPIClient::V2::MetricTagConfigurationType::MANAGE_TAGS,
attributes: {
tags: tags_to_keep,
metric_type: statsd_metric_types.fetch(metric).fetch("type")
},
}
)
}
)
attempts = 0
begin
attempts += 1
# Create a tag configuration
result = api_instance_v2.create_tag_configuration(metric, body)
p result
rescue DatadogAPIClient::V2::APIError => e
puts "Error when calling MetricsAPI->create_tag_configuration: #{e}"
if e.code == 429 && attempts < 3
puts "rate-limited; retrying"
sleep 60
retry
end
end
sleep 1
end
end
def metric_tags
return @metric_tags if defined?(@metric_tags)
unless File.exist?(METRIC_TAGS_FILE)
metric_tags = statsd_metric_types.each_key.with_index.with_object({}) do |(metric, i), metric_tags|
puts "#{i} of #{statsd_metric_types.size}"
sleep 60.fdiv(50) + 0.1
response = api_instance_v2.list_tags_by_metric_name(metric)
tags = response.data.attributes.tags
tag_keys = tags.each_with_object(Set.new) { |tag, set| set << tag.split(":")[0] }
metric_tags[metric] = tag_keys.to_a
rescue DatadogAPIClient::V2::APIError
puts "error, retrying"
sleep 60
retry
end
File.write(METRIC_TAGS_FILE, JSON.pretty_generate(metric_tags))
end
@metric_tags = JSON.parse(File.read(METRIC_TAGS_FILE))
end
def all_metrics
return @all_metrics if defined?(@all_metrics)
unless File.exist?(ALL_METRICS_FILE)
from = Integer(Time.now - 3600 * 24) # 1 day ago
response = api_instance.list_active_metrics(from)
metrics = response.metrics
File.open(ALL_METRICS_FILE, "w") do |file|
metrics.each do |metric|
file.puts(metric)
end
end
end
@all_metrics = File.readlines(ALL_METRICS_FILE, chomp: true)
end
def metric_types
return @metric_types if defined?(@metric_types)
unless File.exist?(METRIC_TYPES_FILE)
metric_types = {}
all_metrics.each_with_index do |metric, i|
response = api_instance.get_metric_metadata(metric)
metric_types[metric] = response.to_hash
end
File.write(METRIC_TYPES_FILE, JSON.pretty_generate(metric_types))
end
@metric_types = JSON.parse(File.read(METRIC_TYPES_FILE))
end
def api_instance
@api_instance ||= DatadogAPIClient::V1::MetricsAPI.new
end
def api_instance_v2
return @api_instance_v2 if defined?(@api_instance_v2)
DatadogAPIClient::V2.configure do |config|
config.unstable_operations[:create_tag_configuration] = true
config.unstable_operations[:list_tag_configuration_by_name] = true
end
@api_instance_v2 = DatadogAPIClient::V2::MetricsAPI.new
end
def statsd_metric_types
@statsd_metric_types ||= metric_types.select do |name, attrs|
attrs.key?("statsd_interval")
end
end
end
AddCustomTagGroups.new.call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment