OmniAICreator/Qiita-1.07M huggingface dataset:
Ruby インスタンス変数を外部から操作する パート2

昨日の記事[Ruby インスタンス変数を外部から操作する](https://qiita.com/pank24ever/items/7c615a09b19322a7cefd)の続きです

##attr_accessorメソッド
単純にインスタンス変数の内容を外部から読み書きする場合は、
arrt_accessorメソッドを使う

```rb
class User
  #@nameを読み書きするメソッドが自動的に定義される
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  #nameメソッドや、name=メソッドを明示的に定義する必要がない
end

user = User.new('太郎')
#@nameを変更する
user.name = 次郎
user.name #=> "次郎"
```

複数指定することも可能

```rb
class User
  #@nameを読み書きするメソッドが自動的に定義される
  attr_accessor :name, :age

  def initialize(name)
    @name = name
    @age = age
  end

  #nameメソッドや、name=メソッドを明示的に定義する必要がない
end

user = User.new('太郎', 20)
user.name #=> '太郎'
user.age #=> 20
```

##attr_renderメソッド
インスタンス変数の内容を読み取り専用にしたい場合は、
arrt_renderメソッドを使う

```rb
class User
  #読み取り用のメソッドだけを自動的に定義する
  attr_render :name

  def initialize(name)
    @name = name
  end
end

user = User.new('太郎')
#@nameを参照する
user.name #=> "太郎"

user.name = '次郎'
#=> NoMethodError
```

##attr_writerメソッド
インスタンス変数の内容を書き込み専用にしたい場合は、
arrt_writerメソッドを使う

```rb
class User
  #書き込み用のメソッドだけを自動的に定義する
  attr_writer :name

  def initialize(name)
    @name = name
  end
end

user = User.new('太郎')
#@nameは変更できる
user.name = "次郎"

#@nameの参照はできない
user.name
#=> NoMethodError
```

##参考記事、書籍
チェリー本
VueCLIでポートフォリオ作った話

# 概要
自分のポートフォリオを最近学んだVueで作成したのでまとめておきます。
作ったのは[こちら](https://yuta97.github.io/MyPortfolio-dist/index.html#/)です。
# 開発フロー
Vue create ⇨　build ⇨　Github pagesで公開
## 始め方
基本的には[公式](https://cli.vuejs.org/)の通りで問題ない
Vueの入門記事はたくさんあるのでざっと読みながら開発していけばいいと思います。
## vue roter
ルーティングはvue routerを使用。
[公式](https://router.vuejs.org/ja/installation.html#vue-cli)を読めば大体使い方はわかるはずです。
## デザイン
Vuetifyを導入しました。
色々テンプレがあり簡単にリッチなサイトになるのでおすすめ。
カスタマイズはうまくいかず。
[公式](https://vuetifyjs.com/en/)
## build
`npm run build`で　`dist`というフォルダが作成されそこにビルドされたものが入ります。
## Github pages
ビルドで作ったフォルダをGithubにあげて、設定から公開させるだけでOK
詳細はこちら[公式](https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/about-github-pages)
# エラーとかとか
## vue create  VS vue init
プロジェクトを始める際にどちらを使うかの問題。簡単に言えばVersionの違いに関係するようです。
僕はVuetifyの導入のために`vue create`にしました。
詳細はこちら（[vue init と vue createの違い](https://qiita.com/teraco/items/74a6104d3e201c4f654e)）

## buildした時にPATHが通っていない
`build`した際に白紙になってページが表示されない問題が生じました。
下の参考のようにHistory Modeの問題のようなのでオフにしました。
参考：
[【vue-router】Vue.jsでビルドしたウェブサイトが白紙で表示される場合の対処法 【History Mode】](https://hayeta.hatenablog.com/entry/vue-blank-page)
HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get (Elixir)


この記事は [Elixir その2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/elixir2) 9日目です。
前回は、[CircleCIでmix testする、Gigalixirへデプロイする(Elixir/Phoenix)](https://qiita.com/torifukukaiou/items/1e266c7b213cdd3fd58e) でした。

---

# はじめに
- みなさん！　[Elixir](https://elixir-lang.org/)を楽しんでいますか！
- `mix deps.get`が失敗して、`HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get` というメッセージがでたことありますか？
- 私の家のインターネット回線の速度が夜になると極端に遅くなるということがありまして、ちょくちょくおみかけします
- まったく見たことがないというアルケミストもいて、その方はインターネット回線がきっといいのでしょう！
    - うらやましい:relaxed:

# もしおみかけしたら

- メッセージの通り、**迷わず行けよ　行けばわかるさ　ありがとう！**

```
$ HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get
```

# 一体なになのさ

- [https://github.com/hexpm/hex/blob/v0.20.6/lib/mix/tasks/hex.config.ex#L44-L49](https://github.com/hexpm/hex/blob/v0.20.6/lib/mix/tasks/hex.config.ex#L44-L49) をご参照ください

# Wrapping Up :lgtm: :santa: :santa_tone1: :santa_tone2: :santa_tone3: :santa_tone4: :santa_tone5: :lgtm:
- Enjoy [Elixir](https://elixir-lang.org/) !!! :rocket::rocket::rocket:
Linux ネットワークの設定ファイル

#【Linux ネットワークの設定ファイル】

###・ホスト名を設定（Debian系）

```bash
# cat /etc/hostname
Debian
```
###・ホスト名を設定（RedHat系）
　ネットワーク機能の有効/無効やデフォルトゲートウェイ等も設定可能</strong>

```bash
# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=CentOS
GATEWAY=192.168.1.1
```

###・IPアドレスとホスト名の対応付け

```bash
# cat /etc/hosts
112.78.124.10   example.com
192.168.1.100   FileServer
```

###・名前解決やサービス名解決の問い合わせ順序の指定

```bash
# cat /etc/nsswitch.conf
hosts:   files dns
services:   files
```

※hosts: の行にDNSの指定がないと名前解決されない。

###・ドメイン名やDNSサーバの指定

DNSクライアントホスト上で、どのDNSサービスに対して、問い合わせを行うかを定義するファイル

```bash
# cat /etc/resolv.conf
domain   ping-t.com
nameserver   192.168.1.1
```
domain行には、このホストが属するドメイン名
search行には、ドメイン名が省略された場合に補完するドメイン名
nameserver行には、参照先のDNSサーバのIPアドレス

※複数指定する場合は、1行ずつ表記する。

###・サービス名とポート番号の対応付け

```bash
# cat /etc/services
telnet   23/tcp
```
macOS Big SurでArduino IDEからESP32の書き込みができない件

手持ちのMacBookを，出来心でCatalina→Big Surにアップグレード．
当然何も起こらないはずがなく…

## ESP32 Dev moduleでのコンパイルができない
コンパイルしようとすると

```
ValueError: dlsym(RTLD_DEFAULT, kIOMasterPortDefault): symbol not found
Failed to execute script esptool
exit status 255
```

などというエラーが発生．

[arduino-esp32 projects fail on macOS 11 "Big Sur"](https://github.com/espressif/arduino-esp32/issues/4408) に同様のissueが上がっている．
どうやらBig Surの仕様のせいらしい．そりゃまだ対応されてないわな…（なぜアップグレードしたんだ俺）

### 対処手順
[M1 MacBook Air 2020 でArduino IDEを動かしてみました](https://kanpapa.com/today/2020/11/m1-macbook-air-2020-arduino-ide.html) を見て解決を試みる．
行った手順を以下に引用．

>1. Arduino IDEの環境設定から、/Users/...../preferences.txt のリンクをクリックして、フォルダを開く。
2. packages/esp32/hardware/esp32/1.x.x フォルダの中にある plathome.txtを開き、
7行目にある`tools.esptool_py.cmd=esptool`となっている部分を
`tools.esptool_py.cmd=esptool.py`と書き換えて保存する。
3. packages/esp32/hardware/esp32/1.x.x/tools フォルダにある esptool.py を packages/esp32/tools/esptool_py/2.x.x/ フォルダにコピーする。
4. 以下のコマンドで、コピーした esptool.py に実行権限をつける。
`chmod +x packages/esp32/tools/esptool_py/2.x.x/esptool.py`


### 解決…できない！
解決できた人はそれでよい．帰りなさい．

私の場合，これが発生した．

```
ImportError: No module named serial exit status 1 Error compiling for board ESP32 Dev Module.
```

あー，pyserialが無いのね．
おっけーおっけー，コマンドからこれでインストールすれば解決だ

```
$ pip install pyserial
```

### pyserialが読み込まれない
読み込んでもらえた人はそれでよい．お帰りなさい．

確かにpyserialはインストールできたはずなのだが，esptoolちゃんは毅然としてImportErrorを履き続ける．ツンデレかな？
更に調べていったら以下のようなissueに辿り着いた．

[esptool fails on MacOS Big Sur preview: Failure to import serial.tools.list_ports #509](https://github.com/pyserial/pyserial/issues/509)

[このコメント](https://github.com/pyserial/pyserial/issues/509#issuecomment-726966076)を参考に私が行った手順は以下の通り．

1. コマンドから`$ /usr/local/bin/pip3 install pyserial`を実行し，大元のPythonにpyserialをインストール
2. 先程コピーした esptool.py をテキストエディタで開き，１行目の`#!/usr/bin/env python`を`#!/usr/local/bin/python3`に書き換える

これで無事に書き込みできました！やったね！

## おわりに
それにしても，なぜ単純にpipでpyserialをインストールしても，esptoolは読み込んでくれなかったのか？
おそらくpyenvやらpipenvやらで，普段のPython環境を構築してしまっていたのが原因かと思われる．

まぁこんな面倒なことをせずとも，いずれesptoolもBig Surに対応してくれるだろうけど，急ぎでESP32を書き込みたい！って人の参考になったなら幸いです．
【Java】文字列を分割する方法

#プログラミング勉強日記
2020年12月8日
3日連続JavaのString型の扱いになるが、今日は文字列を分解するsplitメソッドの使い方をまとめる。

#splitメソッドとは
　文字列を分割して、分割した文字列を配列として格納するメソッド。区切りたい文字には正規表現を設定することができ、分割回数の数値によって空白文字の消去にも使うことができる。String型の配列として返す。（正規表現については[こちらの記事](https://qiita.com/mzmz__02/items/33440a0bb8523f249416#%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%A8%E3%81%AF)で詳しく扱っている。）
　csvファイルといったカンマ区切りの文字列のファイルを操作するときによく使われる。


```java:splitメソッドの書き方
文字列.split(区切りたい文字列, 分割回数);
```

```java:サンプルコード
public class Main {
  public static void main(String[] args) {
    String str = "white,green,blue,red";
    String[] colors = str.split(",");
    for (int i = 0; i < colors.length; i++) {
      System.out.println(colors[i]);
    }
  }
}
```

```:実行結果
white
green
blue
red
```


#文字列の数を指定する場合
　splitメソッドの第2引数に1以上の整数を設定することで、文字列の分割回数を制御することができる。

```java:サンプルコード
public class Main {
  public static void main(String[] args) {
    String str = "white,green,blue,red,,";
    String[] colors = str.split(",", 3);
    for (int i = 0; i < colors.length; i++) {
      System.out.println(colors[i]);
    }
  }
}
```

```:実行結果
white
green
blue,red
```

#末尾の空白文字の要素を削除する場合
　第2引数が0もしくは何も設定しない場合は、末尾の空白文字を削除することができる。削除したくないときは`-1`といったマイナスの値を設定する。

```java:サンプルコード
public class Main {
  public static void main(String[] args) {
    String str = "white,green,blue,red,,";
    String[] colors = str.split(",", 0);
 
    System.out.println("第二引数が0の場合");
    for (int i = 0; i < colors.length; i++) {
      System.out.println(i + ":" + colors[i]);
    }

    colors = str.split(",", -1);
    System.out.println("第二引数が-1の場合");
    for (int i = 0; i < colors.length; i++) {
      System.out.println(i + ":" + colors[i]);
    }
  } 
}
```

```:実行結果
第二引数が0の場合
0:white
1:green
2:blue
3:red

第二引数が-1の場合
0:white
1:green
2:blue
3:red
4:
5:
```

#間にある空白文字を削除する場合
　間の空白文字を削除するときには正規表現を使う。

```java:サンプルコード
public class Main {
  public static void main(String[] args) {
    String str = "white  ,green  ,blue,red";
    String[] colors = str.split("[\\s]*,[\\s]*");
    
    for (int i = 0; i < colors.length; i++) {
      System.out.println(colors[i]);
    }
  }
}
```

```:実行結果
white
green
blue
red
```

#参考文献
[2分で理解！Javaの文字列を分割するsplitメソッド【Stringクラス】](https://eng-entrance.com/java-string-split)
[Javaのsplitの使い方を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/25947)
個人的によく使うgcloudコマンドまとめ ~主にGCE周り~

# はじめに
普段よくCloud Shellから使うGCE周りのgcloudコマンドをまとめたメモです。

# コマンドリスト

### インスタンスリストを確認

```
$ gcloud compute instances list
```
- プロジェクト内の全てのGCEインスタンスが表示されます。
- デフォルトでは、すべてのゾーンのインスタンスが表示されます。ゾーンを絞り込んで表示させたい場合は、
`--filter="zone:( [ここにゾーン名] )"` をつけて発行する。

### インスタンスを起動/停止

```
#起動
$ gcloud compute instances start [INSTANCE_NAMES]

#停止
$ gcloud compute instances stop [INSTANCE_NAMES]
```


### ディスクのアタッチ/デタッチ

```
#アタッチ
$ gcloud compute instances attach-disk [INSTANCE_NAME] --disk [DISK_NAME]

#デタッチ
$ gcloud compute instances detach-disk [INSTANCE_NAME] --disk [DISK_NAME]
```

### インスタンスのマシンタイプ変更

```
$ gcloud compute instances set-machine-type [INSTANCE_NAME] --machine-type [MACHINE_TYPE]
```
- マシンタイプを変更する場合はインスタンスが停止状態である必要があります。

### スナップショットの取得/スナップショット一覧の表示/スナップショットの情報表示
```
# スナップショットの取得
$ gcloud compute disks snapshot [DISK_NAME]

# スナップショット一覧の表示
$ gcloud compute snapshots list

# スナップショットの情報表示
$ gcloud compute snapshots describe [SNAPSHOT_NAME]
```

- [DISK_NAME] は、スナップショットを作成するゾーン永続ディスクの名前です。
- `gcloud compute snapshots describe`は作成時刻、サイズ、ソースディスクなど、特定のスナップショットについての情報を一覧表示できます。

# 参考資料
- [Compute Engine ガイド](https://cloud.google.com/compute/docs/how-to)
- [Cloud SDK コマンドライン インターフェース リファレンス](https://cloud.google.com/sdk/gcloud/reference/compute)
CentOS 8にRuby 2.7をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してCentOS8にRuby 2.7をインストール
参考：[RHEL8のパッケージ構成 - BaseOSとApplication Stream - 赤帽エンジニアブログ]( https://rheb.hatenablog.com/entry/rhel8_baseos_and_appstream)
　　　[第4章 新機能 Red Hat Enterprise Linux 8 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/8.3_release_notes/new-features#enhancement_dynamic-programming-languages-web-and-database-servers)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux 8 Application Streams Life Cycle - Red Hat Customer Portal](https://access.redhat.com/node/4079021)より、2023-05がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。
なおCentOS Linux 8が2021-12にEOLを迎えるため、それ以降の更新を受けるためにはCentOS Stream8を含めた他ディストリビューションへの移行が必要。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
CentOS Linux release 8.3.2011

# yum module install ruby:2.7
... 略
```

### 各種確認

```shell-session
# which ruby
/usr/bin/ruby

# ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
```
CentOS 8にPHP 7.4, PHP-FPM 7.4をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してCentOS8にPHP7.4をインストール
親記事：[PHP, PHP-FPMの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/dfe3823554b7caba6f6a)
参考：[RHEL8のパッケージ構成 - BaseOSとApplication Stream - 赤帽エンジニアブログ]( https://rheb.hatenablog.com/entry/rhel8_baseos_and_appstream)
　　　[第4章 新機能 Red Hat Enterprise Linux 8 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/8.3_release_notes/new-features#enhancement_dynamic-programming-languages-web-and-database-servers)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux 8 Application Streams Life Cycle - Red Hat Customer Portal](https://access.redhat.com/node/4079021)より、2029-05がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。
なおCentOS Linux 8が2021-12にEOLを迎えるため、それ以降の更新を受けるためにはCentOS Stream8を含めた他ディストリビューションへの移行が必要。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
CentOS Linux release 8.3.2011

# yum module install php:7.4
... 略
```

### 各種確認

```shell-session
# which php
/usr/bin/php

# php -v
PHP 7.4.6 (cli) (built: May 12 2020 08:09:15) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

# php -i | grep php.ini
Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini

# which php-fpm
/usr/sbin/php-fpm

# /usr/sbin/php-fpm -v
PHP 7.4.6 (fpm-fcgi) (built: May 12 2020 08:09:15)
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```
アドベントカレンダー6日目：SREを読んでみた「リスクの受容」編②

前回は、リスクの受容に関して、学びました。信頼性の向上のみを行うのではなく、必要に応じて、トレードオフを行うことで、より意味のある改善を行うことができます。
今回は、受容したリスクによって、生まれたリソースを用いるためにエラーバジェットの考えを導入し、活用する方法を学びます。

## どこにでもあるありふれた対立
以前の回で、プロダクト開発チームとSREチームの間に文代が生まれているという話をしました。これは、自分のチームの利益を増やすことは、相手のチームの利益を抑えることで成り立つような関係になっていたからでした。
しかし、そのような対立やトレードオフは、どこにでもあります。予想外のことに強いソフトウェアは、ユーザーが安心して、使うことができますが、強すぎれば、使いずらく、弱すぎれば、使い物になりません。サービス障害やサービスの信頼を落とすようなことをしないために、様々なテストをする必要がありますが、やりすぎれば、市場を失うかもしれません。リリースに伴うリスクの低減とその他の作業とのバランスをどのようにとるべきでしょうか？この線引きは、個人やチームの中の何ならの基準によってなされることが多いです。

> **そういった判断は、政治、恐怖、あるいは願望によってきめられているかもしれません。**<sup>1</sup>

この決定を下すうえで、客観的なメトリクスがあることは、より良い交渉の結果を導くためにとても重要です。
エラーバジェットは、そのため指標の一つとなります。

## エラーバジェットの形成
エラーバジェットとは、リスクを受け入れたことにより、生まれる余剰のリソースです。
どの程度のリスクを受け入れるのかを求めるためには、まずサービスレベルの目標、すなわちSLO（Service Level Objective)を決定する必要があります。その後、実際の稼働時間を計測します。SLOと実際の稼働時間の差分が「損失可能な信頼性」という「予算」の残分となります。計測された稼働時間がSLOを超えている、言い換えれば、エラーバジェットがまだ残っているなら新しいリリースをプッシュできます。
仮に0.001%の失敗率をエラーバジェットとした場合、0.0002%が失敗すると、エラーバジェットは20%消費されます。失敗が少ないほど、エラーバジェットを確保でき、プロダクトの開発に取り組めることになります。

## メリット
エラーバジェットを用いると、開発とSRE、双方にメリットがあります。
システムのSLOを満たしている限り、リリースを継続できます。SLOを満たせないことが頻発し、エラーバジェットを使い切りそうなら、リリースを一旦中断し、システムの弾力性を上げたり、パフォーマンス改善のための取り組みをします。
エラーバジェットをもとに次の取り組みを柔軟に判断することもできます。プロタクト開発チームがテストをそこそこにリリースを早く行いたいと考えるとき、エラーバジェットが多いなら、失敗率が上がるリスクを取ってでも、リリースを早めることができます。エラーバジェットが少ないなら、エラーバジェットが底をつき、リリースができなくなるというリスクを取らないためにテストを多くしたり、リリースを遅くするということもできます。
このように開発チームは、エラーバジェットをできるだけ使いたいですが、使いすぎている場合は、失敗率を減らす試みを行います。SREチームは、失敗率を下げたいので、結果的にエラーバジェットを節約することになります。

エラーバジェットは、信頼性に過剰に向きすぎている観点を柔軟性や開発を早めることへ導くものでもあります。

##まとめ
今回は、エラーバジェットの形成方法とそのメリットについて、学びました。
次回は、今回のエラーバジェットで定められたとした、SLOについて、具体的に学んでいきます。

* エラーバジェットは、SLOと実際の稼働時間の差分であり、リリースや保守への取り組みの判断の指針になる。

### 雑感
* エラーバジェット的な感覚があると、タスクの進め方の参考にもなるなとも思いました。

#### 引用
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　36-38
Apache を Elastic APM の Proxy にする

この記事は、みらい翻訳 Advent Calendar 2020 9日目の記事です。

こんにちは、株式会社みらい翻訳 プラットフォーム部の@kobarasukimaroです。
2回目の登場です。 AWS のことを書こうと思いましたが色々ギリギリすぎて別のネタにしました。ご容赦ください。

## この記事について
Elastic APM の RUM（Real User Monitoring）でブラウザから Elastic Cloud 上の Elastic APM に直接リクエストせず、 Apache を経由してリクエストを投げるのをやってみたので記述します。

## 環境
Apache 2.4
Elastic APM 7.9.2

## 内容
諸事情あって Elastic Cloud 上の Elastic APM に直接リクエストを投げられない状況でした。
さらに [Nginx だと既にやっている方がいたので](https://github.com/michaelhyatt/spring-petclinic-elastic-apm/blob/master/nginx.conf)楽にできそうでしたが、 諸事情あって Apache を使わざるを得ない状況だったので試行錯誤して設定しました。

設定内容としては[こちら](https://github.com/michaelhyatt/spring-petclinic-elastic-apm/blob/master/nginx.conf)の設定を Apache の conf に置き換えたようなものになります。

```
<Location /intake>
  <If "%{REQUEST_METHOD} == 'OPTIONS'">
    Header set Access-Control-Allow-Origin *
    Header set Access-Control-Allow-Methods GET,POST,OPTIONS
    Header set Access-Control-Allow-Headers Accept:,Accept-Encoding,Accept-Language:,Cache-Control,Connection,DNT,Prag
ma,Host,Referer,Upgrade-Insecure-Requests,User-Agent,elastic-apm-traceparent
    Header set Access-Control-Max-Age 1728000
    Header set Access-Control-Allow-Credentials true
    Header set Content-Type 'text/plain; charset=utf-8'
    Header set Content-Length 0
  </If>
</Location>

RewriteEngine on
SSLProxyEngine On

RewriteCond %{REQUEST_METHOD} ^(GET|POST)$
RewriteRule ^/intake(.*)$ https://elastic_apm/intake$1 [P,
L]
ProxyPassReverse / https://elastic_apm/
RequestHeader append Access-Control-Allow-Origin *
RequestHeader append Access-Control-Allow-Credentials true
```

使用しているモジュールとしては以下になります。

- mod_ssl
- mod_proxy
- mod_headers
- mod_rewrite

### 詳細な解説
すみません、時間があるときに追記します😭

## 最後に
Elastic APM に Apache の Proxy 経由でリクエスト投げたいという杞憂な方が居りましたらご活用ください🙇‍♂️

次回は来週 @mitono がスポットインスタンスについて書くそうです！
その前に誰かカレンダーを埋めそうな気もしてます😁
エクセル縛りで整然データからグラフを書く方法：「ピボットテーブルで集計」機能でデータを整形する

tidy dataであるtest.csvから、timeをx軸、valueをy軸にとる折れ線グラフをRやpythonを使わずに作りたい。
想定場面：Rやpythonを使えない学生が、googleフォームで集計した実験データの整理・グラフ描画をする際の指導

test.csv
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549192/6ae89cdb-092a-9667-523d-47db3a1ca13e.png)


### 手順

1.  csvファイルをエクセル形式で保存する
1.  エクセルの「メニューバーからデータ」->「ピポットテーブルで集計」、範囲を選択してOK
1. ピポットテーブルのフィールド（カーソルを合わせると出てくる）において、"列"にx軸としたいtime、"行"やフィルターに分類表記したい属性、"値"にy軸としたいvalueをドラッグアンドドロップで設定する。
1. ピポットテーブルから直接範囲選択してグラフを書こうとすると怒られる（!!?）ので、グラフは一度コピーしてから作成する。


一連の操作の画面キャプチャ↓

![ezgif.com-video-to-gif-3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549192/7f3ec24f-d16a-a6df-d599-5de3df9c1daf.gif)

これならExcelに苦手意識を持っている学生でも出来るはず。
また、GoogleSpreadSheetでもほぼ同様の操作でグラフ作成が可能である。


なおRでは、

```R
df <- read.csv("test.csv")
g <- ggplot(df, aes(x=time, y=value, color=id)) + geom_point() + geom_line() + facet_wrap(.~class) + theme_bw()
g
```
<details>
<summary>プロット結果</summary>
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549192/51c57748-aaae-d49f-5d74-34761f75717c.png)
</details>

などとすればよい。データ行がどんなに長くても基本これでOK、簡単！


[21/12/21 追記]Microsoftのサポートに動画付きの情報がありました．
https://support.microsoft.com/en-us/office/create-a-pivotchart-c1b1e057-6990-4c38-b52b-8255538e7b1c#OfficeVersion=Windows
CentOS 8にNginx 1.18をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してCentOS8にNginx 1.18をインストール
参考：[RHEL8のパッケージ構成 - BaseOSとApplication Stream - 赤帽エンジニアブログ]( https://rheb.hatenablog.com/entry/rhel8_baseos_and_appstream)
　　　[第4章 新機能 Red Hat Enterprise Linux 8 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/8.3_release_notes/new-features#enhancement_dynamic-programming-languages-web-and-database-servers)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux 8 Application Streams Life Cycle - Red Hat Customer Portal](https://access.redhat.com/node/4079021)より、2022-11がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。
なおCentOS Linux 8が2021-12にEOLを迎えるため、それ以降の更新を受けるためにはCentOS Stream8を含めた他ディストリビューションへの移行が必要。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
CentOS Linux release 8.3.2011

# yum module install nginx:1.18
... 略
```

### 各種確認

```shell-session
# which nginx
/usr/sbin/nginx

# nginx -v
nginx version: nginx/1.18.0

# yum module info nginx:1.18
Failed to set locale, defaulting to C.UTF-8
Last metadata expiration check: 0:01:26 ago on Tue Dec  8 11:01:21 2020.
Name             : nginx
Stream           : 1.18 [e] [a]
Version          : 8030020200722172754
Context          : 30b713e6
Architecture     : x86_64
Profiles         : common [d] [i]
Default profiles : common
Repo             : appstream
Summary          : nginx webserver
Description      : nginx 1.18 webserver module
Requires         : platform:[el8]
Artifacts        : nginx-1:1.18.0-2.module_el8.3.0+430+f2605aab.src
                 : nginx-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-all-modules-1:1.18.0-2.module_el8.3.0+430+f2605aab.noarch
                 : nginx-debuginfo-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-debugsource-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-filesystem-1:1.18.0-2.module_el8.3.0+430+f2605aab.noarch
                 : nginx-mod-http-image-filter-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-http-image-filter-debuginfo-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-http-perl-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-http-perl-debuginfo-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-http-xslt-filter-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-http-xslt-filter-debuginfo-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-mail-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-mail-debuginfo-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-stream-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64
                 : nginx-mod-stream-debuginfo-1:1.18.0-2.module_el8.3.0+430+f2605aab.x86_64

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled, [a]ctive
```
Go制約付き高速JSONエンコーダージェネレータ

# 前書き
9月～10月に開催されたISUCON10[^1]で利用しようと思って、ちまちま作ってたJSONのエンコーダです。
ISUCONの練習をISUCON9の予選を使って10万点が出るまで行ったんですが、最後の方はJSONエンコードが処理時間を大きく占めていて、削りたいなと思っていたのと、作ってみると面白そうだなというのでつくってみました。

https://github.com/sapphi-red/json-constantiater

[^1]: http://isucon.net/archives/54704557.html 、チーム「がんもどき」で本選に出場して総合3位を取りました :tada:

ちなみに予選ではそもそもJSONがボトルネックになるところまでたどり着かず、本選ではJSONではなくprotobufだったということで結局一度も使わなかったです。:pensive:

# 制約付き
ところで制約付きっていうのをタイトルに入れてるんですが、ISUCONでしか使わないっていう想定の上で複数の前提を置いた上でつくったためです。
具体的には

- 保守性は問わない
- 生成されたコードが読める
- 一部の仕様にしか対応しない
- 実際は例外がありうる場合でも発生しないという仮定をできるようにする
- コード生成前にコードを多少書き換える必要がある[^3]

[^3]: sliceやmapはそのままでは正常に動かず、`type UserMap map[string]User`のように型をつくる必要があります

などです。
ISUCONの予選が9/12、本選が10/3だったのに9/6につくり始めたのでジェネレータのコードの保守性とか使いやすさとかコーナーケースとかを結構削いでいます…。

# ベンチマーク結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388834/6eb481ae-7f0d-0ab8-7376-f5843f267739.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388834/cfd7dbf3-cfab-4e6b-8c46-64539add6d87.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388834/7f3f7c00-b1b4-177a-b5c8-7d3d3811fd19.png)

下のほうがデータサイズが大きいです。
[ベンチマーク内容](https://github.com/sapphi-red/json-constantiater/tree/master/benchmarks)

## ConstantiateとConstantiateNonOptimizedについて
これらの違いは

> 実際は例外がありうる場合でも発生しないという仮定をできるようにする

この仮定を利用しているかどうかで、Constantiateでは例えばUUIDしか入らないとわかっているフィールドでは文字列のエスケープ処理をせずそのまま文字列コピーするようにしているのに対して、ConstantiateNonOptimizedではエスケープ処理がされています。

このような処理のスキップのオプションを以下の5つ用意しています。

- `noescape`: エスケープをしない
- `omitnano`: `time.Time`のナノ秒を出力しない
- `small`: 0～999であると仮定する
- `unsigned`: 正の数しかとらないと仮定する
- `nonnil`: ポインタ型で`nil`をとらないと仮定する

実際のプロダクトとかでは使えませんが、ISUCONなら仕様が変わらないので強い仮定を置くことができるので、このようなオプションを実装しました。

# 仕組み
[生成されたコード](https://github.com/sapphi-red/json-constantiater/blob/master/benchmarks/large_payload_constantiated.go)を見るとほとんどわかるんですが、書き込む`[]byte`を使いまわしてメモリ確保を減らして、`append`だけで文字列を構築することで命令数を減らすというのが大きな方針です。

このジェネレータは大きく三つの部分、1.コード生成部分、2.コード最適化部分、3.ライブラリ部分からできています。

## コード生成部分
ソースコードのASTを読み込んで構造体やコメントの情報を取り出して、文字列でソースコードを生成しています。

## コード最適化部分

コード生成をした後に一旦ASTで読み出して最適化をかけてます。
この最適化は複数の`append`が並んでいるときに一つの`append`にまとめるような処理をしています。

```go
res = append(res, '{')
res = append(res, `"`...)
// 上が下に変換されます
res = append(res, `{"`...)
```

## ライブラリ部分
生成されるコードで共通の関数が実装されてます。
文字列をエスケープして`append`する関数などがあります。

- `string`で扱うとコピーが多く走ってしまうので`[]byte`で基本扱う(golangでは文字列がimmutableのため)
- 条件分岐よりも`map`のアクセス、さらにそれよりも`slice`のアクセスのほうが速い

あたりの細かい処理の調整とかをしています。

# 終わりに
ちまちまと書いていたらもう12月になっていました…。
ベンチマーク結果だけ見るとよさそうな感じになってはいるんですが、実際に効果が出るかどうかわからないのと、おそらくgo routineの数が増えると十分に性能を発揮できない[^2]ので、改善点はまだまだたくさんあるといった感じですね。
次回ISUCONに出るときにもしかしたらいくつか改善して使ってみるかもしれません。

[^2]: 今のところmutexを効率よく使う実装にしていないため。
CentOS 8にNode.js 14をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してCentOS8にNode.js 14をインストール
参考：[RHEL8のパッケージ構成 - BaseOSとApplication Stream - 赤帽エンジニアブログ]( https://rheb.hatenablog.com/entry/rhel8_baseos_and_appstream)
　　　[第4章 新機能 Red Hat Enterprise Linux 8 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/8.3_release_notes/new-features#enhancement_dynamic-programming-languages-web-and-database-servers)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux 8 Application Streams Life Cycle - Red Hat Customer Portal](https://access.redhat.com/node/4079021)より、2023-04がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。
なおCentOS Linux 8が2021-12にEOLを迎えるため、それ以降の更新を受けるためにはCentOS Stream8を含めた他ディストリビューションへの移行が必要。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
CentOS Linux release 8.3.2011

# yum module install nodejs:14
... 略
```

### 各種確認

```shell-session
# which node
/usr/bin/node

# node -v
v14.11.0

# yum module info nodejs:14
Failed to set locale, defaulting to C.UTF-8
Last metadata expiration check: 0:02:16 ago on Tue Dec  8 10:56:12 2020.
Name             : nodejs
Stream           : 14 [e] [a]
Version          : 8030020200924204355
Context          : 30b713e6
Architecture     : x86_64
Profiles         : common [d] [i], development, minimal, s2i
Default profiles : common
Repo             : appstream
Summary          : Javascript runtime
Description      : Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
Requires         : platform:[el8]
Artifacts        : nodejs-1:14.11.0-1.module_el8.3.0+516+516d0fc0.src
                 : nodejs-1:14.11.0-1.module_el8.3.0+516+516d0fc0.x86_64
                 : nodejs-debuginfo-1:14.11.0-1.module_el8.3.0+516+516d0fc0.x86_64
                 : nodejs-debugsource-1:14.11.0-1.module_el8.3.0+516+516d0fc0.x86_64
                 : nodejs-devel-1:14.11.0-1.module_el8.3.0+516+516d0fc0.x86_64
                 : nodejs-docs-1:14.11.0-1.module_el8.3.0+516+516d0fc0.noarch
                 : nodejs-full-i18n-1:14.11.0-1.module_el8.3.0+516+516d0fc0.x86_64
                 : nodejs-nodemon-0:2.0.3-1.module_el8.3.0+402+6f8dd522.noarch
                 : nodejs-nodemon-0:2.0.3-1.module_el8.3.0+402+6f8dd522.src
                 : nodejs-packaging-0:23-3.module_el8.3.0+402+6f8dd522.noarch
                 : nodejs-packaging-0:23-3.module_el8.3.0+402+6f8dd522.src
                 : npm-1:6.14.8-1.14.11.0.1.module_el8.3.0+516+516d0fc0.x86_64

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled, [a]ctive
```
【CSS】レスポンシブ時に右側に余白ができたときの解消法

#レスポンシブ時に右側に余白ができたときの解消法
はじめての投稿になります！
アプリ開発中に出くわした問題解決時の備忘録がてら、今後ちょいちょい投稿していきます！

```
<body>
 <div class="wrap">
.
.

 </div>
</body>
```
body要素をまるっとwrapクラスで囲って、、

```
.wrap {
overflow: hidden;
}

```
そのwrapクラス、css指定ではみ出した要素をhidden指定するだけです^^
以上！
SeleniumでハマったMaxRetryErrorの解決法

##環境##
<h5><ul>
<li>MacOS : Catalina - 10.15.7
</li>
<li>Python : Python 3.6.8
</li>
<li>Selenium : 3.141.0
</li>
</ul></h5>

##概要##
<p>
業務で、競合他社のGoogle検索順位を調べるバッチ作成をしていたときのお話。<br>
数個の「キーワード」をループでそれぞれ検索して、指定する他社のドメインが出てくるかをチェックするようなバッチだった。
以下、ソースコードに似たコード例を載せる。
</p>
```sample.py
from selenium import webdriver
import chromedriver_binary
from selenium.webdriver.chrome.options import Options

# Chromeに接続して引数で検索する
def search(driver, word):
    driver.get("https://www.google.com")
    search = driver.find_element_by_name('q')
    search.send_keys(word)
    search.submit()
    return driver.page_source

def parse():
    ...省略...
    options = Options()
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-gpu')
    driver = webdriver.Chrome(options=options)

    for kw in keyword:
        # 検索欄にキーワードを入れて検索した後に現れる結果画面のソース
        source = search(driver, kw)
        result = analyze(source)
        ...省略...
```
<p>
キーワードが文字列のリストになっているから、一つずつ取り出して検索をかけて結果を得るって感じのコード。<br>
しかし、実行すると、
</p>

##エラー発生##
```
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=51691):
 Max retries exceeded with url: /session/fd963d7b05fb4b6344e0e8034c73ea67/url
(Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fc4e2773f60>:
Failed to establish a new connection: [Errno 111] Connection refused',))
```
<p>上の例外が吐き出された。</p>
####試したこと####
<ul>
<li><code>urllib3</code>を最新にアップグレード</li>
<li><code>time.sleep(10)</code>で検索の間隔を空けた</li>
</ul>

<p>最初は<code>urllib3</code>のバージョンが悪いのかなと思ったけど違うっぽい</p>

##解決方法##
結局、__「設定したドライバーを検索ごとに再設定」__したらいけた。
どういうことかというと、

```sample.py
def parse():
    ...省略...
    options = Options()
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-gpu')
    driver = webdriver.Chrome(options=options)

    for kw in keyword:
        # 検索欄にキーワードを入れて検索した後に現れる結果画面のソース
        source = search(driver, kw)
        result = analyze(source)
        ...省略...
```

上の<code>options = Options()</code>から<code>driver = webdriver.Chrome(...)</code>のところを、

```sample.py
def parse():
    ...省略...
    for kw in keyword:
        # 検索欄にキーワードを入れて検索した後に現れる結果画面のソース
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-gpu')
        driver = webdriver.Chrome(options=options)
        source = search(driver, kw)
        result = analyze(source)
        ...省略...
```
for文の中に入れて、検索するときはその都度ヘッドレスに設定することにした。

##備考##
<h5><ul>
<li>Selenium のバージョン確認方法
</li>
</ul></h5>
<p>Terminalから　<code>python3</code>　を叩いて、下記を実行する。<br>
この書き方じゃダメなモジュールもある。普通に<code>pip3 list | grep "module name"　</code>の方が簡単かもしれない。</p>
```
>>> import selenium
>>> selenium.__version__
'3.141.0'
```
【Flutter】 環境構築 ~ チュートリアル(随時更新)

※自分とチームのためのメモ

## 環境構築

公式サイト  
[Install | Flutter](https://flutter.dev/docs/get-started/install)

<font color="red">`flutter doctor` でOKが出るまでやる</font>

追加のプラグイン  
- Awesome Flutter Snippets

## とりあえずざっくり日本語ドキュメント手動かして流し見

- [Flutter documentation(公式ドキュメント)](https://flutter.dev/docs)
- [Flutter Doc JP  （日本語だが、古いか？）](https://flutter.ctrnost.com/)
- [Flutterで始めるアプリ開発（これもちょっと古い...）](https://www.flutter-study.dev/)

## パッケージなど

#### ◆状態管理

**グローバルはriverpodでいこう**

- [riverpod](https://pub.dev/packages/riverpod)
- [【Flutter】Providerのほぼ上位互換、Riverpodの基本的な使い方](https://techracho.bpsinc.jp/wingdoor/2020_10_08/97815)
- [【神パッケージ】 Riverpod の使い方【Flutter】](https://note.com/mxiskw/n/n5c06bc2dd0d5#BEm1s)

**hooks**
主にuseState（statefulWidgetの代わり）, useEffect（副作用）など

[flutter_hooks 0.15.0 ](https://pub.dev/packages/flutter_hooks)

#### ◆ディレクトリ構成

とりあえずここを参考にしたがアレンジ。

[File and Folder structure in Flutter](https://medium.com/flutter-community/file-and-folder-structure-in-flutter-967b8be3155e)

## チーム開発 参考

[Githubでチーム開発するためのマニュアル](https://qiita.com/siida36/items/880d92559af9bd245c34)

[GitHubのissueを活用した、個人アプリの開発手順を書いてみた](https://qiita.com/tkmd35/items/9612c03dc60b1c516969)

## コマンド
#### 新規プロジェクト作成

`flutter create --org <com.example> <appName>`
RailsでHTMLファイルを出力する

## やりたいこと
テンプレートに沿ったHTMLファイルを出力したい！

## 前提条件
以下のコマンドでBooksControllerを作成し、その中にHTMLファイルを出力するアクションを作成する。

```ruby
  rails g controller books
```

## テンプレートファイルを作成する
今回は以下のディレクトリを作成し、その中にテンプレートファイルを保存する。
app/views/books/template

``` erb:html_template.html.erb
<!DOCTYPE html>
  <head>
    <meta charset="UTF-8">
    <title>本の詳細</title>
  </head>
  <body>
    <table>
      <tr>
        <th>タイトル</th>
        <td><%= @title %></td>
      </tr>
    </table>
  </body>
</html>
```

## アクションを作成する
以下のようなアクションを作成する。

```ruby:books_controller.rb
  def htmlfile_download
    @title = "本の題名"

    # 指定したファイルの中身を文字列で返す
    # layoutオプションの値をfalseにしておくと、レイアウトが適用されていない状態で取得できる
    template = render_to_string('books/template/html_template', layout: false)

    # HTMLファイルを生成
    send_data(template, filename: "ファイル名.html")
  end
```

以上です。

## おまけ
render_to_stringで取ってきた値は以下のようになっています。

```erb
<!DOCTYPE html>
  <head>
    <meta charset="UTF-8">
    <title>本の詳細</title>
  </head>
  <body>
    <table>
      <tr>
        <th>タイトル</th>
        <td>本の題名</td>
      </tr>
    </table>
</html>
```
Gatsby.js × WordPressでWeb開発を楽しく運営には優しく

JamstackのWeb開発は楽しい！！ライブラリ・フレームワーク開発者にはいつも感謝しています。

ソースコードはローカルで完結するコンパクトさで把握しやすい。ライブリロードで作りながら確認できる。それに、なんといっても成果物のパフォーマンスが高いのがいいですね。速いは正義！

とはいえ、作ったものを使いにくいと思われてしまったら悲しい...。Jamstackを用いつつ、技術に明るくない運営の人にも気持ちよく使ってもらえたらベストではないかと。

## 運営に優しいバックエンドはWordPress

例えば、WordPressとか良いですね。僕も初学者のときからレンサバに簡単インストールして使ってきました。WordPressを選ぶとサイト運営側の学習コストを抑えられることが多いです。

開発側のメリットは「日本語入力に問題がない、CMSの定期的なバックアップと復旧が現実的、サーバーの場所を問わない、帯域幅制限に縛られにくい、GraphQLプラグインが優秀」など。

## 連携しやすいフロントエンドはGatsby.js

選ぶとすればGatsby.js。熱意ある開発者たちによってWordPressとの連携が快適になりました。必須ではありませんが、環境選定の話が都合よく進めば差分ビルドやプレビューも可能でしょう。

ビルド時以外のAPIリクエストを行わないため、WordPressサーバーが弱くても安心。メディアライブラリの画像をインクルードできるようになった点もありがたい。ReactとGraphQLを使って開発します。

## WordPressで開発すること

WordPressには2つのプラグイン（WPGraphQL・WPGatsby）をインストールします。運営の人にはいつも通り投稿・固定ページ制作を行ってもらえばOKです。

- [WPGraphQL – WordPress プラグイン](https://ja.wordpress.org/plugins/wp-graphql/)
- [WPGatsby – WordPress プラグイン](https://ja.wordpress.org/plugins/wp-gatsby/)

※ACFやCPT UIを使っている場合は、追加プラグインが必要

- [WPGraphQL for Advanced Custom Fields | WPGraphQL](https://www.wpgraphql.com/extenstion-plugins/wpgraphql-for-advanced-custom-fields/)
- [WPGraphQL for Custom Post Type UI | WPGraphQL](https://www.wpgraphql.com/extenstion-plugins/wpgraphql-for-custom-post-type-ui/)

### WPGraphQL

![ScreenShot 2020-12-08 3.23.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106505/b3d1810b-2967-3e2d-1cdc-a707a1e63fda.png)

WPGraphQLを有効化するとWordPress内にGraphQLサーバーが立ち上がり、管理画面でデータのプレビューできるようになります。上記スクショでは投稿データが引っ張れていますね。

### WPGatsby

![ScreenShot 2020-12-08 3.27.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106505/e37798ce-2756-99da-1b23-ac008b04f1a8.png)

WPGatsbyを有効化しないと後述する設定のビルドが成功しません。GraphQLに専用の変換を施す、差分チェック、Build Hook設定など、便利な機能がまとまっています。

## Gatsby.jsで開発すること

ローカル環境にNode.jsとgatsby-cliをインストールしておいて、スターターを使うと楽です。

```shell
$ gatsby new my-wordpress-gatsby-site https://github.com/gatsbyjs/gatsby-starter-wordpress-blog
$ cd ./my-wordpress-gatsby-site
$ gatsby develop
```

![ScreenShot 2020-12-08 18.05.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106505/5ac09ef9-ef25-7e7c-fddc-59b8cf3c00be.png)

Gatsby.jsのサイトが立ち上がりました。スターターの設定がデフォルトの状態だと、デモ用のWordPressからデータを取得するため、エラーも出ずに成功します。

### プロジェクトのデータを取得する

データの取得先は `gatsby-config.js` に書かれています。直書き修正もできますが、Gatsby.jsはdotenvが入っているので、`.env` ファイルを作成して上書きすることもできます。

```env:.env
WPGRAPHQL_URL="[プロジェクトWordPressのURL]/graphql"
```

```gatsby-config.js
// dotenvの利用を上部に追加
require("dotenv").config()
```

![ScreenShot 2020-12-08 18.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106505/46e536ec-e1cf-768d-9fcd-2ade6fc1bc35.png)

Gatsby.jsのサイトを立ち上げ直すと、プロジェクトの投稿データに差し代わります。スターターは投稿一覧と投稿ページのみ用意されているので、複製して固定ページやカスタム投稿を作っていきます。

### 自動ビルド・デプロイ先の設定

簡単なのはNetlifyやVercelにGitHubリポジトリを紐づけてドメイン当てるとかですが、デプロイ先が決まっている場合はCircleCIなどを使ってビルド→デプロイします。

## あとがき

これで、運営の人には馴染みあるWordPressでコンテンツを作ってもらいつつ、JamstackでWeb開発する基本の仕組みが整いました。成果物の爆速サイトを共に楽しみましょう！

## 資料

- [gatsbyjs/gatsby-source-wordpress-experimental](https://github.com/gatsbyjs/gatsby-source-wordpress-experimental)
- [GraphQL API for WordPress | WPGraphQL](https://www.wpgraphql.com/)
WSL2

## インストール

* [ディストリビューションの手動ダウンロード](https://docs.microsoft.com/ja-jp/windows/wsl/install-manual)
    * (ubuntu 20.04 は wsl1 では動作に難がある様子。)

### WSLの設定

* `c:\Users\<ユーザ名>\.wslconfig`
    * [Linux ディストリビューションの管理 | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/wsl/wsl-config#configure-global-options-with-wslconfig)

```sh:.wslconfig
# 外部から接続許可
localhostForwarding=True

[wsl2]
memory=2GB
```

### Windows の機能の有効化または無効化

* PowerShell 起動 (管理者として実行)

```sh
# WSLの有効化 (wslコマンドに必要)
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

# Virtual Machine Platform の有効化
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all
```

* [WSL2を入れたらVirtualBoxのゲストOSが途中でフリーズ
](https://www.lancard.com/blog/2020/10/12/wsl2/)

```sh:Hyper-V
# WSL2を入れたらVirtualBoxのゲストOSが途中でフリーズする場合は、Hyper-VをOFFにするとWSL1で利用ができる。

# Hyper-V をインストール (wsl2に必要)
dism.exe /Online /Enable-Feature /All /FeatureName:Microsoft-Hyper-V

# OFFにする (OS再起動が必要。Virtualboxが起動しない場合はこちら。)
bcdedit /set hypervisorlaunchtype off

# ONにする
bcdedit /set hypervisorlaunchtype auto
```

### x64 マシン用 WSL2 Linux カーネル更新プログラム パッケージ

* http://aka.ms/wsl2kernelmsix64

### WSL2を使用

```sh
wsl --set-default-version 2
```

### ディストリビューションの手動ダウンロード

* https://docs.microsoft.com/ja-jp/windows/wsl/install-manual
    * `Ubuntu 20.04` をダウンロード。
    * インポート `Add-AppxPackage Ubuntu*.appx`
    * スタートメニューから起動

![ubuntu.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/1b149cf4-6e28-5e6d-596f-5695458bc83f.png)


----

## 利用

### 起動方法

```dosbatch
rem Ubuntu-20.04 をデフォルト指定
wsl -s Ubuntu-20.04

rem 起動
wsl
```

### ファイル

* windowsからアクセス
    * `\\wsl$`
* Linuxからアクセス
    * `/mnt/c`

### 日本語

```sh
sudo -s

# ロケール
apt install -y locales
sudo locale-gen ja_JP.UTF-8
update-locale LANG=ja_JP.UTF-8
```

* WSL2を再度起動し、日本語になったことを確認。

### dockerのインストール

```sh:docker-install.sh
apt remove -y \
  docker \
  docker-engine \
  docker.io \
  containerd \
  runc

apt install -y \
 apt-transport-https \
 ca-certificates  \
 curl \
 gnupg-agent \
 software-properties-common \
 iptables

update-alternatives --set iptables /usr/sbin/iptables-legacy
/sbin/iptables --version

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
apt-key fingerprint 0EBFCD88
add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
 $(lsb_release -cs) \
 stable"

apt update
apt install -y \
 docker-ce \
 docker-ce-cli \
 containerd.io \
 docker-compose

service docker start
docker ps -a
docker run --rm hello-world
```

----

## エクスポート/インポート

```sh
# 一覧
wsl --list

# 停止 ( .wslconfig を変更した後は都度必要。 )
wsl --shutdown Ubuntu-20.04

# export
wsl --export Ubuntu-20.04 Ubuntu.tar

# 登録の削除
wsl --unregister Ubuntu-20.04

# インポート
wsl --import Ubuntu-20.04 Ubuntu.tar
```
あったらいいなフロントエンド開発の時に

この記事は...

- フロントエンド開発する時にあったら良いなを言語化してみた
- 所謂デザインシステムを拡張したものに近い感じになった
- あくまで理想なので同期的にすべて揃えることは不可能だけど、共通認識としてあると「開発に何が足りないか」考えるヒントになるかも
- ん、というか自分がWeb作る時に考えていることに近いのか...？

## 💡  サービス・プロダクトの概念・原則

- プロダクトの性質を定義
    - サービスなどとして稼働する時にユーザーに伝わるもの・期待値（UXともいう）
        - 開発時に一貫して気にしたい
        - KGI・KPI
            - 数値化されていない素朴なものでもいいので、なんのために作って、どうなったら成功なのかを知ってかないと、なにを作っているのかわからなくなりがち
        - MVP
            - なぜこのサービスがほしいのか
            - なぜこの機能、施策がほしいのか
        - SEO 要件
            - Web でやる以上はターゲットをある程度は決めておきたいよね
        - 挙げてたらキリがなくなりそう...
    - 実装自体に直接関係はしないものもあるが大事
        - プロダクトの開発で困った時の灯台の様なもの
            - 個人開発でもこういうコンセプト考えておくとものは作りやすい

## 🎨 スタイルガイド

- プロダクトのスタイルを定義
    - CSS 設計で効いてくる
        - スタイルガイドがしっかりしていれば設計・実装コストは下がる
            - ここが薄いと実装する人間の裁量で品質に差が出る
                - こういうときにデザインやったことないとしんどいかも
            - あったら嬉しい
                - 色
                    - 配色パターンもあると尚よし
                - タイポグラフィ
                - 余白
                    - Vertical Rhythm とかあると良いよね
                - アンチパターン
            - 「あったら嬉しい」が定義されていれば大方変数化（AltCSS 使用前提）が可能

## 📱 コンポーネントライブラリ

- UI を任意の観点で切り出したものの定義
    - UIを持つプロダクトのコミュニケーションツールとして機能したい
    - UI 設計であったほうがよい
        - ただ静的なものの定義だけではなく、ユーザーのアクションに合わせた状態（過程）が定義されていると良い
            - モーションまで定義されていると最高かも
        - 目に見えている所以外の定義（状態の管理）なども定義されていると嬉しい
        - 場合によっては Storybook など実装ベースで定義できると良いよね
        - ここが固まっているとUIライブラリの選定や状態管理の設計のイメージが湧きやすい
        - a11y も含めて考慮できると最近の傾向からすると良いよね

## 📶 URI

- URI一覧
- 必要なクエリの定義
    - コンポーネントライブラリやページ単位で紐付けたい
        - URI・クエリ <=> 状態管理 は相関関係のケースが多い

## 🗝 認証・認可

- 必要な場合ね
- 認証
    - JWT とかはどうでもよくて、FEはどちらかというと認証情報を永続化するための方針を決めたい
        - Cooki？ LocalStrage？ ここらへんが議論の的になるのかな
        - 最近は BFF経由でセキュア対応した Cookie 操作が安牌？
    - ページによっては認証情報がいらないケースもあるので、そこも分かってくるといいよね
- 認可
    - URI * 認可*n のパターンでどれだけUIの表出に変化があるか、状態管理に制限がでるか知りたい

## 🛠 API I/F

- Swagger など OpenAPI の定義があると嬉しい
    - 型情報に基づいた I/O の議論がしたい
    - Mock 書くのが面倒なのでローカルで叩けるものがあると嬉しみ倍増

## 🗺 インフラ周りの論理構成図

- あったら嬉しいというか早めに方針決めたい
    - 何故？
        - デプロイフローが次に決められる
        - プロキシが入る場合アプリケーション側のURIの定義に色付が必要だったりする
        - 開発環境を整備しやすくなる
            - Docker 周りの定義や Docker-compose 使うのとか

## 🌝 夜も眠れない問題

- ある程度決まっていたほうが行動に移せるサブセットを纏めてみる
    - UI設計・実装
        - スタイルガイド
        - コンポーネントライブラリ
        - URI・クエリ
        - 認証・認可
    - 状態管理
        - コンポーネントライブラリ
        - URI・クエリ
        - 認証・認可
        - その他メタ的に必要な永続情報（Cookie などで管理するもの）
    - 技術選定
        - アプリケーションとインフラは切り離して非同期で考えられると良いよね
            - アプリケーション
            - インフラ
                - ただ、Next.js/Vercel など一気通貫で考えたほうが良いケースもかなり出てきたのであくまでケースバイケースで


## 🤔 何を持って仕様なのか

- 今回はデザイン・エンジニア視点の単語で書き出してみた
    - 所謂ビジネスロジック的なものは各所に分散されているという感じになると思う
        - こう「仕様」というものを言語化するのは実は難しいかもしれない
パケットキャプチャ 5 キャプチャサイズ検証

ツールからDBへの1接続で生成されたpcapサイズを検証

キャプチャ構文
＃ループバックIF指定

```
dumpcap.exe -w C:\tmp\capture.pcap -i 2 -f "port ポート番号"
```

- 処理
  - DB接続
  - 日付を出力するだけのselect文を流してexit
- 上記を10回ループ
- キャプチャされたパケット数 970
- サイズ
  - サイズ 5.65 MB 
  - ディスク上のサイズ 5.65 MB ＃サイズと同じ

10接続で5.65MB
100接続で56.5MB
1000接続で565MB

selectで返されるデータ量を増やしてみる

- 処理
    - DB接続
    - DB上の全オブジェクト情報 (オブジェクト名や種類や作成時刻などのメタデータ) をselectするSQLを流してexit
        - 26カラム, 22086レコードが返される
        - 実行時間23秒
- ループなし1回のみ
- キャプチャされたパケット数 5998
- サイズ
  - サイズ 1.7MB
  - ディスク上のサイズ ＃同上

データ多い方を基準にしようかな ..

1接続で1.7MB
10接続で17MB
100接続で170MB
1000接続で1.7GB
けっこうやな..

うーん、select文だと結果の量に応じてキャプチャされるパケットも多くなる
DMLなら結果として返ってくるのは成功失敗とかだからキャプチャ量は小さい

~~ああ、-a (自動停止) オプションで指定サイズに達したら自動終了かければいいのか~~
~~プラス、ファイルサイズでのローテーションもしておけば (-b filesize:xxKB)、~~
~~指定した以上にディスク容量食わないし、サイズで分割されたファイルで解析できる~~

-a/-bを併用できなかった
-aの制限サイズを超えて、-bだけ効いて無限にローテーションされてく
＃以下は3MB制限かけたが1MBローテだけ効いて4個以上ファイルが作成されてくところ

```
c:\Program Files\Wireshark>dumpcap.exe -w C:\tmp\capture.pcap -i 2 -f "port 1521" -a filesize:3072 -b filesize:1024
Capturing on 'Adapter for loopback traffic capture'
File: C:\tmp\capture_00001_20201208203145.pcap
Packets: 3382 File: C:\tmp\capture_00002_20201208203201.pcap
Packets: 6812 File: C:\tmp\capture_00003_20201208203213.pcap
Packets: 10228 File: C:\tmp\capture_00004_20201208203228.pcap
Packets: 13594 File: C:\tmp\capture_00005_20201208203240.pcap
Packets: 17039 File: C:\tmp\capture_00006_20201208203252.pcap
Packets: 20452 File: C:\tmp\capture_00007_20201208203305.pcap
Packets: 23832 File: C:\tmp\capture_00008_20201208203317.pcap
Packets: 27224 File: C:\tmp\capture_00009_20201208203330.pcap
Packets: 30660 File: C:\tmp\capture_00010_20201208203343.pcap
Packets captured: 31194
Packets received/dropped on interface 'Adapter for loopback traffic capture': 31194/0 (pcap:0/dumpcap:0/flushed:0/ps_ifdrop:0) (100.0%)
```

-aか-bのどちらかしか効かないとなると、-b優先しかない
GB級のpcapなんてWireSSharkで読み込めないしバイナリデータだから単純なファイル分割も無理なはず
本番環境でどのくらいのサイズになるかは、解析するためにファイルサイズ分割はかけて、1時間とかの期間決めて別コンソールからtaskkillするしかないか

キャプチャ中に別コンソールでtaskkill検証
＃強制終了オプションが必要

```
C:\tmp>taskkill /im dumpcap.exe
エラー: プロセス "dumpcap.exe" (PID 3500) を強制終了できませんでした。
理由: この処理は、/F オプションのみで強制終了できます。

C:\tmp>taskkill /f /im dumpcap.exe
成功: プロセス "dumpcap.exe" (PID 3500) は強制終了されました。

C:\tmp>
```

強制終了時に出力先だったpcapでもWireSharkで普通に解析できた
seabornで複数のグラフを重ねてプロットする


seabornのcatplotを使った時に複数のグラフを重ねるやり方がすぐ分からなかったのでメモしておく
ついでにcatplotを使わない場合もメモ


## 実行環境

jupyter notebook
python 3.8
seaborn version 0.11.0



## catplotを使わずにグラフを重ねる方法

まずcatplotを使わずにシンプルに重ねる方法

```python
sns.boxplot(data=df, x=metrics, y='Group', orient='h', color='white')
sns.swarmplot(data=df, x=metrics, y='Group', orient='h', hue='Classification', size=pointsize, palette='Set2')
```

これはそのままグラフを描くコードを別々に書けば良い．

jupyterではこれで複数のグラフを重ねられる．（グラフの形状が似たようなものの場合）

今回は**boxplot**と**swarmplot**を重ねている．

jupyterでグラフを書き，`plt.savefig('hoge.png')`で保存すると以下のようになる．

![casp14_gdtts_loss_group_boxplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401124/ca7d3ecc-18f9-aa16-e3b6-8233f6e1b3a9.png)


グラフを重ねることには成功．

しかしjupyterでは正しくグラフが表示されているが，そのまま保存するとlabelが見切れてしまった状態の画像が保存される．

これを直すためには

```python
sns.boxplot(data=df, x=metrics, y='Group', orient='h', color='white')
sns.swarmplot(data=df, x=metrics, y='Group', orient='h', hue='Classification', size=pointsize, palette='Set2')
plt.tight_layout()
plt.savefig('hoge.png')
```

のように保存する前に`plt.tight_layout`を使うか，

```python
sns.boxplot(data=df, x=metrics, y='Group', orient='h', color='white')
sns.swarmplot(data=df, x=metrics, y='Group', orient='h', hue='Classification', size=pointsize, palette='Set2')
plt.savefig('hoge.png', bbox_inches='tight')
```

のように保存する時に`bbox_inches='tight'`を渡すと以下のようにグラフ全体を保存することができる．

![casp14_gdtts_loss_group_boxplot_tight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401124/cb55c5ed-48bc-d70a-21e4-0c69f0b6469f.png)


このように見切れていないグラフの画像を保存することができた．



## catplotでグラフを重ねる方法

catplotを使って画像を保存したい場合，以下のように`catplot`を2つ書くと2つのグラフが生成されてしまう．

```python
sns.catplot(data=df, x=metrics, y='Group', orient='h', hue='Classification', size=8, kind='swarm')
sns.catplot(data=df, x=metrics, y='Group', orient='h', color='white', kind='box')
```



catplotでグラフを重ねたいときは以下のようにする．

```python
g = sns.catplot(data=df, x=metrics, y='Group', orient='h', hue='Classification', size=8, kind='swarm')
g.map(sns.boxplot, data=df, x=metrics, y='Group', orient='h', color='white')
```

まず1行目は普通にcatplotで良い．

この時に返り値を受け取っておく．(ここではgとしている．seaborn.FaceGridが返ってくる)

続いて返り値（seaborn.FaceGrid）に重ねたいグラフをmapする．

例えばboxplotを重ねたいとき

```python
sns.boxplot(data=df, x=metrics, y='Group', orient='h', color='white')
```

普通に書く場合は上記の書き方となるが，catplotに重ねる場合は

```
g.map(sns.boxplot, data=df, x=metrics, y='Group', orient='h', color='white')
```

のように第一引数に重ねたいグラフの名前（ここでは`sns.boxplot`），それ以降の引数にはグラフを書く時に引数として与えたい引数(ここでは`data=df, x=metrics, y='Group', orient='h', color='white'`)を渡す．

このようにするとcatplotを重ねることができた．

catplotで作成した画像は以下のようになった．

![casp14_gdtts_loss_group_boxplot_catplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401124/9ab987ae-74f9-c218-d557-9ea4cf51e8b2.png)


## 参考
seaborn公式ドキュメント
https://seaborn.pydata.org/generated/seaborn.FacetGrid.html#seaborn.FacetGrid
WEB版Twitterの右カラムがうざいのでChrome拡張で消す

WEB版twitterの右カラムにはトレンドとともに、見たくない（既にブロック・ミュート済）メディアの記事も登場する。見るのもしんどい上、目につくのも嫌なので全部消してやることにした。

#準備するもの

基本的に拡張機能用のフォルダを作り、
manifest.json
と実働ファイル
script.js
を空のファイルで配置しておく。

手間をかけたくないのでJqueryを使うので、予めダウンロードしておく。

```manifest.json
{
    "manifest_version": 2,
    "name": "HideTwitterSidebar",
    "version": "1",
    "content_scripts": [
        {
            "matches": ["https://twitter.com/*"],
            "js": ["jquery-3.min.js","script.js"]
        }
    ]
}
```

長々書くのは面倒なのでシンプルに行こう。

```script.js
$('.r-1hycxz').hide();

```

あとはChromeの拡張機能管理から「パッケージ化されていない拡張機能を読み込む」でフォルダを選択しておしまい。
Postgresql利用中セッションを強制切断する

## エラー

```
postgres=> drop database testdb;
ERROR:  database "testdb" is being accessed by other users
DETAIL:  There is 1 other session using the database.
```

## 接続しているユーザーを確認

```
select pid,usename from pg_stat_activity;
```

## セッションを強制切断

```
select pg_terminate_backend(2645) from pg_stat_activity where usename='postgres';
```