connect-go with opentelemetry
お久しぶりです。計装してますか?
突然connect-goで計装したくなったので実装調べたんですがまったくまともなリファレンスがひっかからなかったのでなんとか実装しました。
下記はこのリポジトリの解説記事となります
opentelemetryインフラの準備
コレクターとかエクスポーターとかめっちゃめんどい事前準備が必要だなーめんどくさいなーとか思っていたんですが、HyperDXさんからall-in-oneパッケージが提供されているのでこれに甘えることとします。
https://hub.docker.com/r/hyperdx/hyperdx-all-in-one
ドキュメントにhyperdxのパッケージを使う例が多いですが、こちらとしてはhyperdxをローカルで使うと決めたものの最後まで使うかは決めていないので、なるべくopentelemetryの標準パッケージを使うという前提で進めています
初期化
import (
"context"
"log"
"log/slog"
"os"
"connectrpc.com/connect"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
)
var tracer = otel.Tracer("your-tracer-name")
var grpcHost = "hyperdx:4317
func InitOTLP() (*trace.TracerProvider, error) {
ctx := context.Background()
authorizationKey := os.Getenv("OTEL_EXPORTER_AUTHORIZATION_KEY")
exporter, err := otlptracegrpc.New(
ctx,
otlptracegrpc.WithInsecure(), // Use WithTLSCredentials for secure connections
otlptracegrpc.WithEndpoint(grpcHost),
otlptracegrpc.WithHeaders(map[string]string{"authorization": authorizationKey}),
)
resources, err := resource.New(
ctx,
resource.WithProcessPID(),
resource.WithHost(),
resource.WithAttributes(
semconv.ServiceName("acme_service"),
semconv.ServiceVersion("vX.Y.Z"),
semconv.DeploymentEnvironment("dev"),
),
)
tp := trace.NewTracerProvider(
trace.WithBatcher(exporter),
trace.WithResource(resources),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
return tp, nil
}
こんな感じのコードになります。exporterはgrpcのものをメインにしていますがここをほかのプロトコルに変えることもできるのでドキュメントを参照ください
OTEL_EXPORTER_AUTHORIZATION_KEYですが、hyperdxを立ち上げると簡易的なチュートリアルが表示されており、その中でAPI tokenが発行されています。それをdocker composeで指定したり env ファイルを作って入れ込むなどをしてください
interceptor
connect-goではリクエストをフックする関数としてinterceptorに登録することで自動的に呼び出すことができるようなので、こんなかんじのコードを初期化後に実行することで対応できます
import (
"connectrpc.com/otelconnect"
"connectrpc.com/validate"
"connectrpc.com/connect"
)
func NewAPMTraceInterceptor(logger *slog.Logger) connect.UnaryInterceptorFunc {
return func(next connect.UnaryFunc) connect.UnaryFunc {
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
ctx, span := tracer.Start(ctx, "request:"+(req.Spec().Procedure))
res, err := next(ctx, req)
if span != nil {
defer span.End()
}
return res, err
}
}
}
//register interceptors
otelInterceptor, err := otelconnect.NewInterceptor()
otelAPMInterceptor := NewAPMTraceInterceptor(logger)
interceptors := connect.WithInterceptors(
otelInterceptor,
otelAPMInterceptor,
validate.NewInterceptor(),
)
docker composeでhyperdxの画面を開くとデータが流れているのが確認できるでしょう
それではよい計装ライフを
ChatGPTに関心した話
お久しぶりです。
猫も杓子もGPTですね。
自分も例に漏れず使っているわけですが関心したことがあったのでまとめてみようかなと思いました
動機
pythonを最近よく書くのである程度詳しい認識はあるのですが、
dictを加算しつつ結合するようなメソッドが欲しいと思いました。
dictを結合する場合 | 演算子や update() メソッドを用いることがよく知られていますが、それらはこのように動作します
In [2]: _d1 = {1:2, 2:3} In [3]: _d1.update({3:4}) In [4]: _d1 Out[4]: {1: 2, 2: 3, 3: 4} In [5]: {1:2, 2:3} | {3:4} Out[5]: {1: 2, 2: 3, 3: 4}
これらはキーが重複していない状態では想定通りの挙動をしますが、キーがかぶっているときには安全側に倒すような挙動となります(エラーなどでずに後ろの値で上書き)
キーが重複していたときに加算してほしいなあと思ったのですがそういった実装はないのでChatGPTに聞いてみることにしました
聞いてみた

解説
だいたいコメントを読んでもらうと想定内のことが書いてありますね
なんで copy() が入っているのかというと、primitive typeを除いてpythonでは引数に参照渡しでくるのでそのまま copy() せずに代入すると引数で渡したp1の値が関数の外で想定外の値になってしまうからです
だいたいのケースでcopyせずに問題なく動くと思いますがあるとなしでは安全さが違う
これらを受けてこういうコードになった
T = TypeVar("T") def merge_dict(src: dict[T, int], *args: Any) -> dict[T, int]: dest = src.copy() for arg in args: for k, v in arg.items(): if k in dest: dest[k] += v else: dest[k] = v return dest
こういう感じにすることで
merge_dict({1: 2, 3:4}, {3:5}, {1: 8})
みたいな書き方でもちゃんと結合させることが可能
感想
multi memcached in upstart
やりたいこと
check
$ ps -ax | grep memcached 8501 ? Ssl 0:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1
これを21211でも起動したい
やり方をぐるる
/etc/init.d/memcachedにヒントがあるとのこと
# Usage: # cp /etc/memcached.conf /etc/memcached_server1.conf # cp /etc/memcached.conf /etc/memcached_server2.conf # start all instances: # /etc/init.d/memcached start # start one instance: # /etc/init.d/memcached start server1 # stop all instances: # /etc/init.d/memcached stop # stop one instance: # /etc/init.d/memcached stop server1 # There is no "status" command.
設定をコピー
$ sudo cp /etc/memcached.conf /etc/memcached_server1.conf
コピーしたほうのconfを編集してポートを21211に変更
で、起動しなかった
ぐぐったらupstartだしね無理だよねという話に遭遇。
なのでsystemctlでそれっぽく動きそうなリファレンスを捜索
これがヒット
これベースでやるとよさそう
service をコピー
$ cd /lib/systemd/system $ sudo cp memcached.service memcached.21211.service
コピーした方を新しい設定ファイルを読みに行くように修正する
起動
$ sudo systemctl start memcached.21211 $ ps -ax | grep memcached 8501 ? Ssl 0:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1 10125 ? Ssl 0:00 /usr/bin/memcached -m 64 -p 21211 -u memcache -l 127.0.0.1
めでたしめでたし
x in alpine linux
TL, DR;
- 成功しませんでした
やりたいこと
- alpine linux(3.3)にXFCEを入れる
- 対象はvirtualbox VM(5.0.18)
ref
ここの通りに入れると結構すんなり進む。そらマニュアルなんだからそうだという話はさておき、
$ Xorg -configure
がこけるはずだ Xorg.0.logを読むとなんかわかるんじゃないかなという話なのでエラーっぽい単語でぐぐる
Yes, Xorg -configure will disable the /etc/X11/xorg.conf.d/ which has the config for manually loading the modules in proper order.
The problem is that musl libc does not support lazy loading. I don't have any good ideas how to properly solve this.
Does it work if you skip the Xorg -configure step and just do startxfce4?
えっ叩いちゃだめなのこれ!!!? ということでstartxfce4を直接たたく
うーん真っ黒画面だ
再度Xorg.0.logを見るとvboxなんちゃらというのが出るのでvirtualbox用アドオンを入れようとする
# apk add virtualbox-additions-grsec # apk add virtualbox-guest-modules-grsec
うん?両方こけるぞ?と思ってパッケージ検索を実行
Branchがedgeになっているので読めるようにしておきます。 /etc/apk/repositoriesをsudo vim
grsecまわりが必要そうなのでlinux-grsecもadd
$ cat /etc/apk/repositories #/media/cdrom/apks http://dl-3.alpinelinux.org/alpine/v3.3/main http://dl-3.alpinelinux.org/alpine/v3.3/community http://dl-3.alpinelinux.org/alpine/edge/main http://dl-3.alpinelinux.org/alpine/edge/community http://dl-3.alpinelinux.org/alpine/edge/testing
で、
# apk del virtualbox-additions-grsec # apk del virtualbox-guest-modules-grsec # apk add linux-grsec # apk add virtualbox-additions-grsec # apk add virtualbox-guest-modules-grsec
からの再起動して、startxfce4
。。。。同じ画面じゃないか
続く(かも)
マウスカーソルが出てる時点でおそらく半分くらい目的は達成されているはずなので、なぜxfceの画面が立ち上がらないかを調べたほうがよさそうだ
メモ書き
やりたいこと
- 庭用ランプを買いたい
— rane (@rane_hs) April 18, 2016
- 個別ソーラーみたいなやつは日照イマイチなところには置けない
⇒ 日照高いところで集光して18-24だけ給電するようなやつ(IoTデバイス?)を作る必要性
tools
電灯
- とくに理由はないけどUSBだと結線がイメージしやすそうという理由によりチョイス
- (外で置くには何かしらのガワが必要になるのでそれはおいおい)
被覆材
- このへんから適当に
コントローラ
- Cではない(これはC++。Lazurite ってのがあってこれも省電力を売りにしてたんだけどCしか使えなさそうなのでやめました)
- 省電力
- 安い
という点からチョイス
給電
- どうやって使おうかというイメージがまだできてない
docker & alpine
いまdocker熱いですね。
どうもそれとセットでalpine linuxってのが熱いらしいです
何がいいのそれっていうと、コンテナサイズが劇的に軽くなるということのようです
くわしくはこのあたりに:
Docker、オフィシャルイメージのOSをAlpine Linuxへ切り替える計画が明らかに。OSの軽量化に傾倒するDocker - Publickey
で、alpineベースでmemcachedとredisのコンテナがあるんですけど両方くっついたコンテナの方がほしくなったので、dockerの勉強がてら作ってみました
使い方は
$ git clone git@github.com:rane-hs/memcached-and-redis.docker.git $ cd memcached-and-redis.docker $ docker build -t memcached-redis-alpine . $ docker run --restart always --name mcdocker -i -t -d memcached-redis-alpine $ docker inspect mcdocker | grep IPAddr # コンテナのIPを入手
で、↑で入手したアドレスにログインします
$ telnet 123.45.67.89 11211 # telnet $ redis-cli 123.45.67.89 # redis
docker commands
使ったコマンドたち。
以下は↑のリンクをgit cloneしてきて1個中に入った状態で叩かれていることを想定しています
build container
docker build -t memcached-redis-alpine .
memcached-redis-alpineという名前でコンテナイメージを作ります
run container
docker run --restart always --name mcdocker -i -t -d memcached-redis-alpine
mcdockerという名前でコンテナを走らせます。イメージは↑で作った名前です
check running container
docker ps
- いまローカルにあるイメージの一覧は
docker imagesで - 両方
-aがoptionalで使えます
remove container (-f : force)
docker rm -f mcdocker
- イメージ削除は
rmi
remove unused container image (1liner)
docker rmi -f $(sudo docker images -a | awk '/^<none>/ { print $3 }')
- 全部きえるわけではないです
check container setting
docker inspect mcdocker
IPAddressでコンテナのIPアドレスがわかります
run container shell
docker exec -it mcdocker /bin/ash
attachはdocker runしたスクリプトにアタッチしちゃうので、Ctrl-Cとかexitしちゃうとコンテナごと閉じます。- ここでは
execを使ってシェルを立ち上げています。alpine linuxではbashがないのでashとしましたがubuntuではbashでよさそう
お役立ちリンク
- docker チートシート
- alpine linuxで
docker pull mysqlできないのは上記を見て対応してください
- dockerオススメTIPS15選。
- sudo dockerプレフィックスをdockerにする方法もあります