web-technical-blog

web開発に関する技術メモ

vagrantのshared folderのmountに失敗してしまった場合

VirtualBoxディレクトリ共有を行うために使っているVirtualboxGuestAdditionというツールのバージョンが, ホストとゲストでずれているとこのような問題がおこるらしい

$ vagrant plugin install vagrant-vbguest
$ vagrant vbguest

https://qiita.com/ak-ymst/items/bdc37aaf53f857d37fcc

vagrant reloadコマンドから起動しないと、 共有フォルダは設定されない

rootかvboxsfグループのユーザーしかアクセスできないため、 既存ユーザーをvboxsfグループに追加しておく。有効にするため一度再起動したら、 共有できるようになっているはず。 単に共有さえできればいいならここまでで設定は終わり。

# gpasswd -a vagrant vboxsf
# reboot

共有フォルダの設定

https://qiita.com/centipede/items/5b3cb4965618993cefec

pythonでS3にgzip形式でPUTする

PythonでS3にgzip形式でPUTする際は以下のようにすればいける。

Python 2.7.5

import boto3
from boto3.session import Session

buff = '111,222,333'

# output csv
session = Session(aws_access_key_id=your_access_key_id,
                    aws_secret_access_key=your_secret_access_key',
                 )

bucket = "your-bucket"
key = "{}.csv.gz".format("yyyy-mm-dd")

io = StringIO()
with GzipFile(fileobj=io, mode='wb') as f:
    f.write(buff)

body = io.getvalue()
s3 = session.resource('s3')
s3.Bucket(bucket).put_object(Key=key, Body=body, ACL='public-read', ContentEncoding='gzip')

Lambdaの呼び出し元について

LambdaFunctionには2つの呼び出し元がある

  1. ストリームベース
  2. ストリームベースではない
1.ストリームベース
2.上記以外はストリームベースではない呼び出し

ストリームベースではないイベントソースからの呼び出しは2種類がある

  • 同期呼び出し
    • AWS CLIや各SDKにてLambda関数をInvokeした場合(デフォルト動作)
    • API Gateway(デフォルト動作)※参考AWS Lambda 関数の API GatewayAPI を作成する
    • Cognito
    • Alexa
    • Lex
  • 非同期呼び出し(非同期のLambdaFunctionでエラーが発生した場合、自動的に間隔をあけて2回再試行される)
    • AWS CLIや各SDKにてInvocationType=EventでInvokeした場合
    • API Gateway(ヘッダでEvent指定時)※参考AWS Lambda 関数の API GatewayAPI を作成する
    • AWS IoT
    • CloudWatch Events(スケージュル含む全てのトリガー)
    • CloudWatch Logs
    • CodeCommit
    • S3
    • SNS
    • SES
    • CloudWawtch Logs
    • KinesisFirehose
    • CloudFormation(Lambdaを利用したカスタムリソース)
    • CodeCommit
    • AWS Config

www.h4a.jp dev.classmethod.jp

Gitのコミットメッセージの書き方

Gitへコミットする際にあまり意識しなかったので勉強になった。

qiita.com

▼基本規則
1行目:変更内容の要約(タイトル、概要)
2行目 :空行
3行目以降:変更した理由(内容、詳細)
▼スリーライン派(コミットベース派)
[fix]削除フラグが更新されない不具合の修正

refs #110 更新SQLの対象カラムに削除フラグが含まれていなかったため追加しました。
▼ワンライン派(チケット駆動派)
[fix]refs #110 削除フラグが更新されない不具合の修正

更新SQLの対象カラムに削除フラグが含まれていなかったため追加しました。

コミット種別(通常版)

  • fix:バグ修正
  • hotfix:クリティカルなバグ修正
  • add:新規(ファイル)機能追加
  • update:機能修正(バグではない)
  • change:仕様変更
  • clean:整理(リファクタリング等)
  • disable:無効化(コメントアウト等)
  • remove:削除(ファイル)
  • upgrade:バージョンアップ
  • revert:変更取り消し

コミット種別(ライト版)

  • fix:バグ修正
  • add:新規(ファイル)機能追加
  • update:機能修正(バグではない)
  • remove:削除(ファイル)

DeNAのデータ分析基盤

logmi.jp

  • Hadoopクラスタの運用は大変そうです。。
  • アナリスト側にYAML定義を理解してもらうのが大変なのは分かる。。

App -> LogGateway

  • LogGatewayで認証したサービスのログを受け取る
    • Log
      • Fluentd
    • DB SnapShot
      • オンプレの場合はApache Sqoopというもので収集

Hadoop

  • データレイクとして使用
    • HiveQL使用者のためにHue提供していたり
  • サービスごとに、分けて異なるHDFSパスへ

HDFS -> Vertica or BIgQuery

  • 内製のバルクロードツール「Medjed」を使用
    • EmbulkとEmbulkを管理するWebアプリケーション
    • アナリスト職やビジネス職の方にとっては、YAMLを理解していただくというハードルがある
    • ハードルを解消するために、Googleスプレッドシートに定義してもらうとYAMLが実行時に生成されるというような仕組みを持っている
    • Googleスプレッドシートベースではあるがスキーマ管理が行えるようになる

ダッシュボード

  • 柔軟な対応ができる内製ダッシュボード「Argus」を使用
  • クエリエンジン
  • 細かな要望に素早く対応できる
  • 社内に合わせた細かな権限管理を行える
  • ActiveDirectoryのグループに合わせた管理・編集・閲覧それぞれの権限を付与できる
  • 権限管理やグルーピングなどのかゆいところに手が届くのがポイント

ジョブスケジューラー

  • ジョブスケジューラーはJenkinsを使用
    • アナリストの方が慣れていたり、使いやすいというのが使い続けている理由
    • いろんなことができてしまう
    • 権限管理もプラグインを入れるとかなり柔軟に対応できる
  • Jenkinsで完結しない業務のために、LinuxのWorkstationも提供している
    • 普通のLinuxサーバーで、アナリストの方がSSHでログインして使用している

Software Design(7月号)のDevOpsの掲載

「DevOps」とは

  • Dev(Development:開発)
  • Ops(Operation:運用/保守) をくっつけた造語

開発担当と運用/保守担当が密に情報共有し、共通の目的に向けて互いの理解を深め

  • リリースサイクルの短縮
  • システムの安定稼働
  • ひいてはビジネスへの貢献をするために継続的に取り組むこと を言う

2009年にO'Reilly主催のVelocityというイベントで発表された資料から「DevOps」という言葉が生まれた

6つの重要なポイント

(1)インフラストラクチャ構築の自動化 従来は手作業で行っていたインフラストラクチャー構築や変更作業をコードで定義し、自動化すること Dockerfile,Terraform,Ansible

(2)バージョン管理 開発者と運用者で、共通のバージョン管理システムを使用する Git,Subversion

(3)ビルドやデプロイの自動化 繰り返し行う定型作業は、手順書など使い手動で実行するのではなく、自動化する

(4)フィーチャー(機能)フラグ運用 フィーチャートグルとも言う 開発した新しい機能にフラグをつけておき、一部のユーザーにだけ試してほしいときに活用する

(5)指標(メトリクス)の共有と評価 ダッシュボードなどで、指標の結果をプロジェクトの各ステークホルダと共有し、評価することが必要

(6)通知ボット ビルドやデプロイ、新しいバージョン、バグ報告など共有するために、ボットを用いて通知を自動化する

組織の文化を作り上げるための4つの心がまえがを唱えている

(1)互いに尊敬する

(2)互いに信頼する

(3)互いに仕事を任せ合う

(4)相手を非難しない

Twitterのタイムラインのスクレイピング

pip install twitterpastcrawler  # twitterページをクロールするライブラリ
pip install requests            # HTTPライブラリ
pip install beautifulsoup4      # スクレイピング処理に必要
pip install wordcloud           # タグクラウドを生成できるライブラリ
pip install pillow              # 画像処理ライブラリ
pip install matplotlib          # グラフ描画ライブラリ
pip install janome              # 内部で辞書を持っているので、Mecabをインストールする必要がない
  • 注意点
    • pipでインストールした「twitterpastcrawler」を修正が必要かもしれない
      • useragent_windows.datファイルのUA(ユーザーエージェント)は新しいものに書き換える必要あり
Mozilla/5.0 (compatible; U; ABrowse 0.6; Syllable) AppleWebKit/420+ (KHTML, like Gecko)CLR 3.0.30729; Media Center PC 6.0)
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100402 Prism/1.0b4.NET CLR 3.0.30729; Media Center PC 6.0; Zune 4.0; InfoPath.3; MS-RTC LM 8; .NET4.0C; .NET4.0E; Maxthon 2.0)2.0.50727; Media Center PC 6.0; Maxthon 2.0)
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2a2pre) Gecko/20090908 Ubuntu/9.04 (jaunty) Namoroka/3.6a2pre GTB5 (.NET CLR
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2a1) Gecko/20090806 Namoroka/3.6a1
Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.9.2.3) Gecko/20100403 Namoroka/3.6.3
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.1) Gecko/20061204
Mozilla/5.0 (Macintosh; U; Intel Mac OS X; nl-NL; rv:1.8.1.3) Gecko/20080722
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.1) Gecko/2008070206
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-au; rv:1.9.0.1) Gecko/2008070206
  • 変更した場合でもエラーする可能性はある
  • crawler.py
    • 170行目付近
      • windows環境だとJSONのデコード処理でエラーするので
##with open(crawler.output_file, "at") as f:
with open(crawler.output_file, "at", encoding='utf-8') as f: ← 書き換える(utf-8)にする
  • 234行目付近
    • csvファイルを書き出し後に継続して処理したい場合はsys.exit(1)だと処理が終了してしまうので、returnに変更する
if self.last_min_pos is not None:
    if not connection_cut and min_pos == self.last_min_pos:
        print("Starting to loop! Exitting with status:")
        self.dump()
        return
        ##sys.exit(1)
import csv
from janome.tokenizer import Tokenizer
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from collections import defaultdict
import twitterpastcrawler
import os

hash_tag = '#DMC体験版'
output_file = '#DMC体験版.csv'

# crawel
crawel = twitterpastcrawler.TwitterCrawler(
    query=hash_tag,
    output_file=output_file,
    max_depth=10
)
crawel.crawl()

# 名詞だけ抽出、単語をカウント
def counter(texts):
    t = Tokenizer()
    # = Tokenizer("user_simpledic.csv", udic_type="simpledic", udic_enc="utf8")
    #t = Tokenizer("userdic.csv",udic_enc="utf8")
    words_count = defaultdict(int)
    words = []
    for text in texts:
        tokens = t.tokenize(text)
        for token in tokens:
            # 品詞から名詞だけ抽出
            if token.part_of_speech.split(',')[0] == '名詞':
                words_count[token.base_form] += 1
                words.append(token.base_form)
    return words_count, words

with open(output_file,'r',encoding='utf_8') as f:
    reader = csv.DictReader(f, delimiter=',')
    texts = []
    for row in reader:
        texts.append(row['text'])

words_count, words = counter(texts)
text = ' '.join(words)

# wordcloudオブジェクトの生成
# font指定
if os.name == 'nt':
    font_path='C:\Windows\Fonts\HGRSGU.TTC'
else:
    font_path = '/System/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc'

# 画像に出したくない単語リスト(本当はもっと色々)
stop_words = ['なる', 'ある', 'いる', 'する', 'ない', 'れる', 'ため', 'こと', 'もの', 'さん', 'これ', 'ここ']

wordcloud = WordCloud(background_color="white",
                      font_path=font_path,
                      collocations = False, # 複合語のオプションをオフ
                      stopwords = set(stop_words),
                      width=900,
                      height=500).generate(text)

# 1文字を表示させたい場合
##wordcloud = WordCloud(background_color="white",font_path=font_path,regexp=r"\w+").generate(text)

# グラフ出力
##plt.figure(figsize=(15,12))
plt.imshow(wordcloud,interpolation='bilinear')
plt.imshow(wordcloud)
plt.axis("off")
plt.show()