Nature Remo Eを使って、消費電力をNew Relicに送信する

Hey, NewRelic Advent Calendar 2020 - Qiita, 15日目の記事だよ!時差があるのは気にしないで!

電力消費量が気になる季節がやってまいりました。ということで、Nature Remo Eを使って電力消費マネジメントの第一歩目である「計測せよ」にチャレンジしてみます。

Nature Remo Eを買う

買ってください

Nature API Tokenを取得する

Remo Eを良い感じにセットアップしていただいて、 https://home.nature.global/ にログインしたらなんとなくtokenが発行できます。

New Relicに情報を送る

電力消費情報をNew Relicに送ることで、アラートを設定して不測の事態に対応したり、パフォーマンスを可視化し、コストをコントロールするためのインサイトを得たりができるようになります。

New Relicに情報を送る方法はいくつかあります。Infrastructureエージェントを動かしているならnri-flex設定はシンプルなのでおすすめではありますが、せっかくなので2020年春あたりから整備されてきた新しいNew Relic Metrics APIを使って、情報を送ることにしましょう。

Nature APIから情報を持ってくる

go-remoeというライブラリがなんとすでにあるので、ありがたく使ってみることにします。解説のブログ記事を見た感じでは、以下2つが候補になります:

  • 瞬時消費電力: その瞬間の消費電力。スピードメーター的なもの。
  • 期間当り(たとえば1分当り)の消費電力: ある期間の消費電力を出すためには、期間終了時の積算消費電力から期間開始時の積算消費電力を良い感じに(正方向と逆方向を適当に)引く必要がある。

瞬時消費電力は扱いが簡単そうです。一方、期間の消費電力を扱うにはなんかちょっと計算をする必要があるようで、うーんなかなか難しい。とりあえず生のデータだけNew Relicに送っておいて、計算は後で考えることにしましょう。

計測・送信間隔は雰囲気的に1分毎を想定してみます。crontabで毎分実行させたり、現代的にはAWSCloudWatch Eventsを使って毎分Lambdaをinvokeさせるような想定です(Lambda Handlerへの実装は、読者の課題とする)。

New Relicに送る

New Relic Metrics APIを眺めてみると、Metrics APIを直接使う方法や、各言語のテレメトリSDK経由で送る方法にたどり着きます。そのあたりから、newrelic-telemetry-sdk-goにたどり着いてみましょう。

メトリックは3種類あると記載されています:

Basic type Aggregated type Description Example
Gauge(ゲージ) AggregatedGauge ある時点での単一の値 部屋の温度
Count(カウント) AggregatedCount 何らかのイベントが起こった回数を記録する エラーの発生回数
Summary(サマリー) AggregatedSummary ある時間間隔における、カウント、合計、最小、最大を記録する 1分あたりのHTTPリクエストのスループットやレスポンスタイムを記録する

Remo Eで取得できる値は、いずれもある瞬間での値なので、とりあえずゲージとして突っ込んでおきましょう。

コードはこうなりました。Nature API Token, New Relic Insert APIはそれぞれ、環境変数として設定しています。

package main

import (
    "context"
    "github.com/reeve0930/go-remoe"
    "github.com/newrelic/newrelic-telemetry-sdk-go/telemetry"
    "time"

    "os"
)

func main() {
    token := os.Getenv("NATURE_API_TOKEN")
    remoClient := remoe.NewClient(token)
    hervester, _ := telemetry.NewHarvester(telemetry.ConfigAPIKey(os.Getenv("NEW_RELIC_INSERT_API_KEY")))

    data, _ := remoClient.GetRawData()
    for _, d := range data {
        hervester.RecordMetric(telemetry.Gauge{
            Timestamp: time.Now(),
            Value:     float64(d.MeasuredInstantaneous),
            Name:      "remoe.MeasuredInstantaneous",
            Attributes: map[string]interface{}{
            "modelId": d.ModelID,
        },
        })
    }
    hervester.HarvestNow(context.Background())
}

New Relicで見てみる

New Relic Oneを開いて、右上のQuery Your Dataからメトリックの情報をクエリできます。Data Explorerから行っても良いですし、たとえばNRQLはこんな感じに発行してみましょう。

FROM Metric SELECT average(remoe.MeasuredInstantaneous) facet modelId TIMESERIES 

f:id:katzchang:20201216024445p:plain
データが良い感じに表示されている様子

データが突っ込まれましたね!

まとめ

こんな感じに、コンパクトなスクリプトでNew Relicにメトリック情報を放り込むことができるという例でした。コード全体はnewrelic-remoeで公開していますので、ご参考になれば幸いです。詳細が気になる方は@katzchangまでメンションなどいただければと思います。仕事だぜm,

キーボードを作ってみた話を書きます

こんにちは、pyspa Advent Calendar 2020の3日目の投稿になります。

今年の思い出としては長らく続く在宅勤務だと思いますし、みなさんもいろいろなガジェットで在宅勤務を成功に導いていらっしゃることと存じております。

ということで、キーボードを作りました。pyspaの皆さまにはお世話になりました。

f:id:katzchang:20201109220044j:plain
イメージ図

背景

決断に至るストーリーはだいたいこんな感じです:

  • Macbook Proのキーボードをそのまま使っていたが、温度が熱くなりがちなので、夏にめっちゃストレスが高まった
  • 会社支給でMagic KeyboardとTrackpadがもらえるので届けてもらったが、今ひとつポジションが定まらなかった
  • Samuraismさんの#MAGICTRAYPALMが良いらしいと聞き、Magic Keyboard対応の試作品を送ってもらった(ありがとうございます!!)が、残念ながらあまり手になじまず(Magic Keyboardは薄くて強度設計が難しいとのこと)

以前から分割キーボードに興味があったこともあり、もうこれは移ってしまおうということであれしました。

買い物

キーボードは主に遊舎工房の物理店舗で買いました。通販じゃパーツの声が聞こえないだろ?*1

工具は主にAmazonで買いました。ぴえんキーキャップはKochi Keyboardから。

キーボード

  • Ergodash mini: 分割で数字キーなしを選びたかった(以前から数字キー打鍵が苦手だった)
  • Sakurio: 静音で軽
  • R2 XDA 40v2 Dye-sub keycaps: 地味めだけどかわいい
  • マグネットでつながるUSBケーブル: チップのUSB端子が壊れやすいらしいので便利とのこと
  • リストレスト: 分割キーボード用のやつを贅沢にも2つ横につなげて、ダラっと手首を乗せられるようにしてます。サイズ感をたしかめるために、まずはそのへんの本とかで試すと良い。
  • ぴえんキーキャップ: 🥺、日本語変換キーに実用してしまってる。手触りで判別できるので意外と便利。

一度加工で失敗したので、ダイオードをAmazonで別途追加注文とかしてます。LEDキラキラは難しそうなので付けていません。

工具と消耗品

あとは家にあったニッパーとか、作業台みたいなのもあるといい。木の板をつかいました。

工作

いろいろあった*2けど頑張った。

f:id:katzchang:20200924161035j:plainf:id:katzchang:20200924174852j:plainf:id:katzchang:20200924180813j:plainf:id:katzchang:20200924211353j:plainf:id:katzchang:20200925213439j:plainf:id:katzchang:20200925223933j:plain
加工頑張ったイメージ図

結果と今後

腱鞘炎が遠ざかり、姿勢が良くなったと言われました。今後は無線化したいけどうまく動かない。

以上、よろしくお願いいたします。

Ward Cunningham, the creator of the concept of technical debt, explained by himself.

This translation post is published under CC BY 3.0 based on the original article.

"Technical Debt" has been a hot topic in the world of system development, and is often on fire.

The creator of the concept of technical debt is Ward Cunningham. In 1992, he compared the first release of the code to debt in the Experience Report of the object-oriented international conference OOPSLA '92 ("Shipping first time code is like going into debt").

Ward Cunningham has made many contributions to the software world. He was the inventor of the Wiki, a mentor of XP and TDD's father Kent Beck, who imported the "pattern language" of the architectural world into the software with Kent Beck, also the one of the member of "Manifesto for Agile Software Development" (for more information, see "パターン、Wiki、XP ~時を超えた創造の原則" or blog articles "君はWard Cunninghamを知っているか? 前篇後篇").

So, what was behind the idea that Ward invented the concept of technical debt? What did he think and why did he come up with this concept? In fact, Ward posted a little less than a five-minute video on YouTube in 2009 explaining the background of technical debt.

www.youtube.com

And the transcript of this video is posted on wiki.c2.com (that Ward himself first world developed Wiki), I have translated it as follows.

[Translation] Debt metaphor.

(The wiki translation follows in the original article.)

After the translation

What's surprising is that what Ward Cunningham is saying is quite different from the "technical debt" we envision.

The image we have in the term "technical debt" might be "crudely written code that prioritizes the release, and is left over without a clean rewrite" or "technical foundation (language, infrastructure or framework) that has become old". Or, Wikipedia in Japanese article states that "The Consequences of Haphazard Software Architecture and Unprepared Software Development". But these come from misunderstanding, Ward says.

According to Ward, the negative impact of debt is the productivity loss caused by the disconnect between the understanding gained with development and the system you are facing, not the maintainability (or clutter) of the code you're writing. Rather, he says, you should always do the best you can at the time when you're writing code.

For Ward, the debt repayment method is refactoring, and the purpose of refactoring is to eliminate the gap between their domain knowledge and the current program. In other words, this refactoring can be said to be something like “Refactoring toward deeper insight” in domain-driven design (DDD). The theme for domain-driven design is "to tackle the core complexity of software", as you know. Of course, the scope of resolving deviations is not only limited to refactoring, but also includes rearchitecting, I think.

The word "debt" tends to be more positive (as in capital) for those closer to management, and more negative (as in loans) for those closer to technology. The debt metaphor Ward is talking about is rather positive. The development approach of releasing software quickly and repeatedly, and learning from experience and hypothesis testing, is becoming more and more common today. In addition, Ward's use of the debt metaphor came about because he and the person he was describing happened to be developing the same financial software. But then, the strong word "debt" may have walked alone and created the current impression of technical debt.

By the way, the WyCash refactoring that led Ward to create the debt metaphor was a strong inspiration to Kent Beck and would appear in his later work, Test-Driven Development (Ward is the protagonist of the Introduction of the book, and the theme of Part 1, "Multilateral Currencies," is based on WyCash's domain objects).

And, Ward consistently says only "Debt" without "Technical". Now, I'm also curious who and why added "Technical", but I would like to quickly bring the translation to the world first.

メンテナンスウィンドウを使わない

6年ほど無停止のサービスを運用してきた私の経験からすると、メンテナンスウィンドウ、つまり計画的メンテナンスに対するアラート発砲を抑制する機能は、使わないほうがうまくいく。仕事の中でも度々メンテナンスウィンドウの話題が出てきたので、個人の見解としてまとめてみたい。

計画的メンテナンスの手順

対外的に無停止だとしても、内部的には停止を伴うメンテナンスをすることがある。たとえば、MySQLを止めることはたまにある。まずは、どのようにメンテナンスを進めていくのかを整理しよう。

内部的な停止を伴うメンテナンスの際は作業に必要な時間とともに、アラートが起こる範囲を予測し、予告しておく。予告の範囲を決めるのは単純で、アラートが届くだろうチャンネルにお知らせしておけばいい。以前のチームではメールとSlackチャンネルを使っていたので、そこに書いていた。準備はこれでいい。

メンテナンス作業が始まる(たとえばMySQLをフェイルオーバーさせる)と、何らかのアラートが出る。メンテナンスチームはAcknowledgeを送るのも良い。予告通りであれば、アラートを受けた人は作業を気にしつつ、作業がうまく進むことを期待するだろう。作業が終わり、サービスが動き出し、アラートが緑に変わる。平和な世界が戻る。

普通でしょ?

意図的にアラートを出す利点

予めアラートを抑制する手順と比較して、いくつかの利点がある。

アラートが適切に設定されていることを確認できる

内部サービス停止のアラートは滅多に起こるものではない。一度も発砲されていないアラートは適切に設定されていることを確認する手段はない。設定画面を注意深く見るくらい?人間の目は信用しないほうがいい。停止する範囲から期待されるアラートを洗い出して、実際に発砲されることを確かめよう。

メンテナンス終了がすぐに伝わる

予想していたよりも早く作業が終わった場合、アラートが収まることで必要な通知をすることができる。「メンテナンスは無事終わりました!」っていうお知らせを急がなくて良くなる。

手間が減る

メンテナンスウィンドウを適切に設定する手間を惜しむのは悪いことじゃない。俺たちは忙しいんだ!

まとめ

意図的にアラートを出す計画的メンテナンスの手法と利点について書いてみた。

もちろん、メンテナンスウィンドウを欲しているチームはあるだろう。その場合、ここで紹介した手法が適用できないか少し考えてほしい。適用が難しいかもしれない事情には興味があるので、ぜひ共有してほしい。

この話はもしかして、アラートの所有者は誰なのかという議論にもなるかもしれない。

New Relic LogsでCustom Attributeを追加する

こんにちは。 New Relic Advent Calendar 2019 - Qiita, 12/10の記事を始めます。

New Relic Logsは、Logを扱うサービスです。fluetndなどのログコレクターからログを突っ込みつつ、クエリしたり、アラートを設定できたりするやつです。

f:id:katzchang:20191210124422p:plain
ogs!

突っ込んだデータはInsightsでもクエリ可能なので、つまり、色々できそう。ということで、どこまで遊べそうかちょっと試してみます。

hostname, service_name

ドキュメントのとおりにfluentdで設定すると、とりあえずログが収集されはじめます。気づくと思いますが、ちょっと空欄のところがありますよね。

f:id:katzchang:20191210124933p:plain
HOSTNAME, SERVICE_NAMEがさみしい

とりあえず fluentd filterで足してみます

<filter **>
  @type record_transformer
  <record>
    hostname ${hostname}
    service_name "オーサムログ🚀"
  </record>
</filter>

fluentdを再起動して、ログをおくってみると…

f:id:katzchang:20191210130439p:plain
🚀

送られました!左側のHostnameフィルタなんかもいい感じに動きそうです。

更に項目を追加してみる

Insightsに入るということはつまり、カスタム属性を追加できるようなきがしますよね。やってみました。

how_awesome という項目を足して…

<filter **>
  @type record_transformer
  <record>
    hostname ${hostname}
    service_name "オーサムログ🚀"
    how_awesome "⭐⭐⭐⭐⭐"
  </record>
</filter>

fluetndを再起動、ログをおくってみると…

f:id:katzchang:20191210130725p:plain
⭐5つ!(3つしか表示されないが)

ご覧のとおり、Insightsからクエリ可能な感じになりました。Logsの画面上ではカスタム属性は表示されませんが、検索条件は補完されたりします。

f:id:katzchang:20191210130928p:plain
how_...

ということで、

今回のサンプルコードは↓のリポジトリにおいてあります。

github.com

ということで、New Relic Logsを簡単に動かしてみました。APMと組み合わせてつかえるLogs in Context もパブリックベータで公開中で、こちらも近々試してみようと思ってます。気になる方はご連絡ください!

GitHub Actionsでデプロイを記録する

こんにちは、@katzchangです。これは New Relic Advent Calendar 2019 - Qiita、12/6の記事です。みなさん、今日もデプロイしていますか?

デプロイが行われるということは、何らかの意図した挙動の変化を期待してるはずです。新しい機能の追加、パフォーマンスの改善など。そしてご存知の通り、アプリケーションのデプロイにはリスクが伴います。だいたいのトラブルはアプリケーションのデプロイが原因だったりします。私はこれを、デプロイの「作者の意図」と「副作用」と呼んでたりします(まれに良い副作用もある)。

つまり、モニタリング上の挙動の変化とデプロイは、関連が深いのです。

という背景がありつつ、New Relic APMではデプロイを記録することができるようになっているので、その紹介をさせていただこうかと思っております!せっかくなので先月から正式版となったGitHub Actionsで動かしてみるところまでやってみます。

デプロイを記録する

デプロイの記録は各言語のエージェントで用意しているAPI経由でもできますが、ここは単純にPOSTリクエストを送る方法をとってみましょう。ドキュメントを開くと、 curl コマンドの例が見えます。なるほど、できそう。

f:id:katzchang:20191205204449p:plain
おなじみのコマンド

これをMakefileに書き下すと例えばこんな感じになります。ほぼそのままです。

deploy-create:
    curl -X POST 'https://api.newrelic.com/v2/applications/$(application_id)/deployments.json' \
         -H 'X-Api-Key:$(NEW_RELIC_REST_API_KEY)' -i \
         -H 'Content-Type: application/json' \
         -d '{"deployment":{"revision":"$(revision)","changelog":"$(changelog)","description":"$(description)","user": "$(user)"}}'

これでもう、終わったようなものですね。

REST API Keyを取ってくる

上のドキュメントからたどると、REST API Keyを取ってくるためのドキュメントにたどり着きます。なるほど、アカウント管理からたどればいいのか。

f:id:katzchang:20191205204416p:plain
中途半端に下の方にある

生成したAPIキーは、環境変数に設定するのがとりあえずよいと思います。zshを使っていれば、 ~/.zshenv に書いていきます

export NEW_RELIC_REST_API_KEY=NRRA-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

シェルを起動しなおしたりすると、環境変数が設定された状態になるはずです。

application_idを取ってくる

APMのapplication idは、URLを見るのが一番はやいでしょう。

f:id:katzchang:20191205204335p:plain
APMのURL

applications の次の数字(ここでは 475666074 )がapplication idです。

リクエストを組み立てよう

あとのパラメータはとりあえず適当にやってみます。まずは動かしてみることが大事です。

revision:=$(shell git rev-parse HEAD)
description:=$(shell git log -1 --oneline)
application_id:=475666074
user=$(shell git log -1 --pretty=format:'%an')
deploy-create:
    curl -X POST 'https://api.newrelic.com/v2/applications/$(application_id)/deployments.json' \
         -H 'X-Api-Key:$(NEW_RELIC_REST_API_KEY)' -i \
         -H 'Content-Type: application/json' \
         -d '{"deployment":{"revision":"$(revision)","changelog":"$(changelog)","description":"$(description)","user": "$(user)"}}'

動かしてみよう

叩いてみます。

make deploy-create
curl -X POST 'https://api.newrelic.com/v2/applications/475666074/deployments.json' \
         -H 'X-Api-Key:NRRA-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -i \
         -H 'Content-Type: application/json' \
         -d '{"deployment":{"revision":"25ccfa8ad1427caa9c4895ed4c6a72aad6f27c90","changelog":"","description":"25ccfa8 fix...","user": "Kazunori Otani"}}'
HTTP/1.1 201 Created
Proxied-By: Service Gateway
Content-Security-Policy: frame-ancestors *.newrelic.com
Cache-Control: max-age=0, private, must-revalidate
Content-Length: 293
Content-Type: application/json
Date: Thu, 05 Dec 2019 11:27:15 GMT
Etag: "1cbcc8f7b8f9124ba6fb97d66e67c1e6"
Server: nginx
Status: 201 Created
X-Rack-Cache: invalidate, pass
X-Request-Id: 62377002304bcbcbd1f584335e347804
X-Runtime: 0.294061
X-Ua-Compatible: IE=Edge,chrome=1

{"deployment":{"id":47717396,"revision":"25ccfa8ad1427caa9c4895ed4c6a72aad6f27c90","changelog":"","description":"25ccfa8 fix...","user":"Kazunori Otani","timestamp":"2019-12-05T03:27:15-08:00","links":{"application":475666074}},"links":{"deployment.agent":"/v2/applications/{application_id}"}}% 

HTTP/1.1 201 Created とあるので、成功したっぽいです。APMのOverviewを開いて、デプロイが記録された様子を見てみましょう。

f:id:katzchang:20191205204240p:plain
オーサムなデプロイ

完璧です。

GitHub Actionsを使ってみる

GitHub Actionsは先月から正式版になった、GitHub謹製のサービスです。Gitの動作にフックして、いろんな挙動をもたせることができます。

ここではとりあえず、masterへのpushを以てデプロイを記録することにしましょう。

name: New Relic 

on:
  push:
    branches:
    - master

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: test
      run: make test
    - name: deploy create
      env:
        NEW_RELIC_REST_API_KEY: ${{ secrets.NEW_RELIC_REST_API_KEY }}
      run: make deploy-create

APIキーは隠したいので、Secretsに入れることにします。リポジトリのSettingsタブから、設定項目を探してみましょう。

f:id:katzchang:20191205205201p:plain
秘密の情報

これで、 push master したり merge master すると、デプロイマーカーが記録されることになります。リポジトリのActionsタブを開くと、アクションの結果を見ることができます。

f:id:katzchang:20191205205510p:plain
苦悩の歴史が垣間見れます

GitHub Actionsに直接curlコマンドを書くこともできなくない。が、Makefileを用意することで、他のCIサービスで動かしたり、サーバ内のスクリプトで動かしたり、もしくは自分のMacBookから動かしたりしても、一貫したメッセージが記録されます。つまり、可搬性がよい。

いつ記録するか?それが問題だ

今回はmasterリポジトリへのpushで、デプロイとして記録することにしました。デプロイブランチを運用しているならそのブランチの変更を検知してもいいし、タグをつけてるならそれでもいいかもしれない。EC2などのVMやコンテナが複数ある場合が多い昨今なので、いつの時点が本当のデプロイと呼べるのかよくわからないときありますよね。まあでもいいんです、そんなことは。とりあえず便利な情報が出るようにしましょう。

はい、Deploymentタブから、デプロイの記録がみれるようになります。

f:id:katzchang:20191205205854p:plain
輝かしい歴史の一旦

これで、メトリックの変化、エラーの変化とデプロイがひと目でわかるようになりました。便利!

github.com

今回の内容は上のリポジトリに全部つっこんでいます。参考になれば幸いでございます。