OmniAICreator/Qiita-1.07M huggingface dataset:
Rubyのグローバル変数をトレースする

`Kernel#trace_var` と `Kernel#caller_locations` を組み合わせることで出来ます。

```rb:trace_var.rb
trace_var(:$v) do |val|
  bl = caller_locations.first
  p [bl.path, bl.lineno, val]
end

a = 3
$v = 1
b = 2
$v = "foo"
```

実行

```
$ ruby trace_var.rb 
["trace_var.rb", 7, 1]
["trace_var.rb", 9, "foo"]
```


## 参考サイト

- [module function Kernel.#trace_var (Ruby 2.4.0)](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/trace_var.html)
- [module function Kernel.#caller_locations (Ruby 2.4.0)](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/caller_locations.html)
awk > csv ファイルの特定の列のユニークな数値をリスト化する > awk -F "," '{print $2}' dipoles_170404 | sort -n | uniq

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 14.04 LTS desktop amd64
TensorFlow v0.11
cuDNN v5.1 for Linux
CUDA v8.0
Python 2.7.6
IPython 5.1.0 -- An enhanced Interactive Python.
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
GNU bash, version 4.3.8(1)-release (x86_64-pc-linux-gnu)
gnuplot 4.6 patchlevel 4
```

```
$ head dipoles_170404 
-0.209440,-1.466077,-5.235988
0.209440,-1.466077,-5.235988
-1.047198,-1.047198,-5.235988
-0.628319,-1.047198,-5.235988
-0.209440,-1.047198,-5.235988
0.209440,-1.047198,-5.235988
0.628319,-1.047198,-5.235988
1.047198,-1.047198,-5.235988
-1.047198,-0.628319,-5.235988
-0.628319,-0.628319,-5.235988
```

csvファイルの特定の列（上記の場合１から３列のいずれか）のユニークな数値をリスト化する。
例として２列目の場合。

```
$ awk -F "," '{print $2}' dipoles_170404 | sort -n | uniq
-5.235988
-4.817109
-4.398230
-3.979351
-3.560472
-3.141593
-2.722714
-2.303835
-1.884956
-1.466077
-1.047198
-0.628319
-0.209440
0.209440
0.628319
1.047198
1.466077
1.884956
2.303835
2.722714
3.141593
3.560472
3.979351
4.398230
4.817109
5.235988
```
gnuplot > 読込みファイルのセパレータをカンマにする > set datafile separator ","

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 14.04 LTS desktop amd64
TensorFlow v0.11
cuDNN v5.1 for Linux
CUDA v8.0
Python 2.7.6
IPython 5.1.0 -- An enhanced Interactive Python.
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
GNU bash, version 4.3.8(1)-release (x86_64-pc-linux-gnu)
gnuplot 4.6 patchlevel 4
```

gnuplotではデフォルトではスペース区切りのファイルを読込むようだ。
カンマ区切りのファイルを読込みたい。

```
$ head dipoles_170404 
-0.209440,-1.466077,-5.235988
0.209440,-1.466077,-5.235988
-1.047198,-1.047198,-5.235988
-0.628319,-1.047198,-5.235988
-0.209440,-1.047198,-5.235988
0.209440,-1.047198,-5.235988
0.628319,-1.047198,-5.235988
1.047198,-1.047198,-5.235988
-1.047198,-0.628319,-5.235988
-0.628319,-0.628319,-5.235988
```

参考　http://gnuplot.sourceforge.net/docs_4.2/node173.html


gnuplot> set datafile separator ","
gnuplot> splot "dipoles_170404"

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/52a593ec-6b87-86cb-97da-c9dd3a02b907.png)
gnuplot > 視点を変更して3D座標を表示する > set view 30,0,1,1 / splot "dipoles_170404"

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 14.04 LTS desktop amd64
TensorFlow v0.11
cuDNN v5.1 for Linux
CUDA v8.0
Python 2.7.6
IPython 5.1.0 -- An enhanced Interactive Python.
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
GNU bash, version 4.3.8(1)-release (x86_64-pc-linux-gnu)
gnuplot 4.6 patchlevel 4
```

3次元のデータ(粒子のDipoleの位置座標)を視点を変えながら表示する。

Ubuntuでは以下を参考にgnuplotのエラー回避をしました。
[Gnuplot で Terminal type set to 'unknown' と出力されてグラフが表示されないときは](http://qiita.com/kazoo04/items/c64d9f72166855b3107e)
情報感謝です。

読込みファイル: dipoles_170404

```
$ head dipoles_170404 
-0.209440 -1.466077 -5.235988
0.209440 -1.466077 -5.235988
-1.047198 -1.047198 -5.235988
-0.628319 -1.047198 -5.235988
-0.209440 -1.047198 -5.235988
0.209440 -1.047198 -5.235988
0.628319 -1.047198 -5.235988
1.047198 -1.047198 -5.235988
-1.047198 -0.628319 -5.235988
-0.628319 -0.628319 -5.235988
```

参考 [視点の変更](http://dsl4.eee.u-ryukyu.ac.jp/DOCS/gnuplot/node128.html)

### set view 0,0,1,1

gnuplot> set view 0,0,1,1
gnuplot> splot "dipoles_170404"

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/d4a7aa9c-add4-93e4-cc8d-152259b3741c.png)

### set view 30,0,1,1

gnuplot> set view 30,0,1,1
gnuplot> splot "dipoles_170404"

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/dbc51f2e-e06d-110c-660d-e232d25cdbf2.png)

### set view 60,0,1,1

gnuplot> set view 60,0,1,1
gnuplot> splot "dipoles_170404"

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/fa0071df-b042-96f0-449e-799cd84278ec.png)

### set view 90,0,1,1

gnuplot> set view 90,0,1,1
gnuplot> splot "dipoles_170404"

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/17c0039b-8633-b077-75c0-47255f7f6c85.png)

本来は球形なのに、上半分のDipoleの座標が取れていない。
技術英語 > When you'[re about to] write some Python code, ... / on the verge of

@ Introducing Python: Modern Computing in Simple Packages by Bill Lubanovic
(No. 3110 / 12833)

> When you' **re about to** write some Python code, ...

https://www.merriam-webster.com/dictionary/about
> on the verge of —usually used with be and a following infinitive 
例: is about to join the army

<hr>
上記で見かけた
on the verge of

http://eow.alc.co.jp/search?q=on+the+verge+of
>on the verge of a major breakthrough
>〔主語の〕大きな進展［発見］が直前に迫って
REACT ROUTERを使ってみる

[REACT ROUTER](https://reacttraining.com/react-router/)便利。バージョンが変わるごとにかなり使い方が変わるらしい。[ここ](https://reacttraining.com/react-router/web/guides/quick-start)に詳しいドキュメントがある。使い方を試してみます。

## 準備
### create-react-appでプロジェクトをつくります。

```
$ create-react-app route-test
```

### react-router-domをインストールします。

react-router-domのバージョンは4.0.0だった。

```
$ yarn add react-router-dom
```

### 開発サーバ立ち上げます。

```
$ yarn start
```

## 試してみる

```src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import './index.css';

const Home = () => (
    <div>
        <h2>Home</h2>
    </div>
)

const About = () => (
    <div>
        <h2>About</h2>
    </div>
)

const Contact = () => (
    <div>
        <h2>Contact</h2>
    </div>
)

const Child = ({ match }) => (
    <div>
        <p>{match.params.id}です</p>
    </div>
)

const App = () => (
    <div>
        <Nav />
        <Router>
            <div style={{padding: '10px'}}>
                <p>
                    <Link to="/">Home</Link>&nbsp;
                    <Link to="/about">About</Link>&nbsp;
                    <Link to="/contact">Contact</Link>&nbsp;
                </p>

                <hr />

                <Route exact path="/" component={Home}/>
                <Route path="/about" component={About}/>
                <Route path="/contact" component={Contact}/>

                <hr />

                <Route exact path="/" render={() => (
                    <p>ホームページにようこそ！</p>
                )} />
                <Route path="/:id" component={Child}/>
            </div>
        </Router>
        <Footer />
    </div>
)

const Nav = () => (
    <div className="Nav" style={{ background: '#6cf', padding: '20px 10px' }}>
        Navbar
    </div>
)

const Footer = () => (
    <div className="footer" style={{textAlign: 'center'}}>
        <hr />
        Footer
    </div>
)

ReactDOM.render(
    <App />,
    document.getElementById('root')
);

```

## スクリーンショット

![screen.png](https://qiita-image-store.s3.amazonaws.com/0/147049/e556fb0e-189a-2adf-12b9-66d8900d184c.png)



## わかったこと

- Routerの中は1つのタグしか入れてはいけない
- Linkでリンクが作れて、勝手にブラウザの履歴に登録される
- Routeは現在位置がpathとマッチした場合のみ、コンポーネントを表示できる
- Routeにexactをつけると、設定しているpathが完全一致の場合のみマッチしたことになる
- Routeのpathに:（コロン）をつけると、URLパラメータとして使える。match.params.hogeでURLパラメタの内容を取得できる。
PHPで特定のディレクトリ内のファイルを取得する方法

写真を複数枚表示したい時に、
DBに保存する程の枚数じゃないけど、一つ一つ表示するコードを書くと面倒だったので、
写真だけが入ったimageフォルダから写真のファイル名を取得して配列にする関数を作った。

```php
function get_file_name($dir){
// ディレクトリの存在確認&ハンドルの取得
    if(is_dir($dir) && $handle = opendir($dir)){
    
        $files = array();
        // ループ処理(ディレクトリを読み込んでエントリがfalseでない間)
        while(($file = readdir($handle)) !== false){
            // ファイルタイプがfileの場合のみ処理する(ディレクトリとかでない場合)
            if(filetype($path = $dir.$file) == "file"){
                array_push($files,$path);
            }
        }
        return $files;
    }
}
```

(参考)
コード：https://syncer.jp/php-how-to-get-directory-file-list
opendir()：http://php.net/manual/ja/function.opendir.php
readdir()：http://php.net/manual/ja/function.readdir.php
filetype()：http://php.net/manual/ja/function.filetype.php
array_push()：http://php.net/manual/ja/function.array-push.php
is_dir()：http://php.net/manual/ja/function.is-dir.php
yarnを使うことにした

なんか人気らしく、色々なところに出てくるし、[ここ](http://qiita.com/0829/items/ec5271c06f8ff0633dd3)によるとnode-modulesのサイズも小さくなったりするらしいので、[yarn](https://yarnpkg.com/lang/en/)を使うことにしました。インストールも爆速らしい。

package.jsonに対応していて、プロジェクト単位のパッケージの管理がnpmと同じようにできて、npmより効率的らしい。npm i -gみたいなグローバルインストールができるやつじゃないみたい。yarn iとやるとエラーになったから短縮文字みたいなのもないらしい。


# インストール

```
$ npm i -g yarn
```

# yarnのコマンド

## yarnのバージョン確認

```
$ yarn --version
```

## npm initの代わり

```
$ yarn init
```

## npm installの代わり

```
$ yarn
または
$ yarn install
```

## npm updateの代わり
 
 ```
 $ yarn upgrade package_name
 ```

## npm removeの代わり

 ```
 $ yarn remove package_name
 ```

## npm install -D package_nameの代わり

```
$ yarn add package_name
```

## npm runの代わり

[ここ](http://qiita.com/y13i/items/27d39edac23b7a867935)によるとyarn runもあるらしくて、npm runとちょっと違って便利らしい。

```
$ yarn run
```
このＷｉｎｄｏｗｓのコマンドラインにイジェクトを

Ｗｉｎｄｏｗｓのコマンドラインには、
イジェクトやＵＳＢメモリの取り外しがありません。

書き込みの終わった媒体の取り出しに１工程手作業が必要です。

Rundll や devcon 等での取り外しが挙がっていますが
このコマンドがあまり知られていないようなので紹介します。

Sysinternals の SYNC というコマンドです。

一応、Microsoft 純正ツールなので
外部のフリーソフトを使うよりは敷居が低いと思います。

ただ、敷居が低いとはいえ英語バージョンのみ、さらに
Sysinternals の コマンドは、最初に使用許諾を求められるので
使い辛いところがあるのも事実です。

そこで、バッチ化により簡易指定とメッセージを日本語で出すようにしました。

Eject d で d ドライブのイジェクトや取り外しが出来ます。

Sync をダウンロードして、パスの通ったところに
exe とバッチを同じフォルダに置いて下さい。
使用ＯＳのビット数に合わせて
　32　→　sync.exe　をそのままに
　64　→　sync64.exe　を　sync.exe にリネームするかバッチを変更
して使います。

Windows PE でも使えます。
ただし、Windows PE には、sort.exe が搭載されていませんので
バッチと一緒に作成した PE のビット数に合わせた
sort.exe も同じフォルダに置いて下さい。

```
Eject.cmd
@echo off
setlocal enabledelayedexpansion

REG ADD "HKCU\SOFTWARE\Sysinternals\Sync" /f /v "EulaAccepted" /t REG_DWORD /d "1" > nul

set        Drive=%~1
set Drive=!Drive:~0,1!

set TargetDrive=NotFind
for %%D in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ) do (
 @if      exist %%D: if /i "%%D"=="!Drive!" set TargetDrive=Find
)

echo;

if     "!TargetDrive!"=="NotFind"                echo;!Drive! ドライブが在りません                     &  goto :eof

for /f "delims=" %%0 in ('@sync -nobanner -e          !Drive! ^| sort /r') do (
 echo;%%0 | find /i "Flushing: !Drive!" > nul && echo;!Drive! ドライブが取り外されました　　　　　　　 && goto :eof
 echo;%%0 | find /i "There is no media" > nul && echo;!Drive! ドライブのデバイスの準備ができていません && goto :eof
)
```
Elixirにしたい理由


![IMG_7332.JPG](https://qiita-image-store.s3.amazonaws.com/0/16626/a8453dd6-cbff-056b-fddb-231f42bf0238.jpeg)


(1) Erlang/OTPが必要だから
(2) Elixirにしたいから
(3) Phoenixにしたいから


(1)なら是非検討すべき。
(2)ならRubyやGoでもいいのかもしれない。
(3)ならRailsのほうがきっといい。



# Erlang/OTPのいいところ
- (ちゃんと適切に使えば)落ちないサーバをつくれる
- 並行処理で性能を出しやすい(マルチコア、サーバ分散)
- バイナリプロトコルで24時間365日動き続ける超高性能ネットワークサーバが得意


# Erlang/OTPのつらいところ
- 文法
- OTPのプロセス設計という特殊技術が必要
- テキスト処理がやりにくい


# Elixirのつらいところ
- 深追いするとErlangにたどり着く
- Erlangのライブラリもよく使うことになる
- Rubyに似てるとはいえ、まったく違う言語


# Elixir,Erlang/OTPにしないほうがいい理由
- 単一のErlangプロセスの性能はよくない(C++やGoがよい)
- 作りたいものはWebアプリだ(Railsはなんでもそろってる)
- Erlang/OTPがこわい


# Elixirを検討してもいいかもしれない理由
- Erlang/OTPを使う大きなコストを払ってでも落ちない超高性能システムを構築したいがErlangは嫌だ
- Erlang/OTPの世界をちょっとのぞいてみるきっかけとして
- OTPの強みについて理解した上でErlangを避け気味に高性能なネットワークサーバを書きたい
原始的なファイル上書きコピーでデプロイせざるを得ない環境でのバックアップスクリプト

デプロイスクリプトもなんもなくて、上書きコピーでデプロイせざるをえない環境で使ってるスクリプトです。

releaseディレクトリ下に上書きするリリースファイルを配置しておいて実行します。
実行するとDEPLOY_PATHにあるファイルでリリースファイルで上書きされる予定のファイルが backupディレクトリにコピーされます。

releaseにあるファイルと同名のファイルをコピーしようとするので新規追加ファイルまでデプロイ先からコピーしようして、ファイル見つからないってエラーでますが、そこはきにしないで^^;



```
#!/bin/sh

# リリースファイルのフォルダ名
DIRPATH="release"
DEPLOY_PATH="/var/www/html"
# バックアップ用のフォルダをリリースファイルと同じフォルダ構成で作成するためにコピー
cp -rf $DIRPATH backup
find backup -type f | while read FILE
do
  rm ${FILE}
done


find ${DIRPATH} -type f | while read FILE
do
   # リリースするファイルのファイルパス取得
   FILE_PATH=`echo ${FILE} | sed -e "s/${DIRPATH}//"`
   #   echo ${FILE_PATH}
   # backupへコピー
   cp -f ${DEPLOY_PATH}/${FILE_PATH} ./backup/${FILE_PATH}
done
```
同一インスタンスでない List を property でまとめて数える

## 概要

例えば、こういうスキルの class があったとして、

```Skill.cs
public class Skill
{
    public int Code { get; private set; }
    public int Level { get; private set; }

    public Skill(int code, int level)
    {
        Code = code;
        Level = level;
    }
}
```

同じスキル・レベルでも別インスタンスである可能性のある `List<Skill>` から、同じスキル・レベルをまとめて数える `IDictionary<Skill, int> SkillCountDictionary(List<Skill>)` を実装します。

## テスト

```SkillTest.cs

public class SkillTest
{

    [Test]
    public void SkillCountDictionary()
    {
        CollectionAssert.AreEquivalent(
            Skill.SkillCountDictionary(Skills()),
            Expect()
        );
    }

    private List<Skill> Skills()
    {
        var skills = new List<Skill>();
        skills.Add(new Skill(1, 1));
        skills.Add(new Skill(1, 1));
        skills.Add(new Skill(2, 1));
        skills.Add(new Skill(2, 2));
        skills.Add(new Skill(2, 2));
        skills.Add(new Skill(2, 2));
        return skills;
    }

    private Dictionary<Skill, int> Expect()
    {
        return new Dictionary<Skill, int>
        {
            {new Skill(1, 1), 2},
            {new Skill(2, 1), 1},
            {new Skill(2, 2), 3}
        };
    }
}

```

## foreach で Dictionary に入れていく実装

```Skill.cs

    public static IDictionary<Skill, int> SkillCountDictionary(List<Skill> skills)
    {
        var testCountDictionary = new Dictionary<Skill, int>();
        foreach (var skill in skills)
        {
            // csharp> dict[0]++; => System.Collections.Generic.KeyNotFoundException
            if (!testCountDictionary.ContainsKey(skill))
            {

                testCountDictionary[skill] = 0;
            }
            testCountDictionary[skill]++;
        }
        return testCountDictionary;
    }

```

当然通りません。
インスタンスが違うので、それぞれ別の Key になってしまいます。

### IEquatable を実装する

```Skill.cs
public class Skill : IEquatable<Skill>
{

    public override int GetHashCode()
    {
        // Tuple の実装があればこっちの方がイケてる気がする
        // return Tuple.Create(Code, Level).GetHashCode();
        return Code.GetHashCode() ^ Level.GetHashCode();
    }

    bool IEquatable<Skill>.Equals(Skill other)
    {
        if (other == null)
        {
            return false;
        }

        return Code == other.Code && Level == other.Level;
    }
```

通りました。けど、長い。

## LINQ GroupBy を使う実装

```Skill.cs
    public static IDictionary<Skill, int> SkillCountDictinary(List<Skill> skills)
    {
        return skills.GroupBy(s => new { s.Code, s.Level })
            .ToDictionary(g => g.First(), g => g.Count());
    }
```

1行で書けました。

## まとめ

* GroupBy が便利でした。
* `IEquatable<T>` は覚えておくといいかもしれない。
    * もうちょっと一般的な場面でも役に立ちそう。
    * Tuple が欲しくなる。
peco, jq, aws-cliでEC2にSSHするワンライナー


色々あって [こちら](https://github.com/a2ikm/ec2list)や[こちら](https://github.com/toritori0318/p5-Yogafire)や[こちら](https://github.com/facebookarchive/ec2-ssh)が使えなかったので、
あったやつだけで頑張ったあれのメモ

# 前提

`aws configure --profile hoge`
などを使って適宜Profileを設定しておくこと
(output formatはjsonになるように)

jq, pecoがいい感じに実行できること

# やること

こんな感じで頑張る

```
aws ec2 describe-instances --profile hogehoge | jq ".Reservations[].Instances[] | select(has(\"PublicIpAddress\")) | {InstanceId, PublicIpAddress, InstanceName: (.Tags[] | select(.Key==\"Name\").Value)}" | jq -r 'to_entries | [.[].value] | @csv' | peco | cut -f 3 -d , | xargs -o -n 1 ssh -i ~/keys/hogehoge.pem -l ec2-user
```

# やってること

## 1つめ

`aws ec2 describe-instances --profile hogehoge`

インスタンス一覧をとってくる

## 2つめ

`jq ".Reservations[].Instances[] | select(has(\"PublicIpAddress\")) | {InstanceId, PublicIpAddress, InstanceName: (.Tags[] | select(.Key==\"Name\").Value)}"`

インスタンス情報が返ってくる所で、 `PublicIpAddress` を持つInstanceだけを拾ってきて、以下のようなJSONに整形する

**ここの`select(has(\"PublicIpAddress\"))`を調整したり、すると、他のパラメータを使うよう変更したりできる**

```
{
   "InstanceId": <Instance1のid>,
   "PublicIpAddress": <Instance1のPublicIP>,
   "InstanceName": <Instance1のNameタグの値>
},
{
   "InstanceId": <Instance2のid>,
   "PublicIpAddress": <Instance2のPublicIP>,
   "InstanceName": <Instance2のNameタグの値>
},
...
```

## 3つめ

`jq -r 'to_entries | [.[].value] | @csv'`

整形されたJSONを下記のようなCSVに変換する

```
<Instance1のid>,<Instance1のNameタグの値>,<Instance1のPublicIP>
<Instance2のid>,<Instance2のNameタグの値>,<Instance2のPublicIP>
...
```

2つめで指定した順番どおりになってないけど、
どうやら `to_entries` をする際にパラメータ名でソートされてしまう模様

## 4つめ

`peco`

pecoで検索できるように渡してあげる

## 5つめ

`cut -f 3 -d ,`

3番目のフィールドにPublicIPがあるので、
デリミタを`,`で指定して3番目のフィールドの値を拾ってくる

## 6つめ

`xargs -o -n 1 ssh -i ~/keys/hogehoge.pem -l ec2-user`

xargsで値を拾ってsshしてあげる

xargs経由でsshする時は、`-o`オプションを指定して標準入力を再度開いてあげないと上手く動かないっぽかった。
`-n 1`オプションは、1個しか動かすつもりがないのでこんな感じで

おつかれやまでした
Google Analytics のレポートを定期的にメールで届ける設定

## Google Analytics のレポートを作成する

まずは定期的に届けるレポートを作成する。
どのサイトでも使える汎用的なマイレポートを作成しておくと楽ちん。

レポート画面で「共有」から「テンプレートのリンクを共有」を選択するとURLが表示されるので、それをコピってまとめておきます。

![定期レポート _共有.png](https://qiita-image-store.s3.amazonaws.com/0/9064/4e26bdc1-907f-d790-d940-1ba3ca27c421.png)

新しいサイトを構築したらそのURLをクリックすれば作ったレポートがすぐに反映されます。
以下は僕が作ったレポートです。

* [定期レポート 1](https://analytics.google.com/analytics/web/template?uid=tcS619xcR_yeb7EMXxajjA)

* [定期レポート 2](https://analytics.google.com/analytics/web/template?uid=CVSFAHcVRnWXwOrdiCErcg)

* [SEOレポート](https://analytics.google.com/analytics/web/template?uid=-lgJwRYJQL23EMxBy5SGMw)

* [パフォーマンス・レポート](https://analytics.google.com/analytics/web/template?uid=W1Ow5mLKQ7irr5nuE-OhMw)

* [閲覧環境レポート](https://analytics.google.com/analytics/web/template?uid=X34TokeGSSKoGsbsDFIx_A)

* [時間軸レポート](https://analytics.google.com/analytics/web/template?uid=Zav6Q840T_KRKSI-WSF0-w)

* [問題点抽出レポート](https://analytics.google.com/analytics/web/template?uid=weFj3fTCRY-T92FG25lAsQ)

* [月別レポート](https://analytics.google.com/analytics/web/template?uid=R0sE13uKRECbCRzsyPCjuA)

[Googleギャラリー](https://www.google.com/analytics/gallery/#posts/search/%3F_.start%3D0%26_.sort%3DUSES%26_.type%3DDASHBOARD/)にいけば世界中の人がレポートを共有しています。


## Google Analytics のレポートを定期送信する設定

レポートの画面から「メール」を選択して頻度や送信先を設定するだけです。

![定期レポート 1_メールボタン.png](https://qiita-image-store.s3.amazonaws.com/0/9064/8599356a-69ba-dcb8-2279-a5b55e8930a1.png)

![定期レポート-1_メール送信設定.png](https://qiita-image-store.s3.amazonaws.com/0/9064/2fcfbea1-3bdc-abc5-e43b-b478b7ff04f4.png)
Spark on YARN のアーキテクチャ

[前回](http://qiita.com/kojish/items/ad16e557520b2b562cb4)も触れましたが、Spark のクラスタマネージャには、Standalone とMesos とYARN が存在します。ここではYARN 上でのSpark アプリケーションがどのように実行されるかを、HDInsight Spark の物理環境（リンクは[こちら](http://qiita.com/kojish/items/5b6bc43d24835d1af434)）に合わせて説明してみたいと思います。その前にまずYARN について軽く触れたいと思います。
##YARNとは
MapReduce v1 時代は、専用のJobTracker やTaskTracker と言われるプロセスでMRのジョブ制御やスケジューリングやモニタリングを行っていました。ただスケーリングに問題があり、MapReduce v2からそれを解決する目的で、YARNというMapReduce 以外でも汎用的に使えるプラットフォームが開発されました。YARNは汎用的に使用できるため、MapReduce以外にもSpark やStorm といったアプリケーションでも同じように利用することが可能です。Hadoop の分散環境上で動くOS みたいなものと思っていただければと思います。またYARNの主な構成としては以下のものが挙げられます。
###Resource Manager
クラスタ上で１つだけ存在します。名前の通り、Spark アプリケーションに対して、CPUコアやメモリなどのリソースの割り当て・管理を行うものです。HDInsight Spark の場合、ヘッドノードで動作しています。
###Node Manager
ワーカーノード内のコンテナを実行します。YARN の場合、Spark アプリケーションはコンテナ（下記）という形で抽象化されており、Node Manager により制御されています。
###ApplicationMaster
ApplicationMaster は、動かすアプリケーション毎（MapReduce やSpark など）につき、それぞれ専用のものが使用されることになっており、汎用的なYARN の処理の中では、アプリケーション固有の動作を提供しているサービスになります。
###Container
CPU、メモリ、Diskなどのリソースをバンドルしたロジカルな箱のようなものになります。Spark の場合、ワーカーノードの中でExecutor として動作します。

##Spark のデプロイのモードは２種類

クラスタマネージャの種類に関係なく、Spark アプリケーションの実行には、Clientモードと Cluster モードの2つがあります。

###Client モード

Driver Program がクラスタの外部で生成されるモードです。下記の例ではDriver Program がヘッドノードで動作している場合の図となります。例えばspark-submit で起動する時は、spark-submit と同じプロセス内にDriver Program が存在することになります。Client モードの場合、Driver Program がSpark アプリケーションの結果を受け取ることができるため、spark-submit の結果をコンソールで確認することが可能となっています。spark-shell は都度結果を知る必要があるため、Client モードになります。

<img width="514" alt="clientmode.png" src="https://qiita-image-store.s3.amazonaws.com/0/168934/edd51098-532e-3951-2de0-4b47269a1f36.png">

1. クライアントプロセスがアプリケーションをResource Manager にsubmit する。
2. Resource Manager がNode Manager に対してApplicationMaster 用のContainer の割り当てを依頼する。
3. Node Manager がApplicationMaster のためのContainer を起動しApplicationMasterが生成される。
4. ApplicationMaster がResouce Manager にアプリケーション起動のための、リソースの取得を要求する。
5. リソースが取得できた場合、ApplicationMaster がNode Manager にコンテナの中のExecutor を起動するよう依頼します。
6. Node Manager がExecutor を起動し、ワーカーノードにて実際の処理が開始されます。

注）点線は、Driver Program は直接Executor と話してステータス確認を行っています。

###Cluster モード
Driver Program はワーカーノードのApplicationMaster の中で起動されます。Client モードと異なりアプリケーションの出力が標準出力に出ないので、 Cluster Manager が提供しているWEB のUI などで確認することになります。またクライアントがワーカーノードから非常に離れている場合は、レイテンシを小さくするためにCluster モードが有効になることがあります。（ちなみに処理の流れは、ほぼClient モードと同じため割愛します）

<img width="464" alt="clustermode.png" src="https://qiita-image-store.s3.amazonaws.com/0/168934/79381d99-eb0c-bc10-0112-09e775dbbc95.png">

このあたりの動作は、本家Spark のWEB サイトを見てもほとんどよく分からないのですが、図式化してみることで、クラスタマネージャの動作が非常に大きな役割を果たしていることが良く分かるかと思います。
VSCodeでステータスバーの色を変える

デフォルトのステータスバーの色、どぎつい青で目がやられます。
![image](https://qiita-image-store.s3.amazonaws.com/0/27326/b57868aa-f288-c65f-0290-72c74bd59354.png)

じゃあテーマを変えますか、となるのですが、どのテーマでも同じ色！
どうもテーマでは変えられいないみたいです。
**(追記： v1.12から変更可能になったようです:tada:)**

ではどうするか。設定ファイルにこうじゃ。

```
{
  "editor.tabSize": 2,
  ：
  // 以下を追加
  "workbench.colorCustomizations": {
      "statusBar.background": "#111111",
      "statusBar.noFolderBackground": "#111111",
      "statusBar.debuggingBackground": "#111111",
  }
}
```

![image](https://qiita-image-store.s3.amazonaws.com/0/27326/d1d47d01-7f33-1bb8-1010-61d6772326bd.png)

その他の場所も細かくカスタマイズできるようになったようです。詳細は以下参照
https://code.visualstudio.com/docs/getstarted/theme-color-reference

ちなみにv1.12以前ではinsiders版で以下の通りの対応が必要でした。

```
{
  "editor.tabSize": 2,
  ：
  // 以下を追加
  "workbench.experimental.colorCustomizations": {
    "statusBarBackground": "#111111",
    "statusBarNoFolderBackground": "#111111",
    "statusBarDebuggingBackground": "#111111"
  }
}
```
【初心者投稿-16】サイト作りに奮闘中。

#昨日までのおさらい
晴れて、progateのHTML&CSS上級編が終わり、エンジニアとしてのスタート地点に立った…と思っていた。(笑)

本日に続く…

#THE理解していた気
これ、一番良くないやつですね…。
なんとな〜く簡単なところだけは覚えているけど、いざ一から作っていこうと思ったら、手が止まる。

とりあえずProgateの完成ページのhtmlとcssのコードを拝借して、編集から初めてみたけど、これで成長するのか…！

1から自分で書いて行った方がいいのか？
皆さんは、ある程度基礎を勉強したあとどうしましたか？？？

#学習の記録
* サイト作り：1日目
* 今日の勉強時間：1時間15分
* 総学習時間：16時間15分
* 今日学んだこと：総学習時間15時間って…笑　全然勉強できていないことに気づく。笑(笑えない。)これは、まだまだ伸び代があると私は捉えます！

※Progateは、13日間でHTML&CSSを終え、一旦休み
Spark のアーキテクチャ概要

Spark アプリケーションの実行の仕組みについて、Apache Spark のサイトを読んでみてもどうもよくわからないので、自分なりにまとめてみました。まずは、概念的ですがSpark のコンポーネントについてです。
##Spark のコンポーネント概要
<img width="334" alt="spark-component.png" src="https://qiita-image-store.s3.amazonaws.com/0/168934/faec74bc-b89c-8eb8-271a-02909a745e6c.png">

これは、Apache Spark のサイトでも書かれている内容 (Cluster Mode Overview) とほとんど同じで、概念的な各コンポーネントのつながりを書いています。また各コンポーネントの概要をまとめると、
###Driver Program
Spark アプリケーションの実行管理や制御を行うもので、main メソッドを含むプロセスとなります。またドライバはSpark アプリケーション毎に１つ存在し、アプリケーションの環境（SparkContext）を作る役割を担っています。
###Cluster Manager
Spark アプリケーションをクラスタ上で実行するためには、クラスタのリソース（メモリやCPU など）の確保を行ったり、スケジューリング管理を行う必要があります。それを行うのがCluster Manager の主な役目となります。ややこしいことにCluster Manager は以下の３つがあり、その内のどれかを使用することになっています。
- Standalone: Spark に標準でついているシンプルなもの
- YARN: Hadoop MapReduce や HBase やStorm など多様な分散アプリケーションを実行するために作られた、汎用性を持ったクラスターマネージャです。
- Mesos: （触ったことが無いのですが）YARNと同じく汎用的に利用できるクラスタマネージャです。
###ワーカーノード
Spark アプリケーションのコードを実行するノードです。
###Executor
JVM のプロセスで、ドライバから依頼されたTask を実行します。
###Task
Executor 内で実際の処理を行うスレッドです。
###Sparkアプリケーション
Driver Program とExecutor を含むクラスタ上で実行されるユーザプログラムです。

のようになります。

クラスタマネージャにより、クラスタの管理やアプリ制御のやり方が少しづつ変わってきますが、上記の基本的概念や、大筋の動きは同じとなるかと思います。

また、クラスタマネージャが実行時に大きな役割を果たしていると思いますので、次回はYARN 上でのSpark の動作について調べてみて書いてみようと思います。
muninのグラフ画像を定期的にメールで届ける

Muninのグラフを定期レポート用にメール送信する方法。

### mutt をインストール

複数ファイルを添付する場合はmuttが良さげ。

```bash
yum -y install mutt
```

### グラフを添付してメールするbashスクリプト作成

```bash:/var/www/cron/munin_graph_send.bash
#!/bin/bash
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 
# 	Muninグラフをメール送信するスクリプト Ver.0.1
# 
# 	Author Digichro co. Yoshinori Sakai
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 
# ─────────────────────────
# ■ 初期設定
# ─────────────────────────

# Muninのグラフ格納ディレクトリ
target_host1_dir=/var/www/html/munin/WEB/target_host1
target_host2_dir=/var/www/html/munin/WEB/target_host2
target_host3_dir=/var/www/html/munin/WEB/target_host3

# レポート用グラフ画像
load_avg=load-month.png
cpu=cpu-month.png
memory=memory-month.png
disk=df-month.png
ipconntrack=fw_forwarded_local-month.png
netstat=netstat-month.png
traffic=if_eth0-month.png

# メール設定
subject='定期レポート用グラフ'
mailbody=`date +%Y年%m月レポート -d '1 days ago'`
mailaddr=myself@example.com


# ─────────────────────────
# ■ メール送信処理
# ─────────────────────────

echo "${mailbody} target_host1" | mutt -s ${subject} ${mailaddr} \
		-a ${target_host1_dir}/${load_avg} \
		-a ${target_host1_dir}/${cpu} \
		-a ${target_host1_dir}/${memory} \
		-a ${target_host1_dir}/${disk} \
		-a ${target_host1_dir}/${ipconntrack} \
		-a ${target_host1_dir}/${netstat} \
		-a ${target_host1_dir}/${traffic} ;

echo "${mailbody} target_host2" | mutt -s ${subject} ${mailaddr} \
		-a ${target_host2_dir}/${load_avg} \
		-a ${target_host2_dir}/${cpu} \
		-a ${target_host2_dir}/${memory} \
		-a ${target_host2_dir}/${disk} \
		-a ${target_host2_dir}/${ipconntrack} \
		-a ${target_host2_dir}/${netstat} \
		-a ${target_host2_dir}/${traffic} ;

echo "${mailbody} target_host3" | mutt -s ${subject} ${mailaddr} \
		-a ${target_host3_dir}/${load_avg} \
		-a ${target_host3_dir}/${cpu} \
		-a ${target_host3_dir}/${memory} \
		-a ${target_host3_dir}/${disk} \
		-a ${target_host3_dir}/${ipconntrack} \
		-a ${target_host3_dir}/${netstat} \
		-a ${target_host3_dir}/${traffic} ;
```

設置してパーミッションを707にする。

### CRONに登録

毎月1日（4:10）にメール送信されるようタスクに登録。

```bash:crontab
10 4 1 * * export LANG=ja_JP.UTF-8; /var/www/cron/munin_graph_send.bash #月次レポート
```

※export LANG=ja_JP.UTF-8 がないとメールのタイトルが文字化けします。
perl怖い

<div class='alert alert-warning'><h4>警告</h4>
この本文は個人の感想しか含まれておりません。
</div>

仕事の都合上よくrubyでスクリプトを書く,だがそれ以上にレガシーなツールのperlスクリプトを良く読む。
個人的にperlは**ものすごく**嫌いな言語で嫌い過ぎて今まで勉強すら拒んできた。
なんで嫌いなのかは明らかで、直感的に読めないからだ。初見だとshiftってなんだ、bless?eval?というかこの関数の引数どうなってるの?

とかまぁいろいろ。

とはいえ、レガシーなツールをたくさん持っている今の部署でこの先生き残るにはperlを勉強しないとつらいので、個人的にperlの**気持ち悪い部分**にフォーカスしてここに書き残したい。
内容は初歩の初歩で自分のモチベーションや継続学習のためのかきのこしているため、あんまり役に立つ情報はないと先に記載しておく。

後**悪い**部分ではない、私が**気持ち悪い**と思った部分なのでという言い訳だけ先にしておきます。

## インスタンスメソッド
```pl
package Class1;

# コンストラクタ
sub new {
    my %self;
    my $class = shift;
    $self->{value} = 0;
    return bless $self, $class;
}
sub test1 {
    my $self = shift;
    print "hello world\n";
}

sub test2 {
    my $self = shift;
    print "good bye world\n";
}
1;
```
このクラスの定義の仕方も初見あまりよくわからなかったがそれはまぁいい。
見ての通りhello worldを出力するtest1,good bye worldを出力するtest2のインスタンス変数が定義されているClass1というpmファイルがある。
このインスタンスメソッドってこんな風に実行できるんだね。

```pl
use Class1;

sub test {
    my ($obj, $method) = @_;
    $obj->$method;
}
my $obj = Class1->new;

test($obj, 'test1');
test($obj, 'test2');
```

出力は

```
hello world
good bye world
```

個人的にこういう書き方ができちゃうと可読性が大変つらい感じになっちゃうような気がするのだけれどなれればそうでもないのだろうか?

Cの関数ポインタとかも同種の読みづらさを感じる。
割と使い道を思いつく分他の言語でもできそうな気がするけど、testしんどそうなのであんまりやりたくないなぁ…
HDInsight Spark の構成

Azure で提供しているHDInsight Spark は、現在のところ 1.5.2、1.6.2、1.6.3、2.0.2、2.1.0 (プレビュー) がリリースされています。各ノードは全てLinux（Ubuntu）の仮想VMが使われておりSparkのバージョンにより、Ubuntu のバージョンは少しづつ異なります。なお対応する仮想VM はこちらのリンクHDInsight の価格を参照いただきたいのですが、注意点としまして、

デプロイ後は仮想VMの種類を変更することができない。
コスト削減のためにAシリーズの低価格のものを使用すると、パフォーマンスが出ない恐れがあるので、ヘッドノード・ワーカーノード共にデフォルト以上の性能の仮想VMを推奨します。（ここでデフォルトとはポータルでデプロイ時にあらかじめセットされているVMタイプのことを指します）
ちなみにデプロイすると、以下のような物理構成で環境が構築されます。

<img width="375" alt="hdispark-struture.png" src="https://qiita-image-store.s3.amazonaws.com/0/168934/a3c9d9f2-eb7d-a379-b304-f6fb803375d8.png">

以下にそれぞれの部分について説明をすると、
## ヘッドノード
ヘッドノード（マスターノードとも言います）は、デフォルトで２重化されており、主にクラスタやSpark ジョブの管理・制御用のコンポーネントや、Jupyter のようなアプリケーションがインストールされています。それぞれのモジュールは様々にいろんな機能を提供しているので、ここでは詳細な説明を避けますが、主に以下のコンポーネントが含まれます。

- Resource Manager （YARN）
- NameNode（HDFS）
- Hive Metastore
- HiveServer2
- App Timeline Server
- History Server
- Ambari Metrics Collector / Metrics Monitor
- Thrift サーバ
- Jupyter
- Livy
- Oozie　など。

 ヘッドノードは２重化されているため、Resouce Manager やNameNode はActive/Stanby 構成を取っており冗長化しています。Hive Metastore と HiveServer2 は両方のノードでActive な状態で動作しています。またApp Timeline Server とHistory Server は両方のノードにインストールされていますが、Ambari Metrics Collector が動作している方のノードのみで動作するようになっています。

##ワーカーノード
ワーカーノードは実際にSpark ジョブが実際に動作する仮想VM なので、ジョブ実行に必要なものがインストールされており、ヘッドノードに比べると、以下のような必要最小限のコンポーネントのみが含まれます。

- NodeManager（YARN）
- DataNode（HDFS）
- Metrics Monitor（Ambari）
- Zookeeper

##Zookeeper 
Zookeeper は、分散環境での設定情報の集中管理や、リソースの競合を防止するための機構を提供したり、自動フェイルオーバーの提供などを行います。上述のResouce Manager（YARN）やNameNode（HDFS）のActive/Stanby 構成はZookeeperによるものです。ちなみにZookeeperには、A シリーズの仮想VM が使用されているのですが、VM タイプをデプロイ時やデプロイ後に変更することができません。またデプロイすると３台のZookeeperが構築されますが、台数を増やすことも現状サポートされておりません。ちなみにSpark のZookeeper は課金対象となっていないです。

##ゲートウェイノード
Azure ポータルから確認することはできませんが、2台のGateway ノードというものが裏で存在しています。HDInsight Spark をデプロイすると各ノードの仮想VM は仮想ネットワーク上に構成されるようになり、それぞれのノードの通信は仮想ネットワークを介して行われることになります。ただしユーザは直接ノードにアクセスすることができず、Gateway を介してノードへのアクセスが許可されています。外部からのアクセスはデフォルトではヘッドノードへのSSH とAmbari のWEB UI へのアクセスのみが許可されていますが、アクセス時のユーザ認証やリクエストのフォワーディングはGateway によって自動制御されています。Gateway は外からは見えないためユーザは一切管理を行う必要がありません。

##Azure Blob ストレージ
Blob ストレージは、HDInsight Spark のデフォルトストレージとして使用されています。IFとしてはHDFS ですが中身がBlob ストレージとなっています。そのため、SSH でノードにログインしてhadoop コマンドでストレージの中身にアクセスすることも可能となっています。普通のSpark のようにHDFS を構築することも可能ではありますが、Azure 上での取り扱いの良さを考慮して、Blob ストレージがデフォルトとして採用されていると思われ、開発時などはAzure Storage Explorer が利用できることから非常に重宝しています。

##エッジノード
最後にエッジノード（任意で追加可能）というものがあります。例えばHDInsight のクラスターに作業用のLinux VM や何がしかのアプリを動作させるためのノードを追加したいことがあるかと思います。個別にLinux の仮想VM を立てても良いのですが、エッジノードとしてVM を追加すると、デフォルトで Spark2 Client やYARN Client などのクライアントツールが事前にインストールされたVM をクラスタへ追加することが可能になります。詳細はHDInsight での空のエッジ ノードの使用を参照ください。なおエッジノードを追加すると、下記のようにポータルやAmbari（赤枠内）からもノードの情報が見えるようになります。

<img width="589" alt="hdinodes2.png" src="https://qiita-image-store.s3.amazonaws.com/0/168934/02e0dd86-c6a4-8800-7e17-598b19229f5b.png">
<img width="272" alt="hdi-portal-nodes.png" src="https://qiita-image-store.s3.amazonaws.com/0/168934/fc7958e9-547e-c873-947f-06dd0032a80f.png">
IPoEでmtuを1500に出来ないときの解決法 (付・IPv6トンネルのmtuを1460にする方法)

IPoEが開通して、やっとパケット損失無しの生活に突入しました。しかし、何故かmtuが1500にならないため調査。なお、OSはUbuntu前提となっています。

# MTU 1500をセットするものの
Network-ManagerでMTUを1500に設定して繋ぎ直し、ifconfig eth1でMTUが1500になっているのを確認しましたが、何故か大きなパケットが通りません。

```
$ sudo ping6 -M do -s 1407 -c1 ipv6.google.com
PING ipv6.google.com(kix05s02-in-x0e.1e100.net) 1407 data bytes
ping: local error: Message too long, mtu=1407

--- ipv6.google.com ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
```

MTU = 1406 (ping6で通るペイロードの限界) + 40 (IPv6ヘッダサイズ) + 8 (ICMPv6ヘッダサイズ) = 1454。何かがおかしいです。結論から言うと、```sysctl net.ipv6.conf.eth1.mtu``` が何故か1454になっていたので、```sudo sysctl net.ipv6.conf.eth1.mtu=1500```とすれば解決しました。原因は不明。

MTU変更後は、```sudo ip -6 route flush cache```でIPv6のMTUのキャッシュをクリアし、ping6で1500バイトのパケットが通るか確認します。

```
$ sudo ping6 -M do -s 1452 -c1 ipv6.google.com
PING ipv6.google.com(nrt13s48-in-x0e.1e100.net) 1452 data bytes
72 bytes from nrt13s48-in-x0e.1e100.net: icmp_seq=1 ttl=54 (truncated)

--- ipv6.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 5.393/5.393/5.393/0.000 ms

```

# IPv6トンネルのMTUを上げる
こちらの環境はDS-Liteであるため、DS-LiteのトンネルのMTUも上げときます。

DS-LiteのMTUは、1500 (IPv6のMTU) - 40 (IPv6ヘッダサイズ) = 1460 になるかと思いきや、[標準ではencapsulation limitとして8バイトが必要となるため、MTUは1452となるらしいです](http://www.spinics.net/lists/netdev/msg143874.html)。これを無効にするためには、```ip -6 tunnel add```時に```encaplimit none```を追加すれば良いようです。再度トンネルを追加しなおせば、自動的にMTUが上がります。

```
$ sudo sysctl net.ipv6.conf.ip6tnl1.mtu
net.ipv6.conf.ip6tnl1.mtu = 1460
```

その後、```sudo ip -4 route flush cache```でIPv4のMTUのキャッシュをクリアし、pingで1460バイトのパケットが通るか確認します。

```
$ ping  -M do -s 1432 -c1 www.google.com
PING www.google.com (216.58.197.196) 1432(1460) bytes of data.
72 bytes from nrt13s48-in-f4.1e100.net (216.58.197.196): icmp_seq=1 ttl=57 (truncated)

--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 5.824/5.824/5.824/0.000 ms

```

# 終わりに
やっぱり、定期的にnet.ipv6.conf.eth1.mtuが1454に戻ってしまいます。何が原因でしょうか? とりあえず、```while [ 1 ]; do  sysctl net.ipv6.conf.eth1.mtu=1500 > /dev/null; sleep 1 ; done``` を実行して回避しています。

**追記:** ```sudo /etc/init.d/network-manager restart```でNetwork Managerを再起動したら治ったように見えます。Network Managerは鬼門だなぁ。
Azure 上でSpark を使うメリット

ビッグデータ分析基盤として名を馳せている Apache Spark ですが、Azure 上では、HDInsight Spark という名前で提供されています。HDInsight Spark はただ単にマイクロソフトが、OSS のSpark をAzure に乗せたのではなく、Hortonworks のHDP（Hortonworks Data Platform）をベースのプラットフォームとしています。またHDP に加えてさらに 下記のようなAzure ならではのメリットを提供しています。

##クラスタ構築・スケールが簡単

クラスター構築・ノードの増減がAzure ポータルからボタンを数回クリックするだけで構築できてしまいます。初期の構築はたったの15 – 30分以内で完了です。これはクラウドならではのメリットでしょう。

##マイクロソフトの サポート付き。SLA 99.9% を提供。

##すぐにデータ分析などの作業を開始可能

デプロイ後は、Jupyter Notebook、Anaconda が最初からインストールされており、すぐに分析作業などを開始することができます。また各種BI（PowerBI、Tableauなど）も標準でサポートしており、Spark で作ったテーブルをBI で可視化することが簡単にできます。

##信頼性の高いストレージと高パフォーマンスのストレージ

ストレージには、Azure Blob ストレージをデフォルトで採用しています。Blob ストレージは同一データセンター内で自動的に3つの複製を持っており、耐障害性が非常に高く、またAzureの他のサービスとの連携性が高いことからデフォルトで採用されています。（※ HDFS ももちろん利用可能です）また、Azure Data Lake Store もストレージとしてオプションで利用可能です。Data Lake Store はアクセス時に、Azure AD 認証を必要とするためセキュリティが非常に高いです。またBlob ストレージに比べてパフォーマンスも優れており、Blob ストレージに比べて、高いレベルでの分析環境を提供することが可能です。

##Kafka + Spark

Kafka とSpark をマネージドサービスとして提供されています（プレビュー）。現時点でKafkaをマネージドサービスとして提供しているクラウドベンダは少ないのではないでしょうか。Kafka になじんだ開発者の方は是非ご利用を。

##Microsoft R Server + Spark

こちらもマネージドサービスで提供されております。分散処理が難しいR のコードをSpark の分散環境で動作させることが可能です。

##仮想ネットワークへの対応

Azure の仮想ネットワークにSpark クラスタを参加させることが可能です。クラスタ構築時にメニューから仮想ネットワーク一覧ができきますので、そこから該当するネットワークを選択するだけでセットアップ完了です。

##Livy を使ってリモートから実行

リモートからSparkジョブを投げるためのインタフェース、Livy （OSSプロジェクト：livy.io 参照）というREST IF が標準で組み込まれており、ジョブの投入・監視を行うことが容易に可能です。

##開発者向けのIDE プラグイン

Eclipse と IntelliJ 向けの プラグインを無償で提供しています。これによりIDE からSpark ジョブの投入やモニタリングが出来るようになります。またプラグインにはScala や Java のサンプルコードやテンプレートも付属しており開発効率を高めるだけでなく、さらにはローカルPC 上でアプリを動かすための仕組みをついているため、簡単に開発を開始することが可能です。

##Spark Streaming 向けの機能

Kafka を使ってストリーム分析を行う方もいるのではないかと思いますが、似たような機能のAzure IoT Hub や Event Hub からのストリームイベント受信を標準でサポートしています。

いかがでしょうか？上記の内容はOSS の Apache Spark で対応しようとすると、相当大変だと思われますが、HDInsight Spark を使うと標準で入っているので、非常に大きなメリットがあるものと思います。
Webサイト上の数値の変動をDatadogで可視化する

# はじめに

Webサイト上に掲載された数値を Web Scraping で取得し、それを [Datadog](https://www.datadoghq.com/) を用いて可視化するための [Agent Check](http://docs.datadoghq.com/ja/guides/agent_checks/) を作ってみました。

https://github.com/mounemoi/datadog-web-scraper

Datadog はサーバ監視のクラウドサービスですが、自作の Agent Check とカスタムメトリクスを利用することでユーザが指定した様々な数値をモニタリングできるようになります。
この機能を利用して、Web Scraping で取得した数値を Datadog に取り込み、Datadog の多彩なグラフ描画機能で可視化してしまおうというネタです。

# 取得サンプル

この Agent Check を用いて、いくつかサンプルを作ってみました。

## 1. Wikipedia のページ総数推移

[Wikipedia](https://en.wikipedia.org/wiki/Main_Page) のページ総数を取得して、その変動を Datadog でグラフ化してみました。
グラフはある日を起点にして、どの位ページ数が変動したかを表示しています。
(この起点の計算はDatadogで実施してます)

<img width="585" alt="Wikipedia のページ総数" src="https://qiita-image-store.s3.amazonaws.com/0/46613/f83d7768-e7e8-742d-67e3-352e4b5a2a02.png">

この値は [Wikipedia トップページ](https://en.wikipedia.org/wiki/Main_Page) の以下の数値部分を Web Scraping で取得しています。

<img width="366" alt="Wikipedia トップページ" src="https://qiita-image-store.s3.amazonaws.com/0/46613/688ac5b1-9dd1-b192-810a-1b4be26aa131.png">

グラフを見ると、線形的にページ数が増えてることが分かります。1日約900ページ位ですね。凄いですね。

## 2. オークションの出品数推移
これは某オークションサイトの、あるカテゴリの出品数を取得したものです。

<img width="585" alt="オークションの出品数遷移" src="https://qiita-image-store.s3.amazonaws.com/0/46613/dd5eee93-c962-3db2-9f9d-64c737efecfd.png">

毎日、21時から24時にかけて出品数が減ってますね。右端の一気に下がってる日は日曜日の夜です。
やはり、オークションが一番盛り上がるのは終了間際なので、みんながよく見る時間に合わせて終了時間を設定している出品者が多いのでしょうか？
(数値変化が分かりやすいように、y軸の原点を調整してます。これもDatadogの機能で行っています)

## 3. 東京の風速

こちらはアメダス情報を配信しているサイトから、東京の風速を取得してみました。
温度の変化を示したグラフはよく見かけるので、あえて風速です。

<img width="564" alt="東京の風速" src="https://qiita-image-store.s3.amazonaws.com/0/46613/45562fdf-5d95-4e19-d894-b4549efd2804.png">

 （前日との変化が分かりやすいように、前日の同時刻の数値（黒線）を同時に表示させています。これも Datadog の機能ですね)

この前日の午前中は雨だったのもあり、風速も強めだったようですね。
また、この配信サイトは1時間ごとに情報を更新していることも分かりました。

他にも Datadog の機能や Integration を組み合わせて「ECサイトの価格変動を記録し、一定の金額になったら slack 通知する」なんていうこともできると思います。

# Agent Check のインストール方法と設定方法

インストール方法と、Web Scraping で取得する値の指定方法は、リポジトリ内の [README.ja.md](https://github.com/mounemoi/datadog-web-scraper/blob/master/README.ja.md) に記載しています。

利用には Datadog のアカウントと、Datadog Agent をインストールしたサーバが必要です。

なお、この Agent Check の Web Scraping は単純に HTML を GET しているだけなので、JavaScript などで描画している値や、ログインが必要なページの値は取得できないです。

# まとめ

Datadog は Agent Check や SDK を用いることで様々な数値をカスタムメトリクスで取得することができます。
この機能でサーバ監視情報以外の、例えばサーバ上で稼働しているサービスの利用情報なども可視化することができる訳ですが、その練習として作ってみました。

また、 Agent Check は python で記述するため、 python 開発者はとっつきやすいだろうなと思いました。

Datadog って面白いですねー。
Visual Studio Code上ではC#スクリプトのコード補完がいい感じに効くっぽいよ

#C#スクリプトとは
この辺を読めばだいたいわかるよ。
[C#スクリプト実行 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C](http://ufcpp.net/study/csharp/cheatsheet/apscripting/)
[csi.exeコマンド登場！ C#スクリプト（.csx）やREPLを動かそう - Build Insider](http://www.buildinsider.net/language/csharpscript/01)

#C#スクリプトのコード補完

スクリプトといえどコーディングするときはシンタックスハイライトやコード補完が欲しいですよね。
Visual Studio 2017はC#スクリプト(.csx)でもちゃんと補完してくれます。

![vs_script1.gif](https://qiita-image-store.s3.amazonaws.com/0/119431/d03fe9ad-bf62-1106-9e1d-958532b9b0ae.gif)

と見せかけて、#loadによる別のソースファイルの参照や#rによるDLLの参照の場合は、その先にあるクラスやメソッドを補完候補として表示してくれません。

![vs_script2.gif](https://qiita-image-store.s3.amazonaws.com/0/119431/63c1fb3f-7ac0-e37b-d1ac-ed2ecfc2be21.gif)

この中途半端さのせいで妙にストレスが溜まります。
解決策はあるのでしょうか？それともそのような機能を搭載してくれるまで我慢しないといけないのでしょうか？

#Visual Studio Code + scriptcs

[scriptcs](http://scriptcs.net/)
[Visual Studio Code で C# script を書く - miso_soup3 Blog](http://miso-soup3.hateblo.jp/entry/2015/12/15/011302)

自分なりにいろいろ調べた結果、Visual Studio Code上のscriptcsならいい感じに補完してくれるぜ！
という結論に落ち着きました。
ついでにCtrl(Cmd)+Shift+Rを同時に押すと、スクリプトを実行して結果を表示してくれます。
凄いですね。

![vscode_script.gif](https://qiita-image-store.s3.amazonaws.com/0/119431/80db4f80-8c59-3ac1-480f-5f25dd37789d.gif)

今日知ったばっかりでVisual Studio Codeもscriptcsもほとんど使ったことがないので、使い続けてみると案外また別のところで不便に感じるかもしれませんが、とにかく私は満足です。
おわり。

#追記
いつのまにかVisual Studio 2017でもインテリセンスが効くようになっていました。
いや、コメントにもある通り、元々出来たけど私が勘違いしただけかもしれません。
![hiyoko.gif](https://qiita-image-store.s3.amazonaws.com/0/119431/478ce96d-f8f8-664d-67de-b45228b4444c.gif)
subprocess.Popenの出力をリアルタイムで読む

# 概要
subprocess.Popenで標準出力に出力される内容を追いかけて読んでいきます。この際、readline()で改行ごとに読むのではなく、read()を使ってひたすら(?)読んでみます。ストリーム周りではよく悩むのでメモ。

CentOS7上でPython 2.7.5で動作確認しました。

# 文字出力スクリプト
Popenで起動される側のスクリプトです

```py:textout.py
#!/usr/bin/env python
import sys
import time
for i in range(0, 10):
    sys.stdout.write("[Count {0:04d}]".format(i))
    time.sleep(1)
```

1秒ごとに`[Count 0000]`を出力する単純なスクリプトです。ただ、改行しないので、readline()では読めません。

# 実行スクリプト
上のスクリプトをPopenで呼び出し、標準出力を読んでいきます。

```py:reader.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, time, errno, fcntl
from subprocess import Popen, PIPE

# Popenでtextout.pyを実行する
# このときpythonに -u オプションを渡し、バッファリングしないようにする
p = Popen([sys.executable, "-u", "textout.py"], bufsize=0, stdout=PIPE)

# p.stdoutをノンブロッキングモードにする
flag = fcntl.fcntl(p.stdout.fileno(), fcntl.F_GETFL)
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, flag | os.O_NONBLOCK)

while True:
    # 読み込みループ
    try:
        # p.stdoutを読み込む
        # ノンブロッキングモードなので読める分だけ読む
        buf = p.stdout.read()
        if buf == "": break   # p.stdoutがクローズされたら抜ける
        sys.stdout.write(buf) # 読んだ内容を出力
        sys.stdout.flush()    # 改行がないのでflush()
    except IOError, e:
        # 読むべき内容がない場合はIOError(11,
        # "Resource temporarily unavailable")が
        # スローされるので待機
        if e.errno == errno.EAGAIN:
            time.sleep(0.1)
p.wait()
```

# 実行結果
```shell-session
$ ./reader.py
[Count 0000][Count 0001][Count 0002][Count 0003][Count 0004][Count 0005][Count 0006][Count 0007][Count 0008][Count 0009]
```

1秒ごとに`[Count 0000]`が出力されます。

# ポイント
- textout.pyを実行する際はバッファリングしない、またはsys.stdoutに書き込んだらflush()する
- reader.pyはread()でp.stdoutを読むので、ノンブロッキングモードで読む
- 出力待ちの時はerrno.EAGAINが送出されるので、例外処理して待機する
- textout.pyが終了するまで待つならこんな面倒なことをせずにread()一発(^^;
VSCode+Vimでキーリピートが効かないとき

これで解決 

```
defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false         # For VS Code
defaults write com.microsoft.VSCodeInsiders ApplePressAndHoldEnabled -bool false # For VS Code Insider
```
https://github.com/VSCodeVim/Vim#faq

VSCode Insiders は正式リリース前のバージョンで、新機能がいち早く試せます
環境変数/クラスパスの備忘録

#javaのプラグインjarのmacとlinuxの楽なクラスパスの通し方。
windowsはPATHが通っていればどこでも良い

###macのjar置き場
~/Library/Java/Extensions/
にjarを置けば、クラスパスを指定すること無く自動的にパスが通る

###Linuxのjar置き場
$JAVA_HOME/jre/lib/ext
$JRE_HOME/lib/ext
同上。
deinで管理してるプラグインのディレクトリにサクッと移動する

最近vimプラグインの実装をサクッと見たいときが多いので便利コマンド作りました。
コマンド名は思い切ってdeinにしてます。
  
* zshで作りましたがbashでも動きます(たぶん)
* findの前にcdしてるのはpecoでのフィルタリング時に手軽に作者名/プラグインのみ表示したかったためです。
* 今の所github.com以外のプラグインは使ってないので、この実装ではそれ以外のプラグインは表示されません。


```bash
dein(){
  save_pwd="${PWD}"
  cd ~/.cache/dein/repos/github.com/
  result="$(find */* -maxdepth 0 -type d | sort | peco)"
  [[ -z $result ]] && cd "${save_pwd}"
  cd "${result}"
}
```
パフォーマンスの良いSQLを記述しよう [SQLServer]

## はじめに
SQLのチューニングといえばインデックスをとりあえず作成する。といった対応が取られがちですが、数万レコード程度のデータ量ではあまり効果がありません。
またインデックスを乱立すると複数の条件がある時などにオプティマイザが誤作動を起こす要因ともなります。よって本当にインデックスがないことが原因なのか？を熟考する必要があります。

今回は、処理を早くするクエリの記述方法を備忘録がてらにまとめておこうと思います。

## 目次
1. SELECT旬では必要なカラムのみを取得
2. 暗黙の型変換
3. WHERE句の左辺に算術演算子や関数を使用しない
4. WHERE句は選択条件が少なくなる条件から記述
5. UNION と UNION ALL の使い分け

## 1. SELECT旬では必要なカラムのみを取得
取得するカラムを絞る事で検索速度が上昇

```ruby:Bad
SELECT *
FROM Order
```
```ruby:Good
SELECT O.id
      ,O.orderName
FROM Order AS O
```

## 2. 暗黙の型変換
左辺に暗黙の型変換が発生するとインデックスが有効にならないため、検索速度が低下

```ruby:前提条件
Order.id の型は nvarchar(15)
```
```ruby:Bad（左辺がint型に暗黙の型変換がされる為）
SELECT O.id
      ,O.orderName
FROM Order AS O
WHERE O.id = 120000
```
```ruby:Good
SELECT O.id
      ,O.orderName
FROM Order AS O
WHERE O.id = N'120000'
```

## 3. WHERE句の左辺に算術演算子や関数を使用しない
左辺に算術演算や関数を指定するとインデックスが有効にならないため、検索速度が低下

```ruby:Bad
SELECT O.id
      ,O.orderName
FROM Order AS O
WHERE O.price * 2 > 20000
```
```ruby:Good
SELECT O.id
      ,O.orderName
FROM Order AS O
WHERE O.price > 20000 / 2
```

## 4. WHERE句は選択条件が少なくなる条件から記述
検索条件が複数ある場合、抽出する件数が少なくなる条件から先に行う

```ruby:前提条件
Order.type = 1 のレコードは10件
Order.price > 20000 のレコードは1000件
```
```ruby:Bad（左辺がint型に暗黙の型変換がされる為）
SELECT O.id
      ,O.orderName
FROM Order AS O
WHERE O.price > 20000
  AND O.type = 1
```
```ruby:Good
SELECT O.id
      ,O.orderName
FROM Order AS O
WHERE O.type = 1
  AND O.price > 20000
```

## 5. UNION と UNION ALL の使い分け
UNION を使用した場合、重複行を排除するためのソートが発生する。よって検索速度が低下
重複を許す場合は UNION ALL を使用する。
OUTLOOK VBA オブジェクトまとめ   Store オブジェクト補足 StoreオブジェクトはVBSで使用できる

[OUTLOOK VBA オブジェクトまとめ - QIIQ via Qiita](http://qiita.com/Q11Q/items/ac14d96c00e707de5d13)
では検証できなかった、Store Object について補足します

##Store.GetSpecialFolder
[Store.GetSpecialFolder メソッド (Outlook)](https://msdn.microsoft.com/ja-jp/library/office/ff867630.aspx)

### olSpecialFolderAllTasks = 0
[すべてのタスク] 検索フォルダー。

### olSpecialFolderReminders = 1
[アラーム] 検索フォルダー。 

これは正直アラームの設定が複雑な時に使えそうだが、具体的な使用方法はPHPで使用されている程度である。
[How to get Microsoft Outlook reminder event list on webpage by PHP? - codingdir.com](http://codingdir.com/questions/17541632/How-to-get-Microsoft-Outlook-reminder-event-list-on-webpage-by-PHP-)

## Store object can use Vbs with some notes ストアオブジェクトはVBSでつかえるが…

以下のVBSは保存先フォルダの受信トレイ（受信トレイのサブフォルダはカウントしていない）のメールの数をカウントするVBS
つまりVbscriptでもStoreオブジェクトは使用できる

```vbnet:mailCount.VBS
Option Explicit
Dim oApp: Set oApp = CreateObject("Outlook.Application")
Dim NS: Set NS = oApp.GetNamespace("MAPI")
Dim olStores, olStore, oRoot, olFolders, olFolder
Set olStores = NS.Stores
Set olStore = olStores("保存先")
Set oRoot = olStore.GetRootFolder
Set olFolders = oRoot.folders
Set olFolder = olFolders("受信トレイ") '定数ではなく具体的なフォルダ名
MsgBox olFolder.Items.Count
Set NS = Nothing
Set oApp = Nothing
```

## 保存先フォルダの場合の注意点

### Store.GetDefautlfolderは無効

とりあえず当方が確認したOutlook 2013では
Set olStore = olStores("保存先")
のように保存先フォルダを指定した時は、
Set olFolder = olStore.GetDefaultFolder(6)
Set olFolder = olFolders(olFolderInbox)
は***無効***である。
定数ではなく具体的にフォルダ名指定すると初めて受信トレイ（受信メールフォルダ）に到達できる。

### 保存先フォルダの場合はフォルダの名前を具体的に指定する必要がある。

 - 保存先のようなローカルのOutlookデータファイルの中ではolDefaultFolder定数は使用できない。
 - よって、保存先の受信トレイは必ず次のように指定する

```vbnet
Set olStore = olStores("保存先")
Set oRoot = olStore.GetRootFolder
Set olFolders = oRoot.folders
Set olFolder = olFolders("受信トレイ")
```
## 通常のメールアカウントの場合
### Store.Getdefaultfolderが有効
たとえばLastName.FirstName@Domain というメールアドレスなら

```VBNET:MailItemCount.VBS
Option Explicit
Const olFolderInbox = 6
Dim oApp: Set oApp = CreateObject("Outlook.Application")
Dim NS: Set NS = oApp.GetNamespace("MAPI")
Dim olStores, olStore, oRoot, olFolders, olFolder
Set olStores = NS.Stores
Set olStore = olStores("LastName.FirstName@Domain")
Set olFolder = olStore.GetDefaultFolder(olFolderInbox)
MsgBox olFolder.Items.Count
```
このようにDefaultFolderで受信トレイに到達することができる。

## Tips
####ENUMをConstで定義するメリット
- 今回は残念な結果でしたが、一般的には一つの確立したテクニックとして、VBScript、参照設定をしない場合のVBA、PowerShellではEnumで決まっている定数を(Global)のConstで定数化すると便利です。
Vbscript Always Usefull when enumulation decide constitution
For example　たとえば
olFolderInbox 9
then 
Const olFolderInbox = 9
これだと検索も効くのでオリジナルな定数名よりはるかに容易にネットのヘルプにも到達できます。

- この定数の解説リンク [Outlook.OlDefaultFolders](https://msdn.microsoft.com/en-us/library/office/aa220100(v=office.11).aspx)
- しかし上記サイトでは定数がいくつかはわかりません。MSDNではよくあることです。

####定数名がいくつかを調べる方法
- こうした時はOUTLOOKのVBEditorを起動し、イミディエイトウィンドウに次のように入力してReturnを押します

?olFolderInbox

- もしくはF2を押してオブジェクトブラウザを起動し olFolderInbox を入れて検索します。すると、３分割された画面の一番下に
Const olFolderInbox = 6
 Outlook.OlDefaultFolders のメンバー

と出てきます。この6が定数の値です。
- VBAでは仮にこのあと参照設定しても、Constが優先されるので、うっかり削るのを忘れても安全です（ただし削除が原則です）
iOS 実装サンプルアプリ集

iOSアプリ開発時に参考になりそうな、実装サンプルor実際にリリースされているアプリののリポジトリリストです。
類似アプリを作成するときに参考にしたり、プロジェクト構成などを参考にできそうです。

## aslanyanhaik/youtube-iOS [[Code]](https://github.com/aslanyanhaik/youtube-iOS)
**YouTubeUIテンプレートアプリ** 

YouTube公式アプリそっくりの動きをするアプリの実装サンプルのリポジトリです。
swiftで作成されています。
![スクリーンショット 2017-04-03 12.57.22.png](https://qiita-image-store.s3.amazonaws.com/0/68288/0b9210c1-476a-9571-9f64-46af466e0054.png)

## tnantoka/edhita [[Code]](https://github.com/tnantoka/edhita) [[Store]](https://itunes.apple.com/us/app/edhita-open-source-text-editor/id398896655)
**テキストエディタアプリ**

HTML、MarkDownをプレビューしながら編集できるアプリのリポジトリです。
![screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/68288/cf5774fc-d088-5663-71b2-4c8252f4e719.png)

## thedillonb/CodeHub[[Code]](https://github.com/thedillonb/CodeHub) [[Store]](https://itunes.apple.com/app/codehub-github-for-ios/id707173885?ign-mpt=uo%3D8)
**GitHub API利用アプリ**

Githubの閲覧、アカウント管理ができるアプリです。
![68747470733a2f2f7261772e6769746875622e636f6d2f74686564696c6c6f6e622f436f64654875622f6d61737465722f53637265656e73686f74732f496d616765312e6a7067.jpeg](https://qiita-image-store.s3.amazonaws.com/0/68288/32546a2c-043c-325a-2259-b869aa699eef.jpeg)

## CatchChat/Yep[[Code]](https://github.com/CatchChat/Yep) [[Store]](https://itunes.apple.com/app/codehub-github-for-ios/id707173885?ign-mpt=uo%3D8)
**コミュニティアプリ**
コミュニティ系アプリだと思われます。
公式サイトにアクセスできず詳細はよくわからないです。

![スクリーンショット 2017-04-03 13.09.51.png](https://qiita-image-store.s3.amazonaws.com/0/68288/57024209-9914-f20f-2e20-c8d218611b76.png)
AWS lambdaからdynamodbに接続: "AccessDeniedException"で怒られたのでポリシーを設定した

# やりたかったこと

lambdaから条件によって、dynamodb内のレコードを読み書きしたかった。

# 発生した問題

```エラー
2017-04-03T12:11:12.144Z	******	Unable to delete item. Error JSON:
{
    "message": "User: arn:aws:sts::******:assumed-role/******/****** is not authorized to perform: dynamodb:DeleteItem on resource: arn:aws:dynamodb:us-east-1:******:table/******",
    "code": "AccessDeniedException",
    "time": "2017-04-03T12:11:12.131Z",
    "requestId": "******",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 0
}
```

# どう解決したか？

lambdaのポリシーに、dynamodbにアクセスできる権限を付与しました。

まず、現在のlambdaのポリシーを確認
![IMG_3987.JPG](https://qiita-image-store.s3.amazonaws.com/0/96286/aa6ec9d4-d1fc-35ed-9dba-f97e608ed112.jpeg)

次に、ポリシーの役割を増やす。こんな感じ
（なんかフワフワした説明ですみません）
![IMG_3988.JPG](https://qiita-image-store.s3.amazonaws.com/0/96286/3f457cb0-8a3b-e3c0-efe9-c16533da9e60.jpeg)

その際、ARNという、完全修飾名みたいなものが必要になる。dynamodbはoverviewからわかります
![IMG_3989.JPG](https://qiita-image-store.s3.amazonaws.com/0/96286/093a3d73-c0f0-b706-2264-bee366a0af8e.jpeg)

以上！