OmniAICreator/Qiita-1.07M huggingface dataset:
高可用性アーキテクチャの構築

参考：https://docs.microsoft.com/ja-jp/learn/modules/design-for-availability-and-recoverability-in-azure/2-high-availability
「Azure で最適なソリューションを設計する - Azure での可用性と回復性のための設計 高可用性アーキテクチャの構築 - 高可用性アーキテクチャの構築」

# アーキテクチャの高可用性の評価手順
1.ご利用のアプリケーションのサービス レベル アグリーメント（SLA）を特定する
2.アプリケーションの HA 機能を評価する
3.依存するアプリケーションの HA 機能を評価する

## 1.SLA を定義する場合の考慮事項
 - 4 つの 9 (99.99%) を実現するには、手動操作による障害からの復旧には依存できません。 アプリケーションには自己診断機能と自己復旧機能が必要です。
 - 4 つの 9 を超えると、SLA を満たすことができるほど迅速に障害を検出することは困難です。
 - SLA を測定する時間枠について考慮します。 この時間枠を短くするほど、許容度は厳格になります。 時間単位または日単位のアップタイムという観点で SLA を定義することはおそらく意味がありません。

アプリケーションの可用性を高めるためのツールおよび機能
①可用性セット
②可用性ゾーン
③負荷分散
④サービスとしてのプラットフォーム (PaaS) HA 機能

### ①可用性セット
可用性セットは、同じアプリケーション ワークロードに属する VM を分散させることでハードウェア障害および予定メンテナンスから同時に影響を受けるのを防ぐ必要があることを Azure に通知する方法です。 可用性セットは、更新ドメインと障害ドメインで構成されています。

### ②可用性ゾーン
可用性ゾーンは、独自の電源、冷却装置、およびネットワークを備えた、リージョン内にある独立した物理的なデータ センター場所です。 リソースをデプロイする際に可用性ゾーンを考慮に入れることにより、特定のリージョンでのプレゼンスを維持しながら、データ センターの停止からワークロードを保護することができます。 仮想マシンのようなサービスは、ゾーン サービスです。これらは、リージョン内の特定のゾーンにデプロイすることができます。 他のサービスはゾーン冗長サービスであり、特定の Azure リージョン内の複数の可用性ゾーンにわたってレプリケートされます。 両方の種類により、Azure リージョン内では単一障害点が発生することはありません。

### ③負荷分散
ロード バランサーでは、ネットワーク トラフィックをアプリケーション全体に分散する方法が管理されます。 ロード バランサーは、個々のコンポーネントでの障害に対するご利用のアプリケーションの回復力を維持する上で、また要求の処理でご利用のアプリケーションを確実に使用できるようにする上で不可欠です。 サービス検出が組み込まれていないアプリケーションの場合は、可用性セットと可用性ゾーンの両方に対して負荷分散が必要です。

Azure には 3 つの負荷分散テクノロジ サービスがあり、ネットワーク トラフィックをルーティングする機能で区別されます。

#### １）Azure Traffic Manager
グローバルな DNS 負荷分散機能を備えています。 Traffic Manager を使用して Azure リージョン内または Azure リージョンとの間で DNS エンドポイントの負荷分散を行うことを検討します。 Traffic Manager は、使用可能なエンドポイントに要求を分散し、エンドポイントの監視を使用して障害を起こしているエンドポイントを検出し、負荷から削除します。
#### ２）Azure Application Gateway
着信トラフィックのラウンド ロビン分散、Cookie ベースのセッション アフィニティ、URL パス ベースのルーティング、および単一のアプリケーション ゲートウェイの背後で複数の Web サイトをホストする機能など、レイヤー 7 の負荷分散機能が用意されています。 既定では、Application Gateway はバック エンド プールにあるすべてのリソースの状態を監視して、異常とみなしたリソースをプールから自動的に削除します。 Application Gateway は異常なインスタンスを継続的に監視し、このインスタンスが利用可能になり正常性プローブに応答するようになると、正常バック エンド プールに戻します。
#### ３）Azure Load Balancer
レイヤー 4 のロード バランサーです。 負荷分散されるパブリックおよび内部のエンドポイントを構成したり、TCP を使用して受信接続をバックエンド プールの送信先にマッピングする規則や、サービスの可用性を管理するための HTTP の正常性プローブ オプションを定義したりできます。

### ④PaaS HA 機能
高可用性が組み込まれた PaaS サービス。 Azure SQL Database、Azure App Service、および Azure Service Bus などのサービスには、高可用性機能が含まれています。これにより、サービスの個々のコンポーネントの障害は、アプリケーションに対して確実にシームレスになります。 PaaS サービスを使用することは、ご利用のアーキテクチャが確実に高可用性になるようにするための最善の方法の 1 つです。
バックエンドとサーバーサイドの違い 


#経緯
就職活動をしていて、内容は似ているのに募集しているエンジニアの募集の書き方に違いがあり、
細かい内容ですが気になったので、今回調べてみました。

#バックエンドとは 

>バックエンドはフロントエンド側からデータや指示を受け付け、計算や変換などの処理を行ったり、ストレージ（外部記憶装置）やデータベースなどでデータの保存や読み出しを行う。
クライアントサーバ型のシステムではサーバ側のソフトウェアを指す。Webアプリケーションでは、Webサーバや、その背後で連携して動作するアプリケーションサーバやデータベース管理システム（DBMS）などのミドルウェア、フレームワークなどが該当する。これらの上で稼働する個別に開発されたプログラムなども含まれる。この部分を開発・運用する技術者を「バックエンドエンジニア」（back-end engineer）という。

引用：http://e-words.jp/w/%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89.html

#サーバサイドとは

>サーバー側でプログラムを実行したりデータを管理したりすること。サーバーサイドでは、クライアントの環境に依存しにくく、開発や管理が容易、扱うデータをサーバー側のデータベースなどで一元管理できる、といったメリットがある。代表的なサーバーサイド技術としては、Java、PHP、ASP.NETなどがある。たとえば、PHPで記述されたWebアプリケーションは、Webサーバー側で実行され、クライアントのWebブラウザーには、HTMLとして表示される。そのため、PHPを実行するための環境を整える必要がない。これに対して、JavaアプレットやJavaスクリプトは、手元のパソコンのWebブラウザー上で実行するので、クライアントサイドのWebアプリケーションといえる。

引用：http://yougo.ascii.jp/caltar/%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89

#自分の解釈
ネット上では複数の情報があり、かなり混同して書かれている記事が多かったので、違いについて判断できませんでした。なので、元エンジニアの方で仕事紹介するプロの方にこの疑問を聞いてみました。

回答としては、企業によって呼び方が違い、内容はそこまで大差ないとのこと。
バックエンドはWEB系企業に使われることが多く、フロントエンドに対して使われている。

一方で、サーバーサイドは基幹系企業に使われることが多い印象とのこと。

ネット上では色々な意見があり、どの情報が正しいのか混同していたので、私自身はこのように解釈しま
した。

これから就職活動を始める方や疑問に思っていた人の参考記事になったら幸いです。
青森をちょっとずつ解析

pandasの練習もかねて、

このオープンデータでAomoriを解析解析する

https://www.e-stat.go.jp/stat-search/database?page=1&query=%E5%AE%B6%E8%A8%88%E8%AA%BF%E6%9F%BB%20%E5%AE%B6%E8%A8%88%E5%8F%8E%E6%94%AF%E7%B7%A8%20&sort=open_date%20desc&layout=dataset&statdisp_id=0003103522&metadata=1&data=1

----

いずれも単位は「グラム」
「二人以上いる世帯における各品の消費量」らしい。

##米の消費量「単位：グラム」

![kome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/f0dd6bbe-c4e8-ea20-7358-060f28cb4aab.png)

文字化け処理は省略。なぜか２０１８年回復してる。



##パン「単位：グラム」

![pan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/07609b18-ddc1-6a21-f486-2016020d61bd.png)

* 青：食パン
* オレンジ：他のパン

食パンは米と同じような動きをしている。　⇒　主食と同じ動き
他のパンは２０１５年からの急上昇？　⇒　イギリストーストの影響？２０１５年は日本橋高島屋で限定売り出したり、注目され始めたかもしれない年。youtubeの動画も出現してた頃。これの影響？その後ブームが落ち着いた？



# 麺類「単位：グラム」
![men.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/b0ff8450-703c-db0d-0b0b-278df45d46c8.png)

##カップ麺「単位：グラム」

![cupmen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/dc5a802b-791f-8df5-9962-c700b47a96d5.png)

２０１３年あたりに確か、青森のカップ麺消費量日本一で短命県ってニュースが一気に広がったころ。


#鮮魚「単位：グラム」

![fish.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/86e3f35b-5621-8b8a-2d6e-23332e9dff54.png)

統計にあった魚の分類は以下の通り。
170 まぐろ【1g】
172 あじ【1g】
173 いわし【1g】
174 かつお【1g】
175 かれい【1g】
176 さけ【1g】
177 さば【1g】
178 さんま【1g】
180 たい【1g】
181 ぶり【1g】
182 いか【1g】
183 たこ【1g】
185 えび【1g】
186 かに【1g】
189 他の鮮魚【1g】
187 さしみ盛合わせ【1g】

「189 他の鮮魚【1g】」が圧倒的に多い。指定された区分に入らないものがたくさんある。

例えば、「ひらめ」とか。さしみ、ムニエルがうまい。有名。
秘密の鮮魚がいるらしい。

##イカ

![ika.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/8c1adc95-0c66-109b-31aa-f0071da82da4.png)

イカ釣り人から、
「昔よりも以下のサイズが小さくて、つれなくなった」
という感想を実際に聞いていたけど、確かに急激に減ってるのは、出回りにくくなった？価格推移見ないとわかんないね。

##カニ

![kani.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163974/7114e653-d993-6e00-6893-13e8c9ef15f8.png)

2018年は昨年、おととしの反動？

次回につづく。
ローカルでpostgreSQLに接続できなくなった時(備忘録)

エラー内容
>
could not connect to server: Connection refused Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 5432?

```
$ brew uninstall postgresql
$ rm -rf /usr/local/var/postgres/
$ brew install postgresql
```

もちろん、ローカルのpostgreデータ吹っ飛ぶので注意。
rspecの導入＋カバレッジを出力する

# 概要

Ruby on Railsの開発で単体試験、カバレッジを測りたいという時のための手順
すでにRailsが起動してるよ！という状態からスタート

# 環境

Ruby on Rails自体はDockerの上で起動（Dockerじゃなくても同じように動くはず）
* Ruby : 2.6
* Rails : 5.2.3
* rspec-rails : 3.8.2
* simplecov : 0.16.1

# やったこと

## Gemfileの編集

Gemfileに``rspec-rails``と``simplecov``を追加する
`test``モードのときにのみインストールするように設定

```ruby:Gemfile
group :test do
  gem 'rspec-rails'
  gem 'simplecov'
end
```

## rspecをインストールする

gemをダウンロードする（今回はdocker-compose使ってます）

```shell
docker-compose build
```

Docker使ってないと```bundle install```かな

```shell
bundle install
```

rspecをインストール(generate）する

```shell
rails generate rspec:install
```

こんなファイル構成が生まれてばOK

```shell
.spec
spec/
spec/spec_helper.rb
spec/rails_helper.rb
```

## 設定を書き換える

Railsのモード指定をする

```ruby:spec_helper.rb
RSpec.configure do |config|
  ENV['RAILS_ENV'] = 'test'

  (略)
end
```

カバレッジレポート作成を設定する

```ruby:spec_helper.rb
require 'simplecov'

RSpec.configure do |config|
  （略）

  if ENV['CIRCLE_ARTIFACTS']
    dir = File.join(ENV['CIRCLE_ARTIFACTS'], 'coverage')
    SimpleCov.coverage_dir(dir)
  end

  SimpleCov.start
end
```

## テストクラス作成

テスト対象のクラスを作る
本来は``rails generate model item ・・・``というように``rails generate``したときにテストクラス（〜_spec.rb）が作られる
けど、すでに存在するクラスに対しては作られないので主導で作成
以下のようなファイル構成で作る（例はitemというモデルがあった場合）

```shell
spec/models/item_spec.rb
```

ファイルの中身はこんな感じ

```ruby:item_spec.rb
require 'rails_helper'

RSpec.describe Item, type: :model do
  # describeはテストの大きな枠で、クラスが持つ機能（メソッド）ごとに作るといいかも
  # 文字列のところは任意で決められ、表すものを書けばOK
  describe 'aaa test' do

    # itはテストケース単位
    # 文字列のところは任意で決められ、表すものを書けばOK
    it 'bbb test' do

      # テスト内容を記載
    end
  end
end
```

試験データを作成するときは``factory_bot_rails``を使うと良い
（今回は説明しません）

## テスト実行

テスト実行は1コマンド

```shell
rspec

# テストケースを指定する場合は引数でファイル名を渡す（対象ファイルが多いと時間がかかるため、開発中は限定したい）
rspec spec/models/item_spec.rb
```

結果がベローって出て、全部緑ならOK
最後にカバレッジが出るので、試験結果とカバレッジ結果を両方確認できる

```
Finished in 0.03117 seconds (files took 3.09 seconds to load)
1 example, 0 failures

Coverage report generated for RSpec to /sample_app/coverage. 187 / 194 LOC (96.39%) covered.
```

カバレッジ結果は``caverage/index.html``に出力されるので、通過していない箇所をブラウザで確認できる

## 注意点

specファイルが書かれていないクラスはカバレッジ計測されません
（他のテストケースを実行したときに呼ばれれば計測される）
全テスト対象クラスを最初から用意しておくことを激しくお勧めします
テスト結果が正しくないまま「カバレッジが高いぞ！」ってはしゃぐことになります

# 応用編

手動で実行すると忘れるものです
なので、リポジトリにpushしたときにテストが実行されるよう自動化をお勧めします
（github → circleCIとかgitlabのスクリプトで十分効果が発揮できる）
テスト結果をslackなどのコミュニケーションツールに投げ込むと失敗に気づけると思います
考えたら色々きりがないので、色々な環境で試してみてください。
MacOS(Mojave)でrailsをinstallしようとしてコケた

## 概要
MacにはデフォルトでRubyが入っているので早速railsを入れようと`sudo gem install rails`したらコケた。
概ね[この記事](https://qiita.com/zreactor/items/c3fd04417e0d61af0afe)通りにやったら解決した。

## `Failed to build gem native extension.`
実行すると以下のようなエラーが発生。

```
ERROR:  Error installing rails:
        ERROR: Failed to build gem native extension.

    current directory: /Library/Ruby/Gems/2.3.0/gems/nokogiri-1.10.3/ext/nokogiri
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby -r ./siteconf20190625-38062-z2jdpr.rb extconf.rb
mkmf.rb can't find header files for ruby at /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/include/ruby.h

extconf failed, exit code 1

Gem files will remain installed in /Library/Ruby/Gems/2.3.0/gems/nokogiri-1.10.3 for inspection.
Results logged to /Library/Ruby/Gems/2.3.0/extensions/universal-darwin-18/2.3.0/nokogiri-1.10.3/gem_make.out
```

`xcode-select --install`で治るという情報もあったが、こちらは既にインストールしてあったので、解決策にはならなそう。
MacOSのMojaveにはmacOS SDK Headerが入っていないのがエラーの原因らしいので、インストールする。

```
$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
```
## `the package path specified was invalid`
実行すると以下のようなエラーが発生。

```
installer: Error - the package path specified was invalid:
 '/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg'.
```

仕方ないので直接ダウンロードする。
[AppleDeveloper](https://developer.apple.com/)から`Command Line Tools (macOS 10.14)for Xcode 10.2.1`を検索。ダウンロードファイルを開いてそのままインストールを進めると`/Library/Developer/CommandLineTools/Packages/`にインストールされる。
AppleIDで認証する必要があるため少し面倒。

## まとめ
無事`sudo gem install rails`でrailsをインストールできた。
Mojave以前のソフトウェアアップデートでも同じような現象が起きたらしいので、以後のアップデートで同じ現象が起きた時用に。
【Solidity】コントラクトが他のコントラクトを実行する時の呼び出し方による動作の違い

# 概要
Solidityにはコントラクトから外部のコントラクトを呼ぶ時の方法が4つある．
それぞれの違いをまとめる．

# 動作の違いまとめ
| 方法 | msg.sender | storage | イメージ |
|----|----|----|---|
| 直接呼び出し | 呼び出し元コントラクト | 外部コントラクト | 外部コントラクトそのものを実行する
| call | 同上 | 同上 | 同上
| callcode | 呼び出し元コントラクト | 呼び出し元コントラクト | 外部コントラクトの関数を持ってきて実行する
| delegatecall | トランザクション発行者 | 呼び出し元コントラクト | 外部コントラクトの関数を持ってきて実行する

# コメント
callcodeは推奨されない

# Happy Hacking :sunglasses: !
ローカルファイルパスを URI オブジェクトに変換する

かなりどうでもいい小ネタです。たまにしかやらないとこういうもののほうがむしろ忘れるのでメモを兼ねて。

設定ファイルをURLで読み込むところがありまして。

ただ、デバッグ時にはローカルのファイルをデフォルト値にしたかったんですね。Uriといえばファイルスキームも使えます file:// でも、プロジェクトに置いたファイルをこれでどう指し示すかわかりません。相対URIも形式としてはあるけど、違いそう。

もののドキュメントには Uri クラスにはローカルファイルパスも渡せそうなので、

```CSharp
var uri = new Uri("hogehoge.txt");
```

みたいに書いてみたんですが、これもうまくいきません。

なので、もうFileInfoを経由することにしました。

```CSharp
var file = new FileInfo("hogehoge.txt");
var uri = new Uri(file.FullName);
```

これで大丈夫でした。
TextViewのEllipsizeする行数を動的に変更する

TextViewの高さが親と兄弟のレイアウトによって可変になる場合に以下のように、長すぎるテキストが見切れてしまうことがあります。
![figure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18273/9ebe78e0-c5b3-24e7-5a78-055b9b7aaf72.png)

`lines` と `ellipsize` を設定すれば良さそうですが、ビューの高さが可変なので `lines` も可変にする必要があります。
この問題は以下のようにサブクラスを定義することで解決できます。

```kotlin:DynamicEllipsizeTextView
class DynamicEllipsizeTextView : TextView {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(
        context,
        attrs,
        defStyleAttr,
        defStyleRes
    )

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        adjustEllipsize(bottom - top)
    }

    private fun adjustEllipsize(containerHeight: Int) {
        // レイアウトが確保した高さ内に収まる行数に設定
        val ableToShowLineCount = containerHeight / lineHeight
        setLines(ableToShowLineCount)
        
        // 更新を反映するために再度テキストを設定
        text = text
    }
}
```

結果はこのようになります。
4行表示できる高さでは4行で省略し、5行表示できる高さでは5行で省略します。
![figure2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18273/2f5f188e-5abd-8791-2aad-de6ee700137f.png)
お手軽らしいGASを使ったSlack APIのSlash Commandsを悪戦苦闘しながら作ってみた

はじめまして。
長年もっぱら見る専でしたが、そろそろ何か、とりあえず備忘録としてでも残せたらと思い立ち、1つ記事を書いていきます。

# きっかけ
最近Python勉強してるし、PythonでSlackのAPIとかお手軽にできないだろうか…。
Google Colabとか？いや、できないんか。Pythonは一旦置いておこう…。
何か…何か…。

え！！GASで簡単にSlack Botを？
~~出来らぁ！！~~

というわけでGASでSlack Botに手を出してみた次第です。

# 手順
Googleさんに聞けば先人達の知恵がたくさんあるので、細かいことは置いておき、
ざっくりと手順を書いていこうと思います。

## 1.GASの準備
簡単です。
Driveを開いて、左側の`「＋新規」`からGoogle Apps Scriptを選択するだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/a1c76ca2-2ad7-e716-b8b8-56fdfdd180d5.png)

すると、無題のプロジェクトが開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/f77aa02c-5b8b-2a12-8ccd-5a7e5067b741.png)

`ファイル` -> `名前を変更`
で適当に名前をつけてDrive上にプロジェクトを保存しておく。

Getでまず試して…とかもあるけど、
今回はとりあえずお試しでPOSTされた内容だけ知りたいため、以下の内容だけ。
ファイル名はデフォルトのコード.gsのままでもOK

```javascript:コード.gs
function doPost(e) {
  return ContentService.createTextOutput(JSON.stringify(e));
}
```

あとは
`公開` -> `ウェブアプリケーションとして導入...`
で
「アプリケーションにアクセスできるユーザー」を「全員（匿名ユーザーを含む）」にして導入をポチリ

すると以下のようなポップアップが開くのでURLを控えておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/0f1b6a68-0b8c-78b2-ea3e-a2d84e8716f7.png)

GAS側はこれだけ。

### ※ 少しはまったこと
一度公開してから、もう一度
`公開` -> `ウェブアプリケーションとして導入...`
を開くと、プロジェクトバージョンというものが`「1」`となっている。
このプロジェクト番号はコードに変更を加えて、試したい！ってなったときに、
毎回`「New」`を選択してバージョンアップし、更新ボタンで更新してやらなければ、
反映されたコードで試すことができないので注意。

## 2.Slack apiでApp作成
[https://api.slack.com/apps](https://api.slack.com/apps)
にアクセスして、`Create New App`
`App Name`を適当に付けて、Slackのワークスペースを選択して`Create App`で新規作成。

## 3.Slash Commandsの作成
画面が切り替わったら、`Features`の`Slash Commands`から`Create New Command`で以下のように設定。
Command : 実際にSlack側で打ちたいコマンド
Request URL : 先ほどGAS側で`ウェブアプリケーションとして導入...`で控えておいたURL
Short Description : Slack側でコマンドを入力したときに出てくる説明
Usage Hint : コマンドの例（無くても可）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/6959ed02-64e1-303b-0fcd-c8b871940f43.png)

あとは`Save`で完了。

## 4.Basic Information
スラッシュコマンドができたので
`Settings`の`Basic Information`で
`Add features and functionality`を確認。
以下のようになっていればスラッシュコマンドができている状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/1920117e-ade6-c60c-0f75-baef54ceb333.png)

あとは`Install your app to your workspace`の`Install App to Workspace`と進み、
ワークスペースにAppをインストールしてあげる。

## 5.完成!!
実際にSlackでコマンドを打ってみる…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/924d4eab-7b12-5459-b3a6-1740fa662cb7.png)

`parameter`から始まるjsonが返ってくれば成功！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55515/5c8e45d9-5fae-f65f-f269-b63af2eec25a.png)

あとは、このjsonの内容を元にいろいろと煮るなり焼くなり…。

# 最後に
いろいろ検索して参考にしてまわっていじってみましたが、
シンプルにSlash CommandsでのPOSTでのレスポンスを試してみたいだけなら、一旦はこれでいいのかなと。
これを元に、今後幅を広げていけそうです。

何か間違い等あればコメントお願いします！

# 参考
[Google Apps Script で Slack Botを作ってみた。(お勉強編)](https://qiita.com/Quikky/items/9de56c049304885a4f4f)
[Slash CommandsとGASでSlackのオリジナルコマンドをつくる](https://qiita.com/chikuwa111/items/7a1a349b82318a5861cc)
[Slack botをGASでつくる方法で一番楽そうなやつ](https://vaaaaaanquish.hatenablog.com/entry/2017/09/27/184352)
[初心者がGASでSlack Botをつくってみた](https://tech.camph.net/slack-bot-with-gas/)
php-master-changes 2019-06-24

今日はテストの修正があった！

# 2019-06-24
## cmb69: Split test case
- https://github.com/php/php-src/commit/94df6dc3fd07fa187ba09c587a8d1357fd8bbe6f
- [7.4~]
- sapi/cli で、ビルトインサーバのテストがなんかこけるので、1 テストで 2 ポートテストしていたのを 2 テストに分離
Looking Glassを用いた自由視点3Dビューアーの作り方

# はじめに
この記事では、Looking Glass Factoryから発売されているホログラフィックディスプレイ製品[Looking Glass](http://lookingglassfactory.com/products/the-looking-glass/#section-hardware-overview)をRealSense T265と組み合わせる事によって、自由視点3Dビューアーとして用いる方法について説明します。
基本的な実装方針は、Looking Glassのディスプレイの方向及び位置(6 DoF)情報を取得し、その情報をリアルタイムにUnityアプリケーション内に反映させる事によって、自由視点3Dビューアーとしての機能を実現します。

![LG_6DoF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112880/0d297fd3-9f98-53e5-6825-5d60ee1482e1.png)

# 事前準備
## 用意する物
- Looking Glass Small or Large model
- Intel RealSense T265
- Windows PC (Unity installed)

## H/Wの準備
1. 通常のLooking GlassのWindows PCとの接続設定を行います。具体的には、Looking Glassに付属のHDMIケーブル及びUSB 3.0ケーブルをWindows PCと接続します。
2. 次の画像のようにLooking Glassの背面にRealSense T265を両面テープで貼り付けます。

![FVLG_Back.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112880/bc0ccd50-2e8e-7bda-99c4-39a270a25f91.png)
3. RealSense T265とWindows PCを付属のUSB 3.0ケーブルで接続します。

## S/Wの準備
1. Windows PCに[Unity](https://unity.com/)をインストール
2. 最新版の[RealSense SDK 2.0](https://software.intel.com/en-us/realsense/sdk)一式をダウンロード
3. 最新版の[HoloPlaySDK](https://lookingglassfactory.com/devtools/holoplay-unity-sdk/)をダウンロード

# Unityを用いた自由視点ビューアーの実装方法
以下の例では、HoloPlay SDKに付属するScene( `Assets/Holoplay/Examples/1 - Framing Content with Holopay`)を例として自由視点ビューアーの作成方法を説明します。
![スクリーンショット 2019-06-25 14.12.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112880/74ccb7ec-8ce0-fe8b-c666-473ceb05f28c.png)

1. HoloPlay SDKのUnity packageをインポート
1. SDKのUnity package(Intel.Realsense.unitypackage)をインポート
1. RsDevice(Prefab)をシーンに配置、Profilesを1にしてStream=Pose, Format=Six DOFに設定
1. `Holoplay Capture` に”Rs Pose Stream Transformer Script(`RsPoseStreamTransformer.cs`)をアタッチし、SourceをRsDeviceに設定
1. 必要に応じて微調整(次節で説明します)
1. `Holoplay Capture`の"Toggle Preview Ctrl + E"を押下
1. Unity PlayerのPlayボタンを押してアプリケーションを実行
1. おもむろにLooking Glassを持ち上げる、Looking Glass内に表示されている3D Objectの映像が変化する事を確認

## 微調整方法の詳細
### スケール調整の調整方法
'RsPoseStreamTransformer.cs`に以下のように修正を加えます。

```cs:RsPoseStreamTransformer.cs
    void Update()
    {
        // 途中省略
        var t = pose.translation;
        float s = 50.0f; // 倍率
        t.Set(t.x * s, t.y * s, -t.z * s);
        var e = pose.rotation.eulerAngles;
        var r = Quaternion.Euler(-e.x, -e.y, e.z);
        // 途中省略
    }
```

今回の実装の経験値として50倍程度で、自然な動作になりました。

### Far Clip/Fov等を調整

'Holoplay Capture'のInspectorタブで"Advanced Camera Settings"を開くと、Fov、Near Clip Factor、Far Clip Factorを入力する画面が現れます。
実際に動作を確認しながら、自然な動作になるように値を調整してください。

# 最後に
以上説明した内容を実行する事で、Looking Glassを仮想世界の3D Objectを色々な視点から観察するためのビューアーとして利用する事が可能になります。
以下の動画は、実際のその動作を撮影した動画になります。
[![Free viewpoint 3D Viewer powered by Looking Glass ](https://i9.ytimg.com/vi/kj9qpgcOim8/mq2.jpg?sqp=CJi9xugF&rs=AOn4CLCH7CIbIY3W1aSM0JmedR0aXh5s_Q)](https://youtu.be/kj9qpgcOim8)
コンパイルとビルドの違いを理解しよう

# はじめに
コンパイルとビルド。
普段何となく飛び交っている二つの言葉ですが、意味が似ている為に混合して使用されていませんか？
実は私もコンパイル＝ビルドみたいに思っていた一人です。
その日の気分で、コンパイルが〜って言ってみたりビルドが〜って言ってみたり:sweat_smile:
これではまずいと思い、今回改めて２つの言葉の違いを調べたのでまとめます。

# 本題に入る前に前提としての知識確認
### ● ソースコードとは
私たちが書いているコードそのもののことです。
実際にコンピュータを動かすコードは、ソースコードではなく、コンピュータが認識できる**オブジェクトコード**というものです。
最初からオブジェクトコードを私たちが書ければ良いのですが、
とてもとても難しいので、私たちでも書きやすいように考案されたのが**ソースコード**です。
ソースコードは現在、様々なプログラミング言語で書かれており、RubyやPHP、JAVA等それぞれで固有の特徴を持ちます。

# いよいよ本題！コンパイルとビルドとは？？
### ● コンパイル
一言でいうと、**"ソースコードをオブジェクトコードに変換すること"** です！
ソースコードは、私たちが書きやすいようにオブジェクトコードを人間語で書いたようなものでしたね。
でもコンピュータは人間ではないので、コンピュータの言語（オブジェクトコード）に翻訳してあげないと理解してくれません。
その変換作業がコンパイル！
ここで重要なのは、
コンパイルはあくまでソースコードをオブジェクトコードに**変換するだけ**ということです！
変換した後の実行作業等は別になります。

### ● ビルド
ビルドとは、 **"コンパイルしたファイルを一つにまとめ、実際に実行まですること"** です。

噛み砕いて説明していきます。
まずコンパイルしている時点では、ファイルは全てバラバラです。
htmlファイルがあったり、jsファイルがあったり、rbファイルがあったり。。
オブジェクトコードに変換したけど、コンピュータが実行するにはバラバラすぎて何が何やらです。
そこで！
これは全部同じ実行ファイルだよ！と、実行する一連のファイルを一つの実行ファイルとしてまとめて整理するんですね。
（このまとめる作業をリンクと言います。）
またそれ以外にも、実行ファイルから参照される外部ファイル等がある場合は、その外部ファイルを適切な場所にコピーして配置します。
ビルドはこの一連の作業のことをまとめた言葉です。

#さいごに
どうでしょうか？？
コンパイルもビルドもよく使われる言葉だけに、しっかりと意味の違いを把握しておくことが大切だと思います。
コンパイルはビルドの作業の一部のことだったんですね。
ぜひこの機会に把握して頂き、知らない人にドヤ顔で説明しちゃってください:information_desk_person::sunny:

【参考URL】
http://e-words.jp/w/%E3%83%93%E3%83%AB%E3%83%89.html
https://www.weblio.jp/content/%E3%83%93%E3%83%AB%E3%83%89
JDBCにおけるコネクションプールの設定について調査してみた

# はじめに

弊社で運用しているシステムで突然、データベースに接続できない現象が発生した。
システムの中核と言われるデータベースに接続できない=システムが使えない状況に陥りました。

調査したところ、データベースに再起動が走ったため、アプリケーションサーバで抱えていたコネクションプールが全滅したのが原因でした。全滅後も、特に再接続が行われず、復旧までの間システムに死亡フラグが立ってしまいました。コネクションプールの設定も、サイズまわりは変更したものの他の設定はデフォルトのままでした。

# 技術スタック

|項目|名称|バージョン|
|:--|:--|:--|
|APサーバ|Payara Server|4.1|
|言語|Java|8|
|DB|Amazon Aurora PostgreSQL|9.6|

# 現象

そもそもコネクションプールとは、コストがかかるDB接続を使いまわそうという仕組みです。
アプリサーバ起動時は次のような状態になってます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53830/12d26f76-80a8-942c-9a82-e8b541d85420.png)

接続な正常な場合、リクエスト時は以下のようになります。

![スクリーンショット 2019-06-25 13.52.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53830/9f4398be-63a7-170e-5e86-03369fc2307d.png)

今回はデータベースが再起動され、以下のような状態になりました。

![スクリーンショット 2019-06-25 13.57.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53830/9eed77b1-8a06-b347-c374-fc7dcbe4dcd4.png)

この状態のまま、接続状態な異常のままコネクションプールに残り続け、アプリからは一切データベースに接続できなくなりました。

# 対応

対応としては、プール内にある接続を全て再接続させるようにすることです。

- 接続状態を検証

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53830/836d041f-1443-b6b4-ed40-8c717f01ad92.png)

- プール内の接続を全て削除

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53830/07c85949-ea80-32ae-ff42-3d2f916315ae.png)

- 再接続

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53830/b00a6f95-1836-3889-6ce7-f333bbe20db0.png)

# 今回修正したパラメータ

パラメータの設定値は、環境に応じて適宜変更してください。

|パラメータ|概要|設定値|
|:--|:--|:--|
|connection-creation-retry-attempts|再接続リトライ回数|3| 
|connection-creation-retry-interval-in-seconds|再接続リトライインターバル|10| 
|is-connection-validation-required|接続検証の有無|true| 
|validate-atmost-once-period-in-seconds|接続検証のインターバル|1| 
|fail-all-connections|接続異常時に全てのプールを削除の有無|true|
VScode のFont Family設定でハマった話




## やりたいこと

WindowsのVSCodeでotfやttfでインストールしてきたフォントを利用したい.

僕の場合, プログラミングだけでなく, markdown形式で原稿の執筆したりしたかったので, いろいろとフォントを変えて試していたんですが, 反映されたり反映されないフォントがあって意外とハマってしまいました. 
今回は, 解決のために何をしていったかという話を書いていきます. 

設定したはずのフォントが上手く反映されず, 困っている人の助けになれば幸いです. 

## 解決策

### 解決策1: VSCodeの再起動

ここでは例としてプログラミング用フォントのRicty Diminishedをttf形式でインストールします.  

インストール後, VSCodeのsettings.jsonで以下の記述を追加. 

    "editor.fontFamily": "Ricty Diminished",

ここでフォントの確認をしたときに反映されなかったりすることがあるんですが, VSCodeの**再起動で反映**されるようになりました.  

### 解決策2: Font Familyに記述すべきファミリ名を知る

settings.jsonにFontFamilyを設定して, VSCodeを再起動したにも関わらず何も変化しない場合があります. 

そういう場合は, そもそもFontFamilyに設定している名前を間違えている可能性があります. 特に日本語用フォントや有料フォントにありがちなんですが, フォント名と設定するファミリ名が違ったりすることがあるので, 以下の方法で確認してみてください. 

Windows10 の場合 `コントロールパネル > デスクトップのカスタマイズ > フォント`の順で開くとPCにインストールされているフォント一覧が確認できます. 

設定すべきはここにある名前ではなく, 画像のようにファミリを有効にして確認できるファミリこそVSCodeのFont Familyに記述すべきファミリ名です. スペースも忘れずに入力してください. 

![スクリーンショット (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144207/12861e13-6082-a88c-4da3-2c6fa0e3233d.png)
![スクリーンショット (28)_LI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144207/074cc6ce-beff-3276-d31d-c6c9e8eb11bf.png)



## あとがき

まさかフォントの設定でハマるとは思っていなかったので, 思わぬところで時間を取られてしまいました. 
初期設定はサクッと終わらせて, もりもり開発していきましょう！
pyfolioを使ってみる

# はじめに
## pyfolioとは
ポートフォリオのパフォーマンスやリスクの分析に役立つPythonライブラリで、3年ほど前に[Quantopian Inc](https://www.quantopian.com/)からリリースされました。

主な機能は様々なグラフを描画して、ポートフォリオを全体像を分析を助けます。
(個々の複数のグラフをまとめたものをtear sheetと呼びます。)

## 今回やること
https://github.com/quantopian/pyfolio/blob/master/pyfolio/examples/full_tear_sheet_example.ipynb

上記のURLを参考にtear sheetの作成してみます。

内容は、一つの銘柄の日次リターンをから様々な図を描画してtear sheetを作成する感じです。(本記事ではgoogleの株価を取得しています。)

上記URLのコードをそのまま実行してもエラーを吐くので注意です。

原因は、pyfolioがgoogle financeからデータを取得していることです。google financeは過去に公式APIの提供を終了していて、非公式のものが出回っていましが、その非公式APIが廃止されたことが原因のようです。

# tear sheetの作成
##環境
Google Colaboratory、Jupyter Notebookなど
## ライブラリの準備
pyfolioのインストール

```python
pip install pyfolio
```
必要なライブラリをインポート

```python
import pandas as pd
import pyfolio as pf
%matplotlib inline

import warnings
warnings.filterwarnings('ignore')

import pandas_datareader.data as pdr
```

`%matplotlib inline`はJupyter Notebookで、ノートブック上にグラフを描画する際に指定する記述です。

`warnings`は実行結果対し特に影響のない警告の表示を消すためのライブラリです。臭いものには蓋をしましょう。

`pandas_datareader`は株価を取得するときに使うライブラリです。株価だけでなく、インターネット上の様々なデータソースからデータの取得を行うことが可能です。




## 株価データの取得
###yahooo financeからgoogleの株価データを取得する
以下の一行でOKです

```python
google = pdr.DataReader('GOOGL', 'yahoo', '2018/1/1', '2019/1/1')
```
DataReaderの引数は4つで、
・name: 銘柄(str型もしくはstr型のlist)
・data_source: 取り出したい元(str型)
・start: 取得開始日(datetime型)
・end: 取得終了日(datetime型)
       (これがないと入力した日付まで取得することになります)
となっています。

データは以下のようなpandas.DataFrame型で取得されます。
head、tailを使ってはじめと終わりの5行を取り出しています。

```python
google.head(5)
```
![スクリーンショット (57).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354177/a14c17de-550d-e139-6bec-c77a17be1c97.png)

```python
google.tail(5)
```
![スクリーンショット (58).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354177/3a3ab272-fa6e-3b14-2fac-99b167a1491f.png)

## 日次リターンの算出
リターンを計算するために終値を使います。

tear sheetを作成するpyfolioのメソッドに渡すリターンのデータはpanda.Series型である必要があります。

```python
cp_google = google['Close']
# cp は colse price の略
```

続いて日次リターンの算出です。

日次リターンの計算式は以下のようになりますが、

```python
(当日の終値 ÷ 全日の終値) - 1　
```

pandasのメソッドを使って簡単に取得できます。

```python
return_google = cp_google.pct_change().dropna()
#dropna() は1行目の欠損値処理
```

## tear sheetの描画

```python
pf.create_returns_tear_sheet(return_google)
```

と実行すると以下を出力します。

![スクリーンショット (66).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354177/3e6d9296-e6c4-b914-2c70-f4b6707cacdc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354177/e5c708a1-e6f4-e94e-35ac-18bfc8deb80a.png)

#今後の展望
pyfolioには他にも色々なtear sheetがあるのでそれらの使い方を調査していきたいです。

また、tear sheetを使った分析方法も勉強して、高いパフォーマンスを発揮できるアルゴリズムを作りたいと考えています。
Machine Learning Recommender Pitch 勉強会メモ

# 概要

[Machine Learning Recommender Pitch](https://machine-learning-pitch.connpass.com/event/132858/)

> Machine Learning Pitchは、機械学習について業務で培った知見や経験や苦労話を共有できる場を提供することを目的としたMeetupグループです。機械学習に取り組み、実社会への適用に日々もがき苦しみ楽しんでいる方々を対象としております。

> 機械学習を実際の製品やサービスに提供するためには、企画（プランナー）、設計（機械学習エンジニア、データサイエンティスト）、基盤（サーバーサイドエンジニア、インフラエンジニア）、品質保証（QAエンジニア、セキュリティエンジニア）、分析（データアナリスト）など様々な職種の協力が必要です。Machine Learning Pitchでは、定期的に毎回テーマを決めて実務者の方々に発表して頂きます。



# 発表内容

## [パーソナライゼーションのためのマルチリービング](https://speakerdeck.com/zr_4/pasonaraizesiyonfalsetamefalsemarutiribingu)

- マルチリービング
    - ABテストと比べ、複数アルゴリズムの検証期間が少なくて済む
    - 群のバイアスに左右されない
    - 一方、ランキングの間接的な影響を評価しにくい

    - 検索で適応されたもので、パーソナライゼーション上での適用事例がない


- 課題
    - パーソナライゼーションにおいて、マルチリービングの負荷が高い
    - 定式化の修正により、高速化
    - フィードバック関数の設計

- オフライン評価
    - 安定性を検証
    - ランキング長とランキングの種類を変化させる
    - 提案手法の方が安定している

- オンライン評価
   - ABテストとマルチリービングでサンプルサイズとp値をを比較
    - 効率的に性能評価できる

## [Graph Convolutional Networkを使った推薦システム](https://speakerdeck.com/nishiba/graph-convolutional-networkswoshi-tuta-tui-jian-sisutemu)

- 問題設定
    - 記事をユーザごとに出し分け
        - 記事へのアクセス数は少ない
    - inactiveユーザにもうまくだしたい
        - 日本の医師は30万と限られているため、inactiveユーザへのアプローチが重要
    - 興味に合わせたものを出したい
        - 若手にはキャリア関連
        - 医師の専門分野(内科、外科など)

- GCNモデル
    - ユーザとアイテムの二部グラフ
    - 属性データはLatent crossに統合する

    - ユーザは、クリックしたアイテムのembeddingの平均で表現する
    - アイテムは、クリックしたユーザのembeddingの平均で表現する

    - ユーザがアイテムをクリックする確率をembeddingのコサイン類似度で計算する

    - 新しいアイテムもクリックがあれば計算できる

- 評価
    - 直近のデータを分割して、テストデータをする
    - データがたまっていない直近のデータからレコメンドされるかを確認する
    - オフライン検証で、Rankingモデルよりも高いスコア
    - ユーザに対して、様々な記事を満遍なく推薦できている

- モデルの挙動
    - 似ているユーザの埋め込みは近くなる
    - ユーザのクリックからアイテムの埋め込みが計算される
    - みんなに見られる人気のアイテムは、平均をとるとみんなから遠くなる

- その他
    - 毎日クリックしているようなユーザは推薦するメリットがないので除いている


## [クックパッドにおける推薦(と検索)の取り組み](https://speakerdeck.com/chie8842/kutukupatudoniokerutui-jian-tojian-suo-falsequ-rizu-mi)

- 検索と推薦
    - 検索　クックパッド内で回遊させたい
    - 推薦　気に入ったレシピをいち早く見つけたい

- KPIが立てづらい
    - ビジネスモデルとしてはプレミアム会員数、施策のゴールとしては遠い
    - CGMとしては、人気のレシピだけを推薦すると、多くのユーザの満足度に繋がらない
    - ユーザが目当てのレシピに行き着いたかどうかわからない

- 負の影響
    - 検索による回遊率の低下への影響
    - 推薦結果が悪い場合のプレミアム会員数低下
CentOS7でT2からT3へ変更時のNIC名変更への対応

# はじめに

AWSでCentOS7で動いているEC2インスタンスをNitro世代(C5、M5、T3、…)に変更する際に
ハマったので、誰かの助けになればと思いメモっておきます。

## 通常の手順

Nitroシステムを使うにはENAを有効にする必要があり、AWSの公式リファレンスやググってみると
以下のような手順が出ます

- ixgbevfモジュールを入れる
- enaモジュールを入れる(kernelアップデート)
- インスタンス停止
- modify-instance-attributeでena-supportを有効にする
- インスタンスタイプ変更
- インスタンス起動

CentOS7の場合、上記だけで対応できない部分があったので、その解決方法を紹介します。

# ハマりポイント

CentOS7からNIC名はensXのような名前となり、従来のethXではなくなっています。
ですが、AWS EC2インスタンスのNitro世代前のインスタンスタイプでは、デフォルトでeth0が
使われます。

これをNitro世代に変更するとensXという名称が使われるようになります。
（カーネル起動オプションなどで固定はできますが、クラウド上でそこいじりたくない、という前提）

そのままENA有効化して起動してもネットワークが繋がりません。
以下のその際にシスログに出力される内容です。MetaDataアクセスができていません。

```
Jun 25 10:47:02 sva0110 journal: [CLOUDINIT] url_helper.py[WARNING]: Calling 'http://169.254.169.254/2009-04-04/meta-data/instance-id' failed [87/120s]: unexpected error ['NoneType' object has no attribute 'status_code']
```

# 変更後の手順

- ixgbevfモジュールを入れる
- enaモジュールを入れる(kernelアップデート)
- <font color="red">cloud-initアップデート</font>
- インスタンス停止
- modify-instance-attributeでena-supportを有効にする
- <font color="red">AMI作成</font>
- <font color="red">AMIからNitro世代インスタンスタイプを指定して起動</font>

## 解説

最新版のcloud-init(現時点：18.2-1）ではインスタンス初回起動時の処理でethXからensXへの
変更も行ってくれるようです！
なので、AMIを作ってAMIからインスタンス作成すればNitro世代でも起動できるようになります。

# まとめ

書いている途中に カーネル起動オプションを修正している公式な手順が見つかりました！！
https://aws.amazon.com/jp/premiumsupport/knowledge-center/install-ena-driver-rhel-ec2/
ということで、意味のない記事になってしまいましたが、もしかしたらこっちの手順の方がよいという
人もいるかもしれないので、そのまま公開します。

最後に、こっちもハマりどころだと思うので紹介しておきます。
[NITRO世代(T3など)へのEC2インスタンスタイプ変更ではfstabに注意](https://qiita.com/isobecky74/items/4dddb4407ac7e5f2c45a)
Azureの監視手法の種類と使い分け

参考：https://docs.microsoft.com/ja-jp/learn/modules/design-for-efficiency-and-operations-in-azure/3-use-monitoring-and-analytics-to-gain-operational-insights
「Azure で最適なソリューションを設計する-Azure での効率性と運用を考慮した設計-監視と分析を使用して運用に関する分析情報を得る」

# アクティビティ ログ
　リソースに対して実行されたすべてのアクションをトレースできる
　アクティビティ ログのデータは 90 日間だけ保持され、ストレージ アカウントにアーカイブしたり、さらに長い保持や詳しい分析のために Azure Log Analytics に送信したりすることができる。

# Azure Service Health
　Azure サービスに影響する問題がお使いの環境に影響を与えるかどうかや、どのようなときか、といったことを理解するのに役立ちます。 局所的な問題のように見えることがもっと広い範囲の問題の結果である可能性があり、Azure Service Health ではその分析情報が提供されます。 Azure Service Health では、お使いのアプリケーションに影響を与える可能性のある Azure サービスでの問題が識別されます。 Service Health は、予定メンテナンスの計画にも役立ちます。

# Azure Monitor
　Azure サービスには正常性、メトリック、または診断の情報を表示する共通の方法があります。 Azure Monitor では、メトリック、アクティビティ ログ、診断ログを収集、集計、視覚化して、Azure サービスのコアな監視を行うことができます。
　メトリックでは、各種リソースはもちろんのこと、仮想マシン内のオペレーティング システムについても、パフォーマンス統計情報を収集できます。 Azure portal のいずれかのエクスプローラーを使用してこのデータを表示し、これらのメトリックに基づいてアラートを作成することができます。 Azure Monitor では非常に高速なメトリックのパイプライン (5 分から最短 1 分) が提供されるため、スピードが重視されるアラートと通知に使用してください。

# Azure Advisor
　リソース内でのパフォーマンス、コスト、高可用性、セキュリティに関する潜在的な問題の監視を維持することができます。 Advisor では、リソースの構成とテレメトリに基づいてユーザーに応じた推奨事項が作成され、従来のほとんどの監視プラットフォームでは提供されないようなガイダンスが提供されます。

# Log Analytics
　Log Analytics は、Azure リソースから監視データを受け取り、コンシューマーが分析や視覚化に利用できるようにします。
Log Analytics 内のこのデータでは、トラブルシューティング、根本原因の識別、監査の目的のために、生データをクエリできます。 いくつかのよく知られたサービス (SQL Server、Windows Server Active Directory) には、すぐに使用できる管理ソリューションがあり、監視データを表示したり、ベスト プラクティスへの準拠を明らかにしたりできます。
　Log Analytics では、クエリを作成し、それらのクエリに基づいて他のシステムとやりとりすることができます。 最も一般的な例はアラートです。 システムのディスク領域が不足したとき、または SQL Server がベスト プラクティスに準拠しなくなったときは、メールを受け取りたいと思うでしょう。 Log Analytics では、アラートの送信やオートメーションの開始、さらには IT サービス管理 (ITSM) との統合などのためのカスタム API へのフックを行うことができます。

# Application Insight
　アプリケーションを詳細に調べてパフォーマンスの問題、使用の傾向、開発したサービスや依存しているサービスの全体的な可用性を明らかにすることで、監視機能をいっそう拡張できます。 アプリケーション パフォーマンス管理ツールを使用することにより、Web アプリとサービスの内部で発生した問題の検出と診断を向上させることができる。
　Azure Application Insights を使用すると、まさにそれを実行できます。 
　Application Insights では、テレメトリの収集、クエリ、視覚化の機能が提供されます。 コードを変更する必要はほとんど、またはまったくありません。 小さなインストルメンテーション パッケージをアプリケーションにインストールすることだけが必要です。 Application Insights はクロスプラットフォームであり、.NET、Node.js、Java がサポートされています。
AWS IAMの管理ポリシーはたまに勝手にアップデートするので要注意

#背景
今日たまたまAWSのマネジメントコンソールにログインしたとき、IAMの管理画面に「AWS Organizations」が増えていたことに気づきました。
ログイン中のIAM Userでは、Oranizationsに対する一切の権限は与えられていないはずなので、押しても何も見えないはずと思い、恐る恐る押してみると、なんとOrganizationsの設定が見えてしまいました。
##IAMの管理画面がアップデートされた図
下部に「AWS Organizations」が増えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211986/e15e2ac9-8cce-9e92-c072-b8da0563c311.png)
##見えないはずのものが見えたの図
IAMの管理画面から、Organizationsの設定が見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211986/f46147dd-b63f-8c4d-ef05-53ad6c42e33a.png)
#原因
Organizationsの権限が付与されたわけではない(その記憶がない)のに、なぜOrganizationsの設定が見えてしまうのか気になりました。
調査したところ、ログイン中のIAM Userには「IAMFullAccess」という管理ポリシーがアタッチされており、この管理ポリシーが最近アップデートされていました。
IAMの管理画面がアップデートされるのを機に、権限が増えたのでしょう。
##IAMの管理ポリシーがアップデートされたの図
2019/6/22に、バージョンが増えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211986/2d6fceba-863c-c8f9-ab6d-a1c2eb986b0f.png)
##Version 1
権限は「iam:*」のみです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211986/02d7c1aa-5dcb-323b-aaf1-772ef9f4733d.png)
##Version 2
「organizations」の権限が増えています。
現在の設定は、デフォルトでこのVersion 2になるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211986/41f5eefb-4c97-8ee7-a504-8716178a6f56.png)
#教訓
今回、IAMの管理ポリシーが勝手にアップデートされ、権限が増えるという場面に遭遇しました。
つまり、意図せず権限が勝手に増えることを防ぐためには、管理ポリシーを使わず、独自にポリシーを作成してアタッチしなければならないようです。
管理ポリシーは便利ですが、勝手にアップデートすることがあると理解して使うべし、ということですね。
jenvを使って、複数バージョンのJavaを使えるようにする

# jenv
現場の開発で、複数バージョンのJavaを使う機会が出てきたので、
切り替えながら使う方法を整理しました。

### インストールと設定
GitHubに公開されているので、もってきて設定します。

```
$ git clone https://github.com/gcuisinier/jenv.git ~/.jenv
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(jenv init -)"' >> ~/.bash_profile
```

### Java homeの登録
Javaは事前にインストールしておいてください。addで、Javaのホームディレクトリを登録していきます。
```
$ jenv add /usr/lib/jvm/java-11-openjdk-amd64
$ jenv add /opt/jdk1.7.0_80/
```
### バージョンの確認

```
$ jenv versions
  system
* 1.7 (set by /home/hogehoge/.jenv/version)
  1.7.0.80
  11.0
  11.0.3
  openjdk64-11.0.3
  oracle64-1.7.0.80
```

### 環境の切り替え全体のJavaバージョンの切り替え

```
$ jenv global oracle64-1.7.0.80
```

### 所定のディレクトリは配下のJavaバージョンの切り替え

```
$ mkdir java7
$ cd java7
$ jenv local oracle64-1.7.0.80
```
これでjava7の配下でのみJavaのバージョンが変わります
マイグレーションについて

前職で、「マイグレーションについて調べてみて。」と言われたけど、結局何を調べて答えたのか忘れてメモもしてなくて。改めて調べてみました。

　↑キーワード検索から、いろんな人の記事を漁るのも良い方法かもしれません。


# Migration とは何者か
【現時点での理解】
　　複数人で開発していて、データベースが勝手に書き換えられるような環境での開発で、 
　全員がおんなじ状態のDBを使えるようにする仕組み。

　ソースコードに対するバージョンコントローラの Git 、
　データベースに対するバージョンコントローラの Migration

　みたいなものでしょうか。
　※筆者は主に PHP/Laravel を書きます。

　[teratailでの質問](https://teratail.com/questions/5843)


## PHP/Laravel の場合

　[Laravelドキュメント:マイグレーション](https://readouble.com/laravel/5.8/ja/migrations.html)
　[bz0さんの記事](https://qiita.com/bz0/items/44b9280fd17566b8c49e)

## Ruby on Rails の場合

　[sntkazuさんの記事](https://qiita.com/sntkazu/items/66cfa1e6e1350f248b24)
　[wacker8818さんの記事](https://qiita.com/wacker8818/items/47333d5ff61c8b9d324d)

## Python/Django の場合

　[okoppe8さんの記事](https://qiita.com/okoppe8/items/c9f8372d5ac9a9679396)
laravel redis cache

laravel で redis キャッシュを使いたい。
ほんとだっるい。

ついでに session も redis にしてやる。

```.env

CACHE_DRIVER=redis
REDIS_HOST=133.230.222.333
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_DB=7
REDIS_READ_WRITE_TIMEOUT=60
SESSION_DRIVER=redis


```


database.php

```

    'redis' => [

        'client' => 'predis',
        'default' => [
            'host' => '133.230.222.333',
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 7),
        ],

        'cache' => [
            'host' => '133.230.222.333',
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 7),
        ],

    ],

```

cache.php 18行目あたり

```

    'default' => env('CACHE_DRIVER', 'redis'),

```




これでredisに入れられます。

`use Illuminate\Support\Facades\Cache;` を忘れずに。

```

        $name = 'hoge_1';//キャッシュの名前
        $time = 3;//秒

        //        キャッシュがあれば使う。なければ処理をして返す。

//        {}内で変数を使いたい場合は use を使う
//        $data = Cache::remember($name,$time, function () use ($repeat,$social_id) {
        $data = Cache::remember($name,$time, function () {
            $data = "ほげ".time();
            return $data;
        });

        Cache::forget($name);//キャッシュを削除

```
Rails production環境で Mysql2::Error: Disk full が出たときの対処

#エラー内容
ある日、production環境で以下のようなDisk fullエラーが出ました。

```
Mysql2::Error: Disk full (/tmp/#sql_253_1.MAI); waiting for someone to free some space... (errno: 28 "No space left on device"):
```

ログがたまりすぎてディスク容量がいっぱいエラーなので、以下のコマンド実行で解決。

#解決法

```
bundle exec rails log:clear
```


ログローテション設定しないと。。
PHPで何かつくる！

本稿は、筆者のアイデアノートとなります。
書き始めて、それぞれ形になったら、別記事としてUPしていきます。
[別記事]()で書いてる物をPHPでも実装してみることになると予想。

## 目的

- PHPと仲良くなる。
- [Laravel](https://readouble.com/laravel/) 以外のフレームワークに積極的に触れる。

## 作りたいもの

- Webスクレイピングサイト
- パスワード暗号化提案サイト
- 自宅監視システム（虫検知）
  - Raspberry Pi と カメラモジュール
  - 虫判定 = [Tensorflow](https://www.tensorflow.org/) をこねこねする

---
#### 参考

[初めてのPHP](https://www.amazon.co.jp/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEPHP-David-Sklar/dp/4873117933)
WSL上のemacs向けclipboard-copy関数を作成した

皆さんは、どうやって clipboard に copy していますか？

僕は、 `clipboard-copy` 関数を init-loader を使って 環境別でそれぞれ定義していました。
ただ WSL では GNU/Linux として認識しつつ、コマンド `xsel` では copy できず、
`clip.exe` を使う必要がありました。

愚直に Linux 側の関数で判定するしか思いつかなかったんですが、紹介します。
もっといい方法があれば、教えていただけると幸いです ＼(^o^)／

## 環境

- WSL 1
- GNU Emacs 25.2.2
- Linux XX 4.4.0-17763-Microsoft #379-Microsoft Wed Mar 06 19:16:00 PST 2019 x86_64 x86_64 x86_64 GNU/Linux

## 実装

WSL 1上であれば、 `uname -a` の結果に Microsoft が入るので、これを用います。
（これが悪用している感じあるので、変えたい）

以下関数を linux-custom.el (init-loaderを使っているので）に記述し、
Linux上での起動時に定義しつつ、実行時になりますが...良しなに切り替えました。

```elisp
(defun isWSL ()
  "run emacs on windows subsystem linux ?"
  (if (string= "" (shell-command-to-string "uname -r |grep Microsoft"))
    nil
    t))

(defun clipboard-copy ()
  (interactive)
  (when (region-active-p)
    (if (isWSL)
      (shell-command-on-region (region-beginning) (region-end) "clip.exe" nil nil)
      (shell-command-on-region (region-beginning) (region-end) "xsel --clipboard --input" nil nil)
      )
   )
)

```
redis 使われている データベース一覧を取得

まずはポートを指定してredis-cliを起動。
 (一般的には 6379)

```

/usr/local/bin/redis-cli -p 6363

```

Redisのパスワードを入力し、ログイン

```

AUTH yourredispass

```

ログイン完了したら info と入力し enter。
一般的には redis は 0〜15 まで使える。

```

db3:keys=1781819,expires=1781819,avg_ttl=5865146908
db4:keys=352381,expires=352381,avg_ttl=6014054315
db5:keys=46,expires=46,avg_ttl=34158613
db6:keys=2398,expires=2398,avg_ttl=84076031837
db7:keys=1121,expires=1054,avg_ttl=7406287
db10:keys=23296,expires=23296,avg_ttl=6397679837

```

これでどのDBを使っているか一目瞭然ですね。
springで共通エラーページへ飛ばす

## プログラム
このように、400エラーのときも403エラーのときも、全て同じように
「common_error.jsp」を指定することで、下記のエラーが出ても、tomcatのエラー表示はされなくなり、自分で作ったページが表示されます。
今回はどのエラーでも同じページを表示するようにしていますが、
よくある404のときは404の可愛い画像を表示したかったら、そのページを指定すればよいということになります。

```web.xml
 <error-page>
    <error-code>400</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
    <error-page>
    <error-code>403</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
  <error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
  <error-page>
    <error-code>405</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
  <error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
    <error-page>
    <error-code>501</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
    <error-page>
    <error-code>502</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
  
    <error-page>
    <error-code>503</error-code>
    <location>/WEB-INF/jsp/common_error.jsp</location>
  </error-page>
```
受けたメールをすべて捨てるSMTPブラックホールサーバの作り方② 

[前回の記事](https://qiita.com/qualitia_cdev/items/3ab284ca92939f58b9bb)で予告した通り、今回はmaster.cfの設定変更だけでSMTPブラックホールサーバを作るスマートな方法を紹介します。


#### Postfixのインストール
CentOS7.4でyumを使ってインストールしました。

#### main.cfの設定
/etc/postfix/main.cfを編集します。
変えた項目は以下の通り。あくまで私の設定例です。

```
myhostname = example.com
mynetworks = 127.0.0.0/8, 172.16.0.0/24(*制限かけています)
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
local_recipient_maps = 
```

#### master.cfの設定
/etc/postfix/master.cfを編集します。
変えた項目は以下のとおり。

```
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=discard:
  -o smtpd_client_restrictions=permit
  -o smtpd_recipient_restrictions=permit,reject
```


#### Postfixのreload
postfixをreloadします。

```
# postfix reload
```

これで作業は完了です。telnetなどでメールを送ると、mailogに以下のようなPostfixがメールをdiscardしたログが出力されます。

```
postfix/discard[3728]: 67BAC4A4DC5: to=<test@example.com>, relay=none, delay=8, delays=8/0.01/0/0, dsn=2.0.0, status=sent (example.com)
postfix/qmgr[3649]: 67BAC4A4DC5: removed
```

注意点はやはりネットワークの設定です。攻撃の対象になることもあるので十分気をつけましょう。

次回は、Dockerを使ってこのメールサーバを立ち上げる方法を紹介します。

*関連記事
[受けたメールをすべて捨てるSMTPブラックホールサーバの作り方①](https://qiita.com/qualitia_cdev/items/3ab284ca92939f58b9bb)
[受けたメールをすべて捨てるSMTPブラックホールサーバの作り方②]
(https://qiita.com/qualitia_cdev/items/85aaffcd5fddae5afb4c)
[受けたメールをすべて捨てるSMTPブラックホールサーバの作り方③ - Dockerを使う]
(https://qiita.com/qualitia_cdev/items/7f165e5f7e62e46ebe2b)
Springでバリデーション(アノテーションだけではなく)

## プログラム
まず、フォームの値を保持するモデルを作成します。

```java:SignUpQuestionFormModel.java
@GroupSequence({ Group1.class,SignUpQuestionFormModel.class })
public class SignUpQuestionFormModel {
    public interface Group1 {
        
    }
    @NotEmpty(message = "必須入力です" , groups = Group1.class)
    @Size(max = 20, message = "{max}文字以内で入力してください" )
    @Pattern(regexp = "^[0-9a-zA-Z]+$", message = "正しいフォーマットで入力してください" )
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
```

次に、バリデーションのサービスを作ります。
上記のモデルの中のアノテーションだけでもバリデーションはできますが、少し複雑なものとかやったりアノテーションだけではできないこともあるので、作成しました(文字数とか必須ぐらいならアノテーションだけでもいいですが)


```java:SignUpValidationService.java
@Service
public class SignUpValidationService {

    public ModelAndView validation(SignUpQuestionFormModel model) {

        ModelAndView mav = new ModelAndView();

        String name = model.getName();

        //氏名は、必須と桁数20以下
        if (name != null && !(name.equals(""))) {
            if (name.length() > 20) {
                mav.addObject("name_msg", "氏名には20桁以内で入力してください。");
            }
        } else {
            mav.addObject("name_msg", "氏名は必ず入力してください");
        }

        //何もひっかからなかったらnullを返す
        if (mav.isEmpty()) {
            return null;
        }
        //ひっかかったらビュー名指定してreturnする
        mav.setViewName("SignUpForm");
        return mav;
   }
}
```

次に、上記のバリデーションサービスをコントローラーから使います。

```java:SignUpController.java
    //新規会員登録の確認画面処理
    @RequestMapping(path = "/SignUpConfirmation", method = RequestMethod.POST)
    public ModelAndView SignUpConfirmation(@Valid SignUpQuestionFormModel model, BindingResult errors,
            HttpSession session) {
     //バリデーション開始
        ModelAndView mav = null;
        // BeanValidationを使用しないバリデーション
        mav = svs.validation(model);
        if (mav != null) {//上記のメソッドでは、一つのバリデーションひっかからなかったら、nullが得られる。
            System.out.println("新規登録の際、バリデーションエラーが起きたので戻る");
            return mav;
        }

    //バリデーション通過したら、DB処理した後に行きたいところに遷移
}
```
sudoを実行するときに環境変数を引き継ぐ

Ubuntuを使っていて、aptとかでインストールをやろうとすると、Proxy環境だと少しコツが必要

ログインユーザの環境変数で、http_proxy、https_proxyを設定していてもSudoには引き継がれない。
そういう場合は、以下の通り

```bash
sudo -E apt update
```

これでログインユーザの環境変数を引き継いで、sudoが実行されます。
Unityエディタ拡張でサウンド再生を行う

## 経緯
Unityのエディタ拡張でサウンドコンテナなどを作ってた時に保持したAudioClipの内容を再生したい( 該当AudioClipの場所にInspectorを移動したくない )場合に調べたのでここに共有

ちなみにデフォでサウンドファイル選択時に音声は鳴らせる→[ここ](http://kan-kikuchi.hatenablog.com/entry/AudioClipTips)を参照



## スクリプト


AudioClipの再生は[ここ](http://baba-s.hatenablog.com/entry/2017/12/04/173920)を参考に作成
停止方法が見つからなかったので[探してきた](https://github.com/jamesjlinden/unity-decompiled/blob/master/UnityEditor/UnityEditor/AudioUtil.cs)


```csharp
using System;
using UnityEngine;


#if UNITY_EDITOR
using System.Reflection;
using UnityEditor;
#endif


namespace Sample
{
    // SE,BGMの管理用コンテナクラス.
    [System.Serializable]
    public class SampleContainer : ScriptableObject
    {

        // 保持するデータ.
        [SerializeField] AudioClip soundData;

        
#if UNITY_EDITOR
        // SampleContainerのインスペクタ拡張.
        [CustomEditor(typeof(SampleContainer))]
        class SampleContainerEditor : UnityEditor.Editor
        {

            // インスペクタ描画.
            public override void OnInspectorGUI()
            {
                var data = target as SampleContainer;

                data.soundData = (AudioClip)EditorGUILayout.ObjectField("AudioClip", data.soundData, typeof(AudioClip));
                
                if (GUILayout.Button("PlayClip"))
                    this.PlayClip(data.soundData);
                
                if (GUILayout.Button("StopClip"))
                    this.StopClip(data.soundData);
            }


            // エディタ上でのサウンド再生.
            void PlayClip( 
                AudioClip clip)
            {
                if (clip == null) return;
                
                var unityEditorAssembly = typeof(AudioImporter).Assembly;
                var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
                var method = audioUtilClass.GetMethod
                (
                    "PlayClip",
                    BindingFlags.Static | BindingFlags.Public,
                    null,
                    new Type[] {typeof(AudioClip)},
                    null
                );

                method.Invoke(null, new object[] {clip});
            }


            // エディタ上でのサウンドを停止する.
            void StopClip(
                AudioClip clip)
            {
                if (clip == null) return;

                var unityEditorAssembly = typeof(AudioImporter).Assembly;
                var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
                var method = audioUtilClass.GetMethod(
                    "StopClip",
                    BindingFlags.Static | BindingFlags.Public,
                    null,
                    new Type[] {typeof(AudioClip)},
                    null
                );

                method.Invoke(null, new object[] {clip});
            }
            
        }
#endif
    }
}

```

## 実行画面

こんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212999/54525a62-dafa-e1e5-d5a2-737a7724f8b4.png)

ScriptableObjectをインスタンス化してAudioClipを設定して "Play" ボタンを押下すると再生 "Stop" を押下すると停止