newrelic-installで、/bin or /usr/bin

newrelicをinstallしようとすると、/binと/bin/usrどちらにインストールするか質問がきます。一体何が違うのでしょうか?

$ sudo newrelic-install install

Below is a list of the directories in which we found a copy of PHP.
Please select the directory or directories for which you wish to install
New Relic. You can select either a single directory or
multiple directories by separating each choice with either a space or a
comma. To select all of the directories shown, please enter the special
keyword 'all' (without the quotes).

   1)   /bin
   2)   /usr/bin

ls -lで見てみると、どちらのディレクトリも同じファイルのように見える
$ pwd
/usr/bin
$ ls -l
-rwxr-xr-x 1 root root 5094784 11月 1 04:35 php

$ pwd
/bin
$ ls -l
-rwxr-xr-x 1 root root 5094784 11月 1 04:35 php

### /bin
– Linuxの基本コマンドが登録されている
– 基本的かつ非常時に利用するコマンド

### /usr/bin
– 一般ユーザが使うコマンド
– 緊急時のシステム保守に必須ではないコマンド

性質からいうと、/usr/binで良いか。

New Relicとは?

公式(英語): https://www.newrelic.com/
公式(日本語): https://newrelic.co.jp/
創業者 Lew Cirne: 元apple、NewRelicの前にTech会社企業、harverd・Stanfordなどで教鞭
概要: アプリケーションパフォーマンス監視。Saas。アプリの表示速度などを測定できる。高可用性状態でアプリケーションをスケールさせる。
競合: Dynatrace, AppDynamics, Data Dogなど
導入企業: GE, Adobe, Airbnb
日本の導入: Sansan, Cygames, CA, Mercariなど

### New Relicの仕組み
エージェントをインストールし、それがデータを収集してNew Relicのサーバに送信する(1分に1回)
-> Mackerelと仕組みは同じ?
対象: Browser, Mobile, Synthetics, Application(APM), Infrastructure

### New Relic APM
– アプリケーションのパフォーマンス監視(処理時間、スループット、エラー率、ユーザ満足度)
– 遅い順、スループットの多い順
– トランザクション毎ではSQLまで確認可
– 外部サービスパフォーマンス
– 言語処理パフォーマンス
– エラー分析、デプロイ追跡、サービスマップ、ヘルスマップ

PHP agent compatibility and requirements
PHP agent installation overview
release note

### New Relic Browser
– DOM, レンダリング、ネットワーク、サーバーサイド処理
– 遅いページのパフォーマンスを測定
– Chrome DevToolのNetworkタブのような機能
– JSをHTMLに埋め込む。APMを使用している場合は、自動
-> GAと同じ仕組みか?

### New Relic Synthetics
– 死活監視
– URLに対しリクエストを送る。HTTP Head, HTTP Get
-> AWSでいうHealth checkのようなものか?

### New Relic Mobile
– iOS, Androidのパフォーマンス監視
– SDKを各環境に埋め込み、ストアで公開

### New Relic Infrastructure
– サーバ監視
– ホスト単位のCPU、 メモリ、ロードアベレージ
– ストレージ
– ネットワーク送信量、受信料
– プロセスごとのパフォーマンス
– インフラのイベント履歴
– IT資産の管理
– クラウド、ミドルウェア監視
-> サーバ監視はAWSの場合、CloudWatchで見れるから、どれくらい有用かは不明

こう見ると、ベンダー各社のトラッキングサービスを1社ほとんどカバーしているという事か? 
それを実現できる技術力は素晴らしい。

Vue.jsでtinymce-vueを使ってv-modelをaxiosでpost

問題:TinyMCEのTextareaをVue.jsのv-modelで取得してaxiosでpostしようとしたが上手くいかない。
->TinyMCEでVue.jsを使えるようにできるパッケージ[tinymce-vue]があるらしい

まず、Vue.jsでのtinymce-vueの使い方のテスト。

$ npm install –dev @tinymce/tinymce-vue

/node_modules/@tinymce/tinymce-vue/lib/browser/tinymce-vue.min.js
の 「tinymce-vue.min.js」を任意の場所(tinymce-vue/)に移動

tinymce-vue.min.jsを読み込んで、後はTinyMCEのQuick Guideの通りに書いてみる。

    <h1>TinyMCEテスト</h1>
    <form method="post" action="confirm.php">
    <div id="app">
        <editor
          api-key="no-api-key"
          :init="{
            heigt: 500,
            menubar: false,
            plugins: &#91;
               'advlist autolink lists link image charmap print preview anchor',
               'searchreplace visualblocks code fullscreen',
               'insertdatetime media table paste code help wordcount'
             &#93;,
             toolbar:
               'undo redo | formatselect | bold italic backcolor | \
               alignleft aligncenter alignright alignjustify | \
               bullist numlist outdent indent | removeformat | help'
          }"
          :other_options="other_options"
          v-model="message"
        />
    </div>
    <input type="submit" value="送信">
    </form>
<script src="tinymce-vue/tinymce-vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
    el: '#app',
    components: {
        'editor': Editor
        
    },
    data: {
        message: 'hello!',
        other_options: {
            language_url: 'tinymce-vue/ja.js'
        }
    },
})
</script>

あれ? v-modelは上手くいってる? other_optionsでlanguage_urlを指定しているけど、これは上手くいってない??

あ、optionではなく、:initの方に書いたらlanguage_urlもできた。

<editor
          api-key="no-api-key"
          :init="{
            heigt: 500,
            menubar: false,
            language: 'ja',
            language_url: 'js/tinymce/langs/ja.js',
            plugins: &#91;
               'advlist autolink lists link image charmap print preview anchor',
               'searchreplace visualblocks code fullscreen',
               'insertdatetime media table paste code help wordcount'
             &#93;,
             toolbar:
               'undo redo | formatselect | bold italic backcolor | \
               alignleft aligncenter alignright alignjustify | \
               bullist numlist outdent indent | removeformat | help',
            
          }"
          v-model="message"
        />

これを実装してテスト
VueでTinyMCE使えないとなり一瞬諦めかけましたが、一つ一つ公式のチュートリアル、Githubからクリアーしていくと、意外と簡単に行けました。
やっぱり入力フォームに絵文字がないとね🙋‍♂️

Vue.jsでTinyMCEを使いたい

– TinyMCEのTextareaをVue.jsのv-modelで取得してaxiosでpostしようとしたが上手くいかない。
– TinyMCEでVue.jsを使えるようにできるパッケージがあるらしい。

Official: tinymce-vue
Get started: TinyMCE Vue.js integration quick start guide
Reference: TinyMCE Vue Technical Reference
Demo: Controlled input

quick start guideに沿ってやっていきます。
$ npm -v
6.13.4
$ sudo npm install -g @vue/cli
$ vue create –default tinymce-vue-demo
$ cd tinymce-vue-demo
$ npm install –save @tinymce/tinymce-vue

// Vueがインストールされたか挙動確認
$ npm run serve
http://192.168.33.10:8080/

//公式通りに書いていきます。
src/App.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <editor
      api-key="no-api-key"
      :init="{
        heigt: 500,
        menubar: false,
        plugins: &#91;
           'advlist autolink lists link image charmap print preview anchor',
           'searchreplace visualblocks code fullscreen',
           'insertdatetime media table paste code help wordcount'
         &#93;,
         toolbar:
           'undo redo | formatselect | bold italic backcolor | \
           alignleft aligncenter alignright alignjustify | \
           bullist numlist outdent indent | removeformat | help'
      }"
    />
  </div>
</template>

<script>
import Editor from '@tinymce/tinymce-vue'

export default {
  name: 'app',
  components: {
    'editor': Editor
  }
}
</script>

なんとなく行けそうなのはわかった。

さて、これをどうやって実装するかだな。。

TinyMCE5.xでtoolbarをbottomに変更する方法

<script>
        tinymce.init({
            //省略
            toolbar_location : "bottom",
        });
</script>

これこれ。結構探した。

https://github.com/tinymce/tinymce/issues/4618#issuecomment-586529196

TinyMCE 5.2.0 was released to the community earlier this week, which added a new toolbar_location setting that can be used to set where the toolbar should be rendered. The valid values are 'top' (default) or 'bottom'. Here's a fiddle to show how to use the new setting/feature: http://fiddle.tinymce.com/8bhaab/1.

There is one issue we're aware of with the new feature when opening an inline dialog (eg search and replace) when sticky toolbars is also enabled. We'll include a fix for that in a future release. Please let us know if you have any further issues.

TinyMCE5.2.1を使おう

1. self-hostedよりjsファイル群をdownloadする
https://www.tiny.cloud/get-tiny/self-hosted/
2. 日本語をダウンロード
https://www.tiny.cloud/get-tiny/language-packages/
-> ja.jsをtinymce/langs配下に配置する
3. Tool Control
https://www.tiny.cloud/docs/advanced/editor-control-identifiers/#toolbarcontrols

– デフォルトでpタグが入るので、forced_root_blockをnullにする
– 必要最低限

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TinyMCE</title>
    <script src="js/tinymce/tinymce.min.js"></script>
    <script>
        tinymce.init({
            selector: "#tiny",
            language: "ja",
            menubar: false,
            plugins: "emoticons",
            toolbar: "bold italic underline strikethrough emoticons",
            forced_root_block : '',
            statusbar: false,
        });
    </script>
</head>
<body>
    <h1>TinyMCEテスト</h1>
    <form method="post" action="confirm.php">
    <textarea id="tiny" name="input"></textarea>
    <input type="submit" value="送信">
    </form>
</body>
</html>

emoticonsが前より大量に増えていて感動した。

Laravel 7.xでslackに通知したい

Incomming Webhookをセットアップして、ターミナルから挙動確認します。

curl -X POST --data-urlencode "payload={\"channel\": \"#hpscript\", \"username\": \"webhookbot\", \"text\": \"これは webhookbot という名のボットから #general に投稿されています。\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/hogeL/hogehoge

curlでslackの#hpscriptのチャネルに投稿されていることを確認できます。

### 1.env設定

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/hogeL/hogehoge

### 2.guzzlehttp/guzzle、slack-notification-channelインストール
$ php composer.phar require guzzlehttp/guzzle
$ php composer.phar require laravel/slack-notification-channel

### 3. Notification作成
$ php artisan make:notification Slack

app/Notifications/Slack.php

use Illuminate\Notifications\Messages\SlackMessage;
class Slack extends Notification
{
    use Queueable;
    protected $content;

    public function __construct($message)
    {
        $this->content = $message;
    }

    public function via($notifiable)
    {
        return ['slack'];
    }

    public function toSlack($notifiable)
    {
        return (new SlackMessage)
            ->from('hpscript', ':bomb:')
            ->to('#general')
            ->content($this->content);
    }

    public function toArray($notifiable)
    {
        return [
        ];
    }
}

app/User.php

public function routeNotificationForSlack($notification){
        return env('SLACK_WEBHOOK_URL');
    }

### 4.slack通知コマンド作成
$ php artisan make:command SendSlackCommand
app/Console/Commands/SendSlackCommand.php

use App\User;
use App\Notifications\Slack;
class SendSlackCommand extends Command
{
    protected $signature = 'slack:send {message}';

    protected $description = 'Send Slack Notification';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        $user = new User();
        $user->notify(new Slack($this->argument('message')));
    }
}

### 5.実行
$ php artisan slack:send ‘slack通知のテストです’
-> Slackの#generalのチャネルで挙動確認

コントローラで使いたい場合

use App\Notifications\Slack;
use App\User;

public function index(Request $request)
    {
        //
        $user = Auth::user();
        $user->notify(new Slack($user->name.'さんがログインしました'));
        return view('subscriber.index', compact('user'));
    }

※メモ
– Notifications/Slack.phpのconstructorでenv()は使えない
– slack-notification-channelは、laravel/frameworkと分離してインストールされるがインストール場所が変わっても名前空間は同じため、使い方は同じ

想像以上に手こずりました。

TravisCI + CodeDeployでデプロイする

TravisCI + CodeDeployのフロー

【High Level】
– Merge Pull Request on master
– Travis Builds project automatically / run tests
– Travis uploads zipped project up to S3
– Travis then tells AWS Code Deploy to deploy to EC2 instance

【Index】
1. Pre-Setup
2. Policy For Server
3. Policy For Travis CI
4. Creating Travis User in IAM
5. Role for EC2 Instance
6. Role for Code Deploy Application
7. Create EC2 Instance
8. Create EC2 Tag
9. Create S3 Bucket
10. Setup Code Deploy
11. Project Setup
12. Setting Up Travis User Credentials on Travis
13. Code Deploy Agent Setup

### 1. IAMでEC2のPolicy作成
Policies -> Create Policy
Name: CodeDeployDemo-EC2-Permissions
Description: CodeDeployDemo-EC2-Permissions

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:Get*",
                "s3:List*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

-> このポリシーによって、EC2がS3からデータを持ってこれる

### 2. IAMでTravisCI、CodeDeployの為のPolicy作成
1.TravisがS3にアップロード
Travis-Deploy-To-S3

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

2.CodeDeployがEC2にデプロイ
Travis-Code-Deploy-Policy
※AccIdHEREはAWSの数字のID
※NameOfTheCodeDeployApplicationNameHEREはCodeDeployのapplication name
※ServerRegionHEREはap-northeast-1

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:RegisterApplicationRevision",
                "codedeploy:GetApplicationRevision"
            ],
            "Resource": [
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:application:NameOfTheCodeDeployApplicationNameHERE"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:CreateDeployment",
                "codedeploy:GetDeployment"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:GetDeploymentConfig"
            ],
            "Resource": [
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:deploymentconfig:CodeDeployDefault.OneAtATime",
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:deploymentconfig:CodeDeployDefault.HalfAtATime",
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:deploymentconfig:CodeDeployDefault.AllAtOnce"
            ]
        }
    ]
}

### 3. IAMでTravisユーザ作成
UserName: Travis
access type: Programmatic access
Set permissions: 上記で作成したTravis-Deploy-To-S3、Travis-Code-Deploy-Policy
->作成後、accesskey、secretkeyを保存

### 4. EC2のロール作成
Create role -> AWS service EC2
Permissions:CodeDeployDemo-EC2-Permissions
Role Name: CodeDeploy_EC2_DEPLOY_INSTANCE

### 5. CodeDeployアプリの為のロール作成
Create role -> CodeDeploy
Permissions: AWSCodeDeployRole
Role Name: CodeDeployServiceRole

### 6. EC2 launch
Amazon Linux 2 AMI (HVM), SSD Volume Type 64x t2.nano 8GiB GP2
Auto-assign Public IP: enable
IAM role: CodeDeploy_EC2_DEPLOY_INSTANCE
Tag: Name travisci

### 7. S3バケット作成
create bucket -> demo-travis-s3

### 8. CodeDeploy作成
Create application -> application nameはIAMのTravis-Code-Deploy-Policyで設定したname
platform: EC2/On-premises

Create Deployment Group -> Deployment Group Name : TravisCodeDeployDemoDeploymentGroup(何でもOK)
Envrionment Configuration -> Amazon EC2 -> 6で作成したtagを選択(Name travisci)
CodeDeployDefault.AllAtOnce

### 9. travis.yml

language: php
php:
  - 7.3

services:
  - mysql

before_script:
  - cp .env.travis .env
  - mysql -e 'create database test;'
  - composer self-update
  - composer install
  - chmod -R 777 storage

script: 
  - ./vendor/bin/phpunit

deploy:
  - provider: s3
    access_key_id: $AWS_ACCESS_KEY
    secret_access_key: $AWS_SECRET_KEY
    local_dir: dpl_cd_upload
    skip_cleanup: true
    on: &2
      repo: hoge/hogehoge
    bucket: demo-travis-s3
    region: ap-northeast-1
  - provider: codedeploy
    access_key_id: $AWS_ACCESS_KEY
    secret_access_key: $AWS_SECRET_KEY
    bucket: demo-travis-s3
    key: latest.zip
    bundle_type: zip
    application: travisci
    deployment_group: TravisCodeDeployDemoDeploymentGroup
    region: ap-northeast-1
    on: *2

script:
  - zip -r latest *
  - mkdir -p dpl_cd_upload
  - mv latest.zip dpl_cd_upload/latest.zip

### 10.Travis側でcrudentialの登録
Environment Variables
– AWS_ACCESS_KEY, AWS_SECRET_KEYを入力

### 11. EC2にCodeDeployインストール
$ sudo yum update
$ sudo yum install ruby
$ sudo yum install aws-cli
$ aws s3 cp s3://aws-codedeploy-ap-northeast-1/latest/install . –region ap-northeast-1
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent status
$ sudo yum info codedeploy-agent

### 12. appspec.yml

version: 0.0
os: linux
files:
  - source: ./
    destination: /home/test/travisci

### 13. git push & deploy
$ git push -u origin master

### 14. travisci
-> passed
-> Done. Your build exited with 0.

### 15. EC2で動作確認
$ cd /home/test/travisci
$ ls
README.md artisan composer.lock database phpunit.xml routes tests
app bootstrap composer.phar package-lock.json public server.php vendor
appspec.yml composer.json config package.json resources storage webpack.mix.js

– 所感
circleCIはデプロイのjob実装に一日かかりましたが、Travisは多少IAMの設定に時間がかかりましたが、デプロイは一発で上手くいきました。
Gitpullではなく、CodeDeployでデプロイできるので、AWSとはTravisの方が相性が良さそう。
ただ、unitテストはmasterへのpushではなく、ブランチのリポジトリへのpushのタイミングの方が良さそう。

TravisCIにDBのテストを追加する

.travis.yml

language: php
php:
  - 7.3

services:
  - mysql

before_script:
  - cp .env.travis .env
  - mysql -e 'create database test;'
  - composer self-update
  - composer install
  - chmod -R 777 storage

script: 
  - ./vendor/bin/phpunit

notifications:
  emails:
    - hoge@gmail.com

config.database.php

'testing' => [
            'driver' => 'mysql',
            'host' => env('DB_TEST_HOST', 'localhost'),
            'database' => env('DB_TEST_DATABASE', 'test'),
            'username' => env('DB_TEST_USERNAME', 'homestead'),
            'password' => env('DB_TEST_PASSWORD', 'secret'),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => false,
        ],

.env.travis

APP_ENV=testing
APP_KEY=base64:****

DB_CONNECTION=testing
DB_TEST_USERNAME=root
DB_TEST_PASSWORD=

CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=sync