paranitips

Never stop learning! がモットーのゆるふわエンジニアブログ

iOSショートカットでちょっとしたライフハックをしてる話

f:id:paranishian:20181024100856p:plain

iOS12から登場したショートカットをつくるのが楽しすぎて時間が溶ける・・・🤤
自分は最近Google Mapを使うことが多いので、そのときに使えるショートカットをつくりました。

iCloudの共有リンクも置いてるので良ければ使ってみてください🙌

※ショートカットAppはプリインストールではないのでAppStoreからインストールする必要があります
ショートカットの使い方はこの記事が詳しいです👇
iOS 12で「ショートカット」アプリを使ってみよう:iPhone Tips - Engadget 日本版

お店の他の口コミを調べる

Google Mapでお店を見つけて、
Google以外の他のサイトの口コミも見てみたいなー🧐」
そんなときに使います。

Google Mapで、
共有 > ショートカット > 〇〇で調べる
で検索できます。

f:id:paranishian:20181023112237g:plain

ページを直接開くショートカットも作ってみたのですが、速度がなんとも遅かったのでシンプルにGoogle検索するだけにしました💡

バス停の場所を調べる

例えば渋谷駅。
「乗り換え案内でバス経由で表示されてもバス停の場所がわからん。。。🤮」
そんなときに使います。

f:id:paranishian:20181023112219g:plain

バス停の場所を調べる

ウィジェットからワンタップで

ウィジェットに表示するとさらに捗る。
いまんとここの2つを重宝してます😎 f:id:paranishian:20181023191202p:plain

目覚ましをセットする 嫁にLINE電話する
f:id:paranishian:20181023185520j:plain f:id:paranishian:20181023185525p:plain

LINE電話をショートカットに表示するには、まず一度LINEで電話すればショートカットAppに表示されるようになります👌

もっといろいろ種類が出てくるとおもしろいなぁ〜。

おしまい🤗

nginx.confを8万行削除した話

f:id:paranishian:20181010192436p:plain

強い気持ちでやりました😇

自分が関わる前からあったnginx.conf。

それはそれは大きく膨らんでおりました🐷

デプロイはchefで行っていたんですが、dry-runでも時間がかかりすぎて差分確認するのも一苦労、、という状態😢

少しでも快適な開発環境にすべく、やっていき!💪

TL;DR

大したことはやってなくて、アクセスログと照らし合わせて地道に削除していっただけなのであしからず🙇

削除の方針

nginx.confの中身を見ると、ほとんどがもはや機能しているかわからないリダイレクトのコードだったので、今回はそれらを削除していくことにしました。

今は使っていないURLでもどこかのブログやサイトで昔のURLが残っていることがあります 🤔💦

ただ、そのURLをどこまで面倒見るの?って話で、今回はプロダクトオーナーと相談して、

「直近3ヶ月でアクセス数がxxに満たない場合はSEO的にも価値がないので削除する」

という方針にしました。
(特に意味はないけど一応数字を伏せておいた😇)

アクセスログの保存と解析

サイトへのアクセスはすべてALBを経由してnginxに流れているので、ALBのアクセスログを見ていきます。

という流れでアクセスログデータを取得します。

ALBのアクセスログをS3に格納する

アクセスログのS3への格納作業自体はポチポチするだけで完了します👌
Application Load Balancer のアクセスログ - Elastic Load Balancing

(この作業を3ヶ月以上前にやってたので、現時点ですでにログデータがたまった状態です)

Athenaの連携とデータ取得

Athenaはこのへんのドキュメントとサイトを参考にしました👇

では、さっそくテーブルを作成していきます。

あらかじめパーティション(今回はdtにした)を設定して作成します。

CREATE EXTERNAL TABLE IF NOT EXISTS alb_logs (
    type string,
    time string,
    elb string,
    client_ip string,
    client_port int,
    target_ip string,
    target_port int,
    request_processing_time double,
    target_processing_time double,
    response_processing_time double,
    elb_status_code string,
    target_status_code string,
    received_bytes bigint,
    sent_bytes bigint,
    request_verb string,
    request_url string,
    request_proto string,
    user_agent string,
    ssl_cipher string,
    ssl_protocol string,
    target_group_arn string,
    trace_id string,
    domain_name string,
    chosen_cert_arn string,
    matched_rule_priority string,
    request_creation_time string,
    actions_executed string,
    redirect_url string,
    new_field string
    )
    PARTITIONED BY (dt string)
    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
    WITH SERDEPROPERTIES (
    'serialization.format' = '1',
    'input.regex' = 
'([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) ([^ ]*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\"($| \"[^ ]*\")(.*)')
    LOCATION 's3://<your-alb-logs-directory>/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<region>';

(locationの<>部分はよしなに変更してください。)

Athenaでは各クエリでスキャンされるデータ量に基づいて課金されるので、対象を絞るためにパーティションつくっておきます。
今回は直近3ヶ月のデータだけで十分だったので手動でパーティションを作りました。
(なのでパーティションの自動化も今回はしていません)

ALTER TABLE alb_logs ADD
  PARTITION (dt='2018-07') LOCATION 's3://<your-alb-logs-directory>/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<region>/2018/07'
  PARTITION (dt='2018-08') LOCATION 's3://<your-alb-logs-directory>/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<region>/2018/08'
  PARTITION (dt='2018-09') LOCATION 's3://<your-alb-logs-directory>/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<region>/2018/09'

パーティションの確認

show partitions alb_logs

リクエストの取得

パーティションを指定してデータ取得します。

SELECT count(*) AS request_count,
         request_url
FROM alb_logs
WHERE dt >= '2018-07'
        AND dt <= '2018-09'
GROUP BY  request_url
ORDER BY  request_count DESC

結果ファイルをcsvでダウンロードすると、以下のようなデータが確認できます。

"request_count","request_url"
"12345","https://sample.com:443/path/to/hoge"
"10000","https://sample.com:443/path/to/fuga"
"8000","http://sample.com:80/path/to/piyo"
...

あとは、grepsedなどのコマンドを駆使してリクエスト数を確認し、nginx.confと照らし合わせて削除していくだけです。(つらそう😇)

例えば、ポート番号が邪魔なのでこんなことをしてパスだけ確認したりとか。

egrep ':\d+\/path\/to\/' results.csv | sed -E "s/http.+:(443|80)\//\//g"

今回はじめてawksedを使いましたが、まだまだ使いこなせてない感😪

気の遠くなるような作業かと思いましたが、意外とトップレベルで削除できるものが多かったのでなんとかなりました。
(たとえば /path/to/hogegrepで引っかからなかったら/path/to/hoge/1/path/to/hoge/2など、配下のURLに関するコードも一気に削除できるよね、みたいな。)

地道な削除作業が完了し、QAを経て無事リリースできました🎉

リリース後は特に障害も起きず、chefでのデプロイもスムーズになったので頑張った甲斐がありました。よかった。

幸せに開発するためには自分で環境を変えて行かなあかんのや!という強い気持ち。

以上です🤗

技術書典で買った「さわって学べる!iOSテスト駆動開発」を読んだのでその感想と3章の誤植の共有

今年の技術書典ではboothでiOS中心に10冊ほど買いました。

今回読んだ本はこれ👇

shindyu.booth.pm

swiftでテストを書いたことがなかったので、TDDを勉強するというよりは、その書き方や導入が把握できればいいかなー、と思って読んでみました。
結果、とてもわかりやすく体系的に学べたので無事テストを書いていけそうです。
これで1,000円とは、お買い得な世の中ですね🤗

TDDをやっていて一つ気になったのが、
「プロパティや関数名をまだ宣言してないのでコード補完が効かなくてつらい問題」
特にtableviewまわりはメソッド名長すぎてtypoがつらい😢

こういうのってどうしてんだろうなーと思って友人のエンジニアに聞いてみたら、

まずは「tableviewがあること」みたいなテストを書いてプロパティつくっていくかなー。 そのテストが通ってればtableviewのコード補完も効くしね。

と言われて、なるほど!!と思った💡

その他メモ

  • Dependency Injectionの中にはConstructor InjectionとSetter Injectionなるものがある
  • 初耳のアーキテクチャがあった
    • MVP, VIPER
  • 既存アプリにTDDを導入する手順は参考になった
    • ビルド時間の計測
      • BuildTimeAnalyzerはそのうち使ってみる
    • Carthageへの移行
    • Embedded Frameworkの利用
    • CIの導入
      • CircleCIは経験済みなのでbitrise使ってみる

3章の誤植の共有

3章は実際にアプリをつくっていく流れだったので、理解のために写経しました。
途中でビルドやテストが通らなくて困ったので、「こうやったら進行できたよ」という共有です。
同じように写経する人の参考になれば😉


p.38 ファイル名が間違っている

ArticleListViewControllerTests.swiftArticleListViewController.swift

p.39 宣言文が間違っていてテストが通らない

// この部分を
let vc ArticleListViewController()

// こう書き換える
let article = Article(title: "記事タイトル")
let client = FakeArticleListAPIClient(fakeResponse: [article])
let vc = ArticleListViewController(client: client)

p.41 itemsの初期化をしていないのでビルドが通らない

// この部分を
var items: [Article]

// こう書き換える
var items: [Article] = []

p.42 tableviewにcellを登録してないので落ちる

// この一行をviewDidLoadに追加する
tableView.register(ArticleListCell.self, forCellReuseIdentifier: "ArticleListCell")

p.45 moduleをimportしてないのでテストできない

// ArticleListViewControllerTests.swiftに追加する
import SafariServices

以上です。
swiftやってくぞ!💪