ごった煮

色々な事を書いてます

Webフロントエンドを Application Insights で監視する

Application Insightsは、アプリケーション解析に便利なログ収集、解析ツールです。

.NET などは、SDK を入れるだけで簡単にフロント、バックエンド問わずアプリケーション解析の為のログを収集できます。

また単純なフロントエンドだけ(JavaScript)のアプリケーションでも簡単にログを収集することが出来るのが非常に魅力的です。

試してみる

いくつかセットアップ方法がありますが、今回は、一番簡単なスニペットを貼り付けるだけのセットアップ方法を紹介します。 以下のスニペットを記述するだけで AI のセットアップは、完了です。

   <script type="text/javascript">
      var sdkInstance = "appInsightsSDK"; window[sdkInstance] = "appInsights"; var aiName = window[sdkInstance], aisdk = window[aiName] || function (e) { function n(e) { t[e] = function () { var n = arguments; t.queue.push(function () { t[e].apply(t, n) }) } } var t = { config: e }; t.initialize = !0; var i = document, a = window; setTimeout(function () { var n = i.createElement("script"); n.src = e.url || "https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js", i.getElementsByTagName("script")[0].parentNode.appendChild(n) }); try { t.cookie = i.cookie } catch (e) { } t.queue = [], t.version = 2; for (var r = ["Event", "PageView", "Exception", "Trace", "DependencyData", "Metric", "PageViewPerformance"]; r.length;)n("track" + r.pop()); n("startTrackPage"), n("stopTrackPage"); var s = "Track" + r[0]; if (n("start" + s), n("stop" + s), n("addTelemetryInitializer"), n("setAuthenticatedUserContext"), n("clearAuthenticatedUserContext"), n("flush"), t.SeverityLevel = { Verbose: 0, Information: 1, Warning: 2, Error: 3, Critical: 4 }, !(!0 === e.disableExceptionTracking || e.extensionConfig && e.extensionConfig.ApplicationInsightsAnalytics && !0 === e.extensionConfig.ApplicationInsightsAnalytics.disableExceptionTracking)) { n("_" + (r = "onerror")); var o = a[r]; a[r] = function (e, n, i, a, s) { var c = o && o(e, n, i, a, s); return !0 !== c && t["_" + r]({ message: e, url: n, lineNumber: i, columnNumber: a, error: s }), c }, e.autoExceptionInstrumented = !0 } return t }(
         {
            instrumentationKey: "Your own instrumentation key"
         }
      ); window[aiName] = aisdk, aisdk.queue && 0 === aisdk.queue.length && aisdk.trackPageView({});
   </script>

instrumentationKey の部分にポータルから取得した AI のキーを挿入します。

アプリケーション全体を監視するためにも、Head タグの一番上に記述することが推奨されています。

これだけで、ページ内のエラーが AI に送られるようになります。

以下のコードを試してみます。 jQuery を読み込んでいないのに $() を使おうとしているので、エラーになります。

<!DOCTYPE html>
<html lang="en">

<head>
   <script type="text/javascript">
      var sdkInstance = "appInsightsSDK"; window[sdkInstance] = "appInsights"; var aiName = window[sdkInstance], aisdk = window[aiName] || function (e) { function n(e) { t[e] = function () { var n = arguments; t.queue.push(function () { t[e].apply(t, n) }) } } var t = { config: e }; t.initialize = !0; var i = document, a = window; setTimeout(function () { var n = i.createElement("script"); n.src = e.url || "https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js", i.getElementsByTagName("script")[0].parentNode.appendChild(n) }); try { t.cookie = i.cookie } catch (e) { } t.queue = [], t.version = 2; for (var r = ["Event", "PageView", "Exception", "Trace", "DependencyData", "Metric", "PageViewPerformance"]; r.length;)n("track" + r.pop()); n("startTrackPage"), n("stopTrackPage"); var s = "Track" + r[0]; if (n("start" + s), n("stop" + s), n("addTelemetryInitializer"), n("setAuthenticatedUserContext"), n("clearAuthenticatedUserContext"), n("flush"), t.SeverityLevel = { Verbose: 0, Information: 1, Warning: 2, Error: 3, Critical: 4 }, !(!0 === e.disableExceptionTracking || e.extensionConfig && e.extensionConfig.ApplicationInsightsAnalytics && !0 === e.extensionConfig.ApplicationInsightsAnalytics.disableExceptionTracking)) { n("_" + (r = "onerror")); var o = a[r]; a[r] = function (e, n, i, a, s) { var c = o && o(e, n, i, a, s); return !0 !== c && t["_" + r]({ message: e, url: n, lineNumber: i, columnNumber: a, error: s }), c }, e.autoExceptionInstrumented = !0 } return t }(
         {
            instrumentationKey: "My own instrumentation key"
         }
      ); window[aiName] = aisdk, aisdk.queue && 0 === aisdk.queue.length && aisdk.trackPageView({});
   </script>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
</head>

<body>
   <h1>Hello World !</h1>
</body>

<script type="text/javascript">
   window.onload = function () {
      $("selector").on("click", function() {
         console.log("error");
      });
   }
</script>

</html>

エラーが発生するとログとして送信されるので、以下のようにクエリエディタで確認ができます。

f:id:papemk2:20191207160801p:plain

まとめ

これでフロントエンドの監視も見落とさないようになれるといいなあ。。。

ASP.NET (.NET Framework) のプロジェクトを Azure DevOps でビルドする

Azure DevOps 便利ですよね ASP.NET Core ならテンプレートも充実してるしすぐにCICD を組むことが出来ます。 ですが意外と .NET Framework のプロジェクトをビルドするのはややこしいと思ったので備忘録にします。

実際にやってみる

結局 MSBuild を頑張る形になります。 普段は、Visual Studio が頑張ってくれるので MSBuild の使い方を意識することは、あまりなくそれがハードルの高さに感じます。

因みに今回は、クラシックエディタを想定しています。(OtherGit を使う想定です)

パイプライン作成時のテンプレートで以下のものを選択します。 f:id:papemk2:20191126184536p:plain

テンプレートが出来ると以下のような感じになります。 f:id:papemk2:20191126184842p:plain

ここで大事なのは、Build Solution の Job です。 1 ソリューション、1プロジェクトみたいな形ならこのままでOKですが、複数プロジェクトが入っていたりすると MSBuild Arguments を書く必要が出ます。 f:id:papemk2:20191126185033p:plain

デフォルトだと、特定のプロジェクトだけデプロイしたい場合に対応できないのでここを頑張ります。

MSBuild arguments

デフォルトでは、以下の記述があります。

/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\\"

これだとプロジェクトが指定されていないので、全てのプロジェクトがビルドされます。 なので特定のプロジェクトだけビルドしたい場合は、以下のようにします。

/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\\" /t:"ターゲットプロジェクト:Clean;Build"

/t ターゲットプロジェクト の後ろのClean;Build は、クリーンしてからビルドするコマンドになります。 これを入れておくのが無難です。

ターゲットプロジェクトは、ソリューション内でフォルダが切られてその下にいる場合は、フォルダ名\プロジェクト名とします。 プロジェクト名に . が含まれる場合は、. を入れられない仕様なので _ に置き換えます。 例えば Target.Project.csproj の場合は、Target_Project にします。

これでビルドを回せば、デプロイ用のパッケージがいい感じに作られます。

MSBuild が入っている環境ならコマンドを試せるので、手元の環境で試して問題が無かったら DevOps に反映みたいな形がいいかと思います。 その場合は、

msbuild ソリューション名.sln 上記のコマンド

とすると実行できます。

まとめ

MSBuild は、Visual Studio があるとうまく隠蔽されていて触る機会が少なくハードルが高いですが、一度覚えると便利なので試してみるといいかもしれません。

ARM Template を YAML で書きたい

インフラを構成管理するという意味で、ARM Template は、とても便利ですが、如何せん Json なので何かと不便な面もあります。 個人的には、コメントが書ける Yaml の方が構成ファイル用のフォーマットとしては、優秀だと感じています。

そこでARM Template を Yaml で記述する方法を紹介します。

どうやるのか

最終的に YamlJson に変換することが出来れば OK です。 ということで Yaml に変換するツールを持ってきます。

ツールの紹介

今回は、Yarm というツールを使用します。

github.com

このツール群は、Arm Template 風に書かれた Yaml を実際の Arm Template に変換してくれるツールです。 このツールは、現役のMS社員の方がメインになって開発をしているツールのようです。

ソースコードをビルドして使用する他にバイナリが配布されているのでそれを使用することも可能です。 とりあえずバイナリをダウンロードしましょう。

github.com

使い方

落としてきたファイルを解凍すると、その中に yarm.cmd というファイルがあるのでこちらを実行します。

コマンドのオプションは、以下の通り

  • -i, --input 入力ファイルのパスを指定します。ローカルのファイルパスに加え、Web上のファイルも指定できます。Yaml or Json ファイルは、自動判別されます。(必須)
  • -o, --output 出力ファイルのパスを指定します。指定しない場合は、入力ファイルと同一の場所に返還後のファイルが出力されます。
  • --help ヘルプ
  • --version バージョン表示
Yaml to Json
yarm -i [Yamlファイル]

例えば

yarm -i deploy-function.yaml

とすると、deploy-function.yaml と同じ階層に deploy-function.json が出力されます。

yarm -i deploy-function.yaml -o function-template.json

とすると、function-template.json の名前で変換結果が出力されます。

Json to Yaml

そもそも Yaml のテンプレート自体非公式なものでドキュメントが存在しないので、最初のテンプレート起こしの意味合いなどでも JsonYaml に変換したい場面があるかと思います。 その場合でも簡単に動かせます。

yarm -i deploy-function.json

のようにすると、deploy-function.yaml として出力されます。

yarm -i deploy-function.json -o function-template.yaml

とすると、function-template.yaml として出力されます。 JsonYaml を気にせず使えるのは、とてもありがたいですね。

またコマンド紹介の部分でも書きましたが以下のようにしても動きます。

yarm -i https://github.com/Azure/azure-quickstart-templates/blob/master/101-app-service-certificate-standard/azuredeploy.json

わざわざローカルに落としてこなくても 変換できるので色々な場面で使えそうです。

まとめ

Yaml は、完璧なフォーマットでないので、劇的に ARM Template を扱うのが楽になるかといわれると微妙ですが、Json と比べて 記述量が少なくなったり、コメントを書いてわかりやすくしたりといったことが出来る分扱いやすくなるかなと思います、

興味のある方は、ぜひ使ってみてください。

Xbox ワイヤレスエリートコントローラを修理した話

我が家には、Xboxのエリートコントローラが2台あるのですが、ここ最近2台とも調子が悪い状態でした。 買ってから数年経つものと日本国外で購入したものということで、サポートに修理に出すのもあれだったので自分で修理してみました。

次回の為にその時のメモを残します。

症状

エリートコントローラは、よくLB、RBのモジュールが壊れるらしいです。 自分のものは、片方が LB の破損、もう片方が ABXY ボタンがかなりの頻度で押した後の戻りが遅いという症状でした。

とりあえずこの記事では、ABXY の修理についてまとめます。 LB ボタンの交換については、別記事で

修理対象

今回の修理対象は、写真の黒いベーシックなヤツです。 f:id:papemk2:20191102195823p:plain

2016年発売なので3年と少し使った感じですが、メインは、赤いほうを使っていたので実際あまり使用していません。

分解に必要なもの

  • T8のドライバー(このコントローラのネジは、全て T8 の形状でした。)
  • マイナスドライバー(分解するときにあると便利)

分解する

最初のネジを外す

一番最初のネジは、電池入れにあります。 封印シールを剥がすとネジが出てきますが。 これを剥がすと完全に公式のサポート対象外になるので、気を付けましょう。 f:id:papemk2:20191102200424p:plain

外すと一つネジが出てきます。 f:id:papemk2:20191102200503p:plain

これが外れたら次は、グリップ部分についているカバーを外します。

グリップカバーを外す

グリップカバーは、内部で6つの爪と粘着テープで固定してあるので、カバーとボディの隙間にマイナスドライバー等を入れて外していきます。 外すと写真のようになります。

粘着テープが剥がれている間隔がしたらもう少しです。 強引にやると爪が折れるかもしれないので慎重にやりましょう。 f:id:papemk2:20191102200745p:plain

グリップ内のネジを外す

グリップカバーを外すと、左右にそれぞれ2本のネジがあるので、これを外します。 このネジも T8 の形です。

これが外れると表のカバーが外せるようになります。 外すと写真のような感じになります。 f:id:papemk2:20191102201030p:plain

直す

ボタンが戻らない症状なので、ボタンがダメになっているのかを確認するためにカバーを外してボタンを押してみても同じ症状が再現しませんでした。 そこで表のカバーだけ戻してボタンを押したところ症状が再現しました。 恐らく何かしらの原因でカバーとボタンが干渉している可能性があったので、ボタンを出す穴の部分を数ミリだけヤスリで削ることにしました。

削り終えたら元に戻します。 先ほどと逆の手順で戻しましょう。

まとめ

とりあえずこれで修理完了です。 似たような症状の方は、自己責任で試してみましょう。

Chromium Edge のプレビュー機能を使う方法について

Chromium Edge の完成度が大分上がってきましたが、まだデフォルトでオンになっていない便利機能が結構あります。

自分のメモ代わりにそれの有効化についてまとめます。

今回の環境

今回は、以下の環境での話になります。 f:id:papemk2:20191031183213p:plain

プレビュー機能を有効化する

以下をアドレスバーに打ち込みます。

edge://flags/

これによってプレビュー機能の管理画面にジャンプします。

f:id:papemk2:20191031183255p:plain

検索窓に適当に何か入れてみると色々出てきます。 例えば通知周りだと以下のような感じ

f:id:papemk2:20191031183743p:plain

他にも、Microsoft Edge blog で紹介された Collections なども f:id:papemk2:20191031183904p:plain

Enable にして再起動すると使えるようになります。

まとめ

いち早く試してみたい人は、使ってみましょう。(自己責任で)

Office 365 の MFA を有効にする

Admin Center にアクセスできない権限で、Office 365 に MFA を有効化しようとすると、画面のリンクを辿ってもどこにもリンクが見当たらない等いろいろあれなのでメモとして残します。

やり方

とりあえず Google に聞いてみます。

office365 mfa setup link

これで検索します。 リンクが見つかります。

f:id:papemk2:20191015181143p:plain

account.activedirectory.windowsazure.com

このページで画面の手順に従うと MFA が有効化できます。

まとめ

MFA は、セキュリティを向上させるうえでかなり重要なので出来るだけ有効化しておきましょう。

それにしてもこれはひどい

AAD のゲストユーザでも SQL Database の AAD 認証を使う話

SQL Database は、 AAD ユーザを使ったログインが出来ますが、外部の AAD からのゲストユーザの場合、直接権限付与が出来ないので、外部ユーザでもログイン出来るようにする方法をまとめます。

仕組み

これを実現するための仕組みは、以下のような形です。

  1. AAD にグループを作成する
  2. 作成したグループにゲストユーザを追加する
  3. グループを DB ユーザとして登録する

この流れで実現が可能です。

グループを作成して、ゲストユーザを追加までは、今回の本質ではないので省略です。

権限付与は、以下の SQL を流すだけで OK です。

GO

CREATE USER [グループ名] FROM EXTERNAL PROVIDER;

ALTER ROLE db_owner ADD MEMBER [グループ名];

GO

これを実行するとユーザ作成完了です。

CREATE USER [グループ名] に FROM EXTERNAL PROVIDER を付けると、AAD のユーザを DB のユーザとして追加するという構文になります。

グループ名に、作成したグループの名前を入れて実行すると、そのグループを DB のユーザとして登録できます。

ゲストユーザ以外なら、ユーザ名にメールアドレスを入れてやると AAD のユーザを DB ユーザに追加できます。

ログインする際、master 以外の DB にユーザを作成した場合は、SSMS などで接続する際に DB 名を指定してやる必要があるので気を付けましょう。

まとめ

SQL Database に繋ぎに行く場合、AAD を使ってセキュアに繋ぐことが自分たちのデータを保護する上でとても重要です。

ゲストユーザ以外を追加する場合でも、グループ単位でまとめてユーザ作成をしておけば、権限の付与やはく奪という作業の手間を省くことが出来るので、ぜひ使ってみてください。