◆結論

◆和訳

DelegatingHandler 継承したアレを AddHttpClient してるとこで AddHttpMessageHandler しろや。※解説は後述。

◆経緯

ASP.NET Core 2.2で、HttpClient を使っている。つまり、 Startup からなんやかんや経て IServiceCollection に AddHttpClient している。

わからねぇならまずググれ。

んで HttpClient 使ってるところで、リクエストとレスポンスをログに吐き出したい気持ちになった。

白目向きながら、投げる前と投げた後で LogInformation を書いたんだけど、「いや違くね?」と思った。つまり Intercept したいわけだから Interceptor を噛ませればいいんじゃないかと。んでググったら結論のページに行き着いた。

◆解説

ちゃんとSteve先生の言う事聞いてお薬ちゃんと飲めば実装できるんだけど、 english が very poor な fuck’n jap ども(俺)に向けて、以下、解説をさせて頂く。

▼Interceptor

割り込むもの。DelegatingHandler なる仕組みで提供されている。DelegatingHandler は HttpMessageHandler を継承していて(略

とにかく DelegatingHandler を噛ますと処理に割り込むことが出来る。

▼DelegatingHanderつくる

ほれ(ボロン

出力されるのは糞ログといって差し支えない感じに仕上がってるから、適宜内容を変えろ。

あと名前空間直せ。

・想定

それらもろもろを解決するのがReadContentAsUtf8StringAsyncでござる。用途によっていいようにしろ。

▼DelegatingHanderを登録

ほれ

※「// ↓こっから」から「// ↑ここまで」までが手を加えた部分。

AddTransient は、「呼ばれるたびサービスつくるよ!」ってやつ。

AddHttpClient については改めて説明しないが、appsettings.json から持ってきたドメインとかルートパスを BaseAddress に設定しておいたりデフォルトヘッダー登録したりできるぜ。

Make HTTP requests using IHttpClientFactory in ASP.NET Core

appsettings.json からの読み出しは IConfiguration.GetSection した結果を Get<T> しろ。appsettings.json に書いたオブジェクトを任意のクラスに落とし込むことが出来る。

この説明で伝わるとは思えんが。

◆使い方

普通に使え。いつも通り使え。

これ

「.CreateClient(“うんち!”)」でロギングが組み込まれた HttpClient が手に入るだろうさ。

ローカルデバッグでログが吐かれる様子を確認したいんならCtrl + Shift + Uで出力を開きたまへ。

◆ログレベル

appsettings.json の中身が、以下の感じになってんじゃん?

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

さっきの DelegatingHandler で「logger.LogInformation」ってメソッド呼んでたんだけど、この「Information」同士は対応している。

だから、たとえば Azureとかいうおちゃめクラウドにアプリを載せて Application Insights でログを眺めたい時は

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "ApplicationInsights": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  },
  "AllowedHosts": "*"
}

だったり

 services.AddApplicationInsightsTelemetry(); 

だったりが必要になるだろうよ。

このへんこのへん

Application Insights のデフォルトのログレベルはWarningだらしい。Informationだと結構多く出てきちゃうし、あんまやりすぎると課金されるから適宜良い感じにしろ。あとSearchブレードを良い感じに使え

ログレベル

ログストリームで確認したい時はここでどうにかしろ。

◆コンパイラ(構文解析機)のバグか

リテラルの中でawaitしたときの挙動

var t = (request.Content?.ReadAsStringAsync() ?? Task.FromResult(string.Empty));
var r = $"{await (t)}";

awaitが怒られる。パーレンが無かったら怒られない。

当然これも怒られる。

var r = $"{await (Task.FromResult(string.Empty))}"

awaitパーレンが許されないわけではなくて、tに代入するところでawaitしてもそれはセーフ。リテラル内でのawaitもOK。良く分からん。バグっぽいな。

▼追記:2019/10/10

挙げてみたらバグだった。やっぱりな♂

https://github.com/dotnet/roslyn/issues/39149

◆結論(2回目)

パソコンの電源は落として帰ろうぜ。スリープでもいいけど。