質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.55%

GAE, python3, google cloud datastore のチュートリアルコードのサービスの動作について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 539

big_naminami

score 9

前提

↓のチュートリアルをこなしていました。GAE、python3, cloud datastore を使っている公式チュートリアルです。
https://cloud.google.com/appengine/docs/standard/python3/building-app/storing-and-retrieving-data

解決したい疑問

ローカルで動かしたら正常に動作するにもかかわらず、GAEにデプロイ後のサービスが正常に動作せず困っております。

チュートリアルの内容を簡単に言うと
・サイトにきたユーザーのアクセス時間を記録し、cloud datastoreに貯めていく(ユーザー識別しない状態)
・貯めたdatastoreから、最新のアクセス時間10個を画面のhtmlに埋め込み、表示させる

です。

ローカルで動かしたとき(python3 main.py)は予想した通りに正常に動きました。

しかし、GAEにデプロイしたとき、予想した通りに動きませんでした。
デプロイはエラー無く出来たのですが、GAEのappにアクセスしてもcloud datastore にアクセス時間を保存できていません。
(GCPのコンソール→cloud datastoreのエンティティから確認済み)
そのため、ページの表示も更新されない状況となっています。
なぜ、cloud datastore がデプロイ後だと、保存できないのでしょうか。

何か情報お持ちの方、アドバイス頂けませんでしょうか。

*ローカルで動かしたとき(ページリロードにそって、正しく動作している)
イメージ説明aaaaaaaaaaaa

*デプロイしたサービスを動かしたとき(ページリロードしているのに正しく動作できていない)
イメージ説明

以下にチュートリアルのコードをそのまま記載いたします。
・app.yaml

runtime: python37

handlers:
  # This configures Google App Engine to serve the files in the app's static
  # directory.
- url: /static
  static_dir: static

  # This handler routes all requests not caught above to your main app. It is
  # required when static routes are defined, but can be omitted (along with
  # the entire handlers section) when there are no static files defined.
- url: /.*
  script: auto

・main.py

# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import datetime

from flask import Flask, render_template

# [START gae_python37_datastore_store_and_fetch_times]
from google.cloud import datastore

datastore_client = datastore.Client()

# [END gae_python37_datastore_store_and_fetch_times]
app = Flask(__name__)


# [START gae_python37_datastore_store_and_fetch_times]
def store_time(dt):
    entity = datastore.Entity(key=datastore_client.key('visit'))
    entity.update({
        'timestamp': dt
    })

    datastore_client.put(entity)


def fetch_times(limit):
    query = datastore_client.query(kind='visit')
    query.order = ['-timestamp']

    times = query.fetch(limit=limit)

    return times
# [END gae_python37_datastore_store_and_fetch_times]


# [START gae_python37_datastore_render_times]
@app.route('/')
def root():
    # Store the current access time in Datastore.
    store_time(datetime.datetime.now())

    # Fetch the most recent 10 access times from Datastore.
    times = fetch_times(10)
    print("this is %s" % type(times))

    return render_template(
        'index.html', times=times)
# [END gae_python37_datastore_render_times]


if __name__ == '__main__':
    # This is used when running locally only. When deploying to Google App
    # Engine, a webserver process such as Gunicorn will serve the app. This
    # can be configured by adding an `entrypoint` to app.yaml.

    # Flask's development server will automatically serve static files in
    # the "static" directory. See:
    # http://flask.pocoo.org/docs/1.0/quickstart/#static-files. Once deployed,
    # App Engine itself will serve those files as configured in app.yaml.
    app.run(host='127.0.0.1', port=8080, debug=True)

・requirement.txt

Flask==1.0.2
google-cloud-datastore==1.7.3

・index.html

<!doctype html>
<html>
<head>
  <title>Datastore and Firebase Auth Example</title>
  <script src="{{ url_for('static', filename='script.js') }}"></script>
  <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>

  <h1>Datastore and Firebase Auth Example</h1>
  <!-- [START gae_python37_datastore_print_times] -->
  <h2>Last 10 visits</h2>
  {% for time in times %}
    <p>{{ time['timestamp'] }}</p>
  {% endfor %}
  <!-- [END gae_python37_datastore_print_times] -->
</body>
</html>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mistn

    2019/05/02 20:49 編集

    gcloud app logs readというコマンドがありました。これはどうでしょうか。
    https://cloud.google.com/sdk/gcloud/reference/app/logs/read

    キャンセル

  • big_naminami

    2019/05/03 02:29 編集

    コメントありがとうございます!
    解決いたしました!
    datastoreで保存していたtimestampの時刻情報の保存方法が原因でした。

    なぜかは分からないですが、今の日本時刻をUTCとしてdatastoreに保存してしまっていたようです(正解は日本時間をJSTで保存です。いつの間にかJSTで保存が出来ていました)。
    JST=UTC+9時間なので、JST時間をUTCで保存してしまうと、未来の時刻データとして保存されてしまいます。
    そして、Webページでは直近の時刻データ10個を取ってくるという処理を行っています。
    つまり、表示する10個の時刻データが誤って保存されてしまった未来の時刻データで埋まってしまって
    あたかも更新されていないように表示されていた、という結論でした。
    (datastoreをよく見ると、中途半端に真ん中あたりにデータが挿入されていました。)

    データ保存は成功していたので、gcloud app logs read 試してみましたが結局エラーは出ず、
    stackdriver logging を試してみてもエラーは出ませんでした。
    (偶然ですが、私が調べた限りでは、gcloud app logs readとstackdriver logging は
    内容では同じっぽい感じでした。情報共有まで。)

    誠にありがとうございました!

    キャンセル

  • mistn

    2019/05/03 09:25

    GAEのリージョンが海外だとタイムゾーンが日本じゃなくなってたのかもしれませんね。
    ともかく解決できたようでよかったです。

    キャンセル

回答 1

check解決した方法

+1

datastoreで保存していたtimestampの時刻情報の保存方法が原因でした。

なぜかは分からないですが、今の日本時刻をUTCとしてdatastoreに保存してしまっていたようです(正解は日本時間をJSTで保存です。いつの間にかJSTで保存が出来ていました)。
JST=UTC+9時間なので、JST時間をUTCで保存してしまうと、未来の時刻データとして保存されてしまいます。
そして、Webページでは直近の時刻データ10個を取ってくるという処理を行っています。
つまり、表示する10個の時刻データが誤って保存されてしまった未来の時刻データで埋まってしまって
あたかも更新されていないように表示されていた、という結論でした。
(datastoreをよく見ると、中途半端に真ん中あたりにデータが挿入されていました。)

データ保存は成功していたので、gcloud app logs read 試してみましたが結局エラーは出ず、
stackdriver logging を試してみてもエラーは出ませんでした。
(偶然ですが、私が調べた限りでは、gcloud app logs readとstackdriver logging は
内容では同じっぽい感じでした。情報共有まで。)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる