Datadogには様々な料金が存在しますが、それぞれ年払い、月払い、従量課金が存在します。
何もしなければ従量課金で支払いが発生しますが、すでに動いているサービスなど前もって使うと分かっているものは、年払いや月払いにすることで費用の削減を行うことができます。
しかし、ここで問題になるのは利用する量が時間によって変動するプロダクトです。
例としては、日本の社会人が働いてる時に利用するサービスであれば平日の8時~19時くらいの利用料が多く、それ以外の時間帯が少ないなどといったものです。
上記の例の場合、休日や深夜といったピーク外は少ないインスタンス数で動作するけど、ピークタイムはその〇倍インスタンスが必要、というケースもあります。
この場合、ピーク外でも動作している分のインスタンスは月払いもしくは年払いで契約し、ピークタイムに必要な追加分はオンデマンドで対応するのがコスト効率的です。
ただ、ピークタイムとオフピークで明確に分かれているわけではなく1日のりよう波を打つような線になるので、どの程度定額払いにするかは悩みどころになります。
今回は直近の利用状況から、どれくらいの量をコミットすればいいのか計算してみます。
直近の利用状況を確認する
ログイン後、Plan & Usage
のページに行き、Usage & Cost
タブを開きます。
ページ下にあるUsage Trends
の項目のセレクトボックスをYearlyにして、Download as CSV
をクリックして直近1年の利用履歴をDLします。
`
最適な料金を求めていくスクリプトを作成する
実際に今から計算する簡単なscriptをrubyで作成します。
今回は、例として2024年11月のAPM Fargate Tasks
の最適なコミット量を出してみます。
CSVにはOrganization
、Name
、Public ID
、Hour
、Product Name
、Aggregation
の6つの情報が入っています。
今回はHour
、Product Name
、から2024年11月のAPM Fargate Tasks
のUsage
を抽出します。
まず抽出までのスクリプトを組んでみましょう。
def extract_usages(year, month, product_name)
row_count = 0
array = []
CSV.foreach('csv/sample.csv', headers: true) do |row|
hour = row['Hour']
usage = row['Usage']
next unless hour.include?("#{year}-#{month}-") && row['Product Name'] == product_name
row_count += 1
array << usage.to_i
end
return array
end
usages = (2024, 12, 'APM Fargate Tasks')
これで2024年11月のusageが手に入りました。本格的に計算をしていきます。
APM Fargate Tasks
の料金は https://www.datadoghq.com/ja/pricing/list/ より、以下のようになっています。
- 年払い: 1taskあたり一月1.25USD
- 月払い: 1taskあたり一月1.50USD
- オンデマンド: 1taskあたり一月1.75USD
今回は以下の料金表から月払いの場合のコミット量を計算することにします。もし個別で契約している場合はPlanページを見ると何円で計算すると良いか書いてあります。
Datadogの料金は1時間ごとに計算され、APM Fargate Tasks
の場合以下の式で表されます。
時刻tのオンデマンド料金 = max(0, 時刻tのusage-コミット量) * 1時間あたりのオンデマンド料金
上記の計算を一月分行って算出したオンデマンド料金にコミット量 x 月払い料金を足すと、特定のコミット量の時の月額利用料を算出することができます。
あとは各コミット量の時の利用料を計算して、一番小さい利用料金になるコミット量を算出します。
ここまで踏まえるとコードは以下のようになります。
# frozen_string_literal: true
require 'csv'
def extract_usages(year, month, product_name, file_name)
row_count = 0
array = []
CSV.foreach(file_name, headers: true) do |row|
hour = row['Hour']
usage = row['Usage']
next unless hour.include?("#{year}-#{month}-") && row['Product Name'] == product_name
row_count += 1
array << usage.to_i
end
return array
end
def calculate_commit_quantity(usages, ondemand_price_per_month, commit_cost_per_month)
min_commit_quantity_candidate = usages.min
max_commit_quantity_candidate = usages.max
min_costs = Float::INFINITY
min_commit_quantity = -1
hours = usages.size
(max_commit_quantity_candidate - max_commit_quantity_candidate + 1).times do |i|
commit_quantity = min_commit_quantity_candidate + i
ondemand_costs = usages.map { |usage| usage - commit_quantity > 0 ? (usage - commit_quantity) * ondemand_price_per_month / hours : 0 }.sum
cost = commit_quantity * commit_cost_per_month + ondemand_costs
if min_costs > cost
min_costs = cost
min_commit_quantity = commit_quantity
end
end
puts "Min cost commit quantity: #{min_commit_quantity} commit(#{min_costs})$"
end
usages = extract_usages(2024, 11, 'APM Fargate Tasks', 'csv/sample.csv')
calculate_commit_quantity(usages, 1.75, 1.5)
実行すると以下のような出力が得られます。(値はダミーを入れています。)
❯ ruby main.rb
Min cost commit quantity: 43 commit(100.2)$
まとめ
今回は過去の利用料からコミット量を試算するスクリプトを作成してみました。
年間払いにするときなどは可能な限り正確に見積もって、安くするための取り組みが必要になるので、直近の利用料からしっかり計算して必要な分だけコミットするようにしましょう。