Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2

ВсСм ΠΏΡ€ΠΈΠ²Π΅Ρ‚. ДСлимся ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠΌ Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ части ΡΡ‚Π°Ρ‚ΡŒΠΈ, ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½Π½ΠΎΠΉ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ для студСнтов курса Β«Data EngineerΒ». Π‘ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ Ρ‚ΡƒΡ‚.

Apache Beam ΠΈ DataFlow для ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ΠΎΠ² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2

Настройка Google Cloud

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Для запуска ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ Π»ΠΎΠ³Π° я использовал Google Cloud Shell, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρƒ мСня Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с запуском ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π° Π½Π° Python 3. Google Cloud Shell ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Python 2, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π»ΡƒΡ‡ΡˆΠ΅ согласуСтся с Apache Beam.

Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΊΠΎΠΏΠ°Ρ‚ΡŒΡΡ Π² настройках. Π’Π΅ΠΌ ΠΈΠ· вас, ΠΊΡ‚ΠΎ Ρ€Π°Π½ΡŒΡˆΠ΅ Π½Π΅ пользовался GCP, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ 6 шагов, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹Ρ… Π½Π° этой страницС.

ПослС этого Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ наши скрипты Π² ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Google ΠΈ ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… Π² Π½Π°ΡˆΡƒ Google Cloud Shel. Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Π² ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ достаточно Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»ΡŒΠ½Π° (описаниС ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ здСсь). Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ наши Ρ„Π°ΠΉΠ»Ρ‹, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ Google Cloud Shel ΠΈΠ· ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов, Ρ‰Π΅Π»ΠΊΠ½ΡƒΠ² ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π·Π½Π°Ρ‡ΠΎΠΊ слСва Π½Π° рисункС 2 Π½ΠΈΠΆΠ΅.

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2
Рисунок 2

ΠšΠΎΠΌΠ°Π½Π΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π°ΠΌ Π½ΡƒΠΆΠ½Ρ‹ для копирования Ρ„Π°ΠΉΠ»ΠΎΠ² ΠΈ установки Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ, пСрСчислСны Π½ΠΈΠΆΠ΅.

# Copy file from cloud storage
gsutil cp gs://<YOUR-BUCKET>/ * .
sudo pip install apache-beam[gcp] oauth2client==3.0.0
sudo pip install -U pip
sudo pip install Faker==1.0.2
# Environment variables
BUCKET=<YOUR-BUCKET>
PROJECT=<YOUR-PROJECT>

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ нашСй Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹

ПослС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΡ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΠ»ΠΈ всС шаги, связанныС с настройкой, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, это ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½Π°Π±ΠΎΡ€ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π² BigQuery. Π•ΡΡ‚ΡŒ нСсколько способов ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это, Π½ΠΎ самый простой β€” ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ консоль Google Cloud, сначала создав Π½Π°Π±ΠΎΡ€ Π΄Π°Π½Π½Ρ‹Ρ…. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ дСйствия, ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ссылкС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ со схСмой. Наша Ρ‚Π°Π±Π»ΠΈΡ†Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ 7 столбцов, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ Π»ΠΎΠ³Π°. Для удобства ΠΌΡ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ всС столбцы ΠΊΠ°ΠΊ строки (Ρ‚ΠΈΠΏ string), Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ timelocal, ΠΈ Π½Π°Π·ΠΎΠ²Π΅ΠΌ ΠΈΡ… Π² соотвСтствии с ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ сгСнСрировали Ρ€Π°Π½Π΅Π΅. Π‘Ρ…Π΅ΠΌΠ° нашСй Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Π° Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΠΊΠ°ΠΊ Π½Π° рисункС 3.

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2
Рисунок 3. Π‘Ρ…Π΅ΠΌΠ° Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹

ΠŸΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΡ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ Π»ΠΎΠ³Π°

Pub/Sub являСтся критичСски Π²Π°ΠΆΠ½Ρ‹ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠΌ нашСго ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ позволяСт нСскольким нСзависимым прилоТСниям Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ. Π’ частности, ΠΎΠ½ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΊΠ°ΠΊ посрСдник, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ Π½Π°ΠΌ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ сообщСния ΠΌΠ΅ΠΆΠ΄Ρƒ прилоТСниями. ΠŸΠ΅Ρ€Π²ΠΎΠ΅, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, это ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Ρ‚Π΅ΠΌΡƒ (topic). Достаточно просто ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π² Pub/Sub Π² консоли ΠΈ Π½Π°ΠΆΠ°Ρ‚ΡŒ CREATE TOPIC.

ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π½ΠΈΠΆΠ΅ ΠΊΠΎΠ΄ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ наш скрипт для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Π»ΠΎΠ³Π°, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… Π²Ρ‹ΡˆΠ΅, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΈ отправляСт ΠΆΡƒΡ€Π½Π°Π»Ρ‹ Π² Pub/Sub. ЕдинствСнноС, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, β€” это ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ PublisherClient, ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΏΡƒΡ‚ΡŒ ΠΊ Ρ‚Π΅ΠΌΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° topic_path ΠΈ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ publish с topic_path ΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ generate_log_line ΠΈΠ· нашСго скрипта stream_logs, поэтому ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ эти Ρ„Π°ΠΉΠ»Ρ‹ находятся Π² ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠ°ΠΏΠΊΠ΅, ΠΈΠ½Π°Ρ‡Π΅ Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΈΠΌΠΏΠΎΡ€Ρ‚Π°. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ это Ρ‡Π΅Ρ€Π΅Π· Π½Π°ΡˆΡƒ google-консоль, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ:

python publish.py

from stream_logs import generate_log_line
import logging
from google.cloud import pubsub_v1
import random
import time


PROJECT_ID="user-logs-237110"
TOPIC = "userlogs"


publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path(PROJECT_ID, TOPIC)

def publish(publisher, topic, message):
    data = message.encode('utf-8')
    return publisher.publish(topic_path, data = data)

def callback(message_future):
    # When timeout is unspecified, the exception method waits indefinitely.
    if message_future.exception(timeout=30):
        print('Publishing message on {} threw an Exception {}.'.format(
            topic_name, message_future.exception()))
    else:
        print(message_future.result())


if __name__ == '__main__':

    while True:
        line = generate_log_line()
        print(line)
        message_future = publish(publisher, topic_path, line)
        message_future.add_done_callback(callback)

        sleep_time = random.choice(range(1, 3, 1))
        time.sleep(sleep_time)

Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ„Π°ΠΉΠ» запустится, ΠΌΡ‹ смоТСм Π½Π°Π±Π»ΡŽΠ΄Π°Ρ‚ΡŒ Π²Ρ‹Π²ΠΎΠ΄ Π΄Π°Π½Π½Ρ‹Ρ… Π»ΠΎΠ³Π° Π½Π° консоль, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½Π° рисункС Π½ΠΈΠΆΠ΅. Π­Ρ‚ΠΎΡ‚ скрипт Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΌΡ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ CTRL+C, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ Π΅Π³ΠΎ.

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2
Рисунок 4. Π’Ρ‹Π²ΠΎΠ΄ publish_logs.py

НаписаниС ΠΊΠΎΠ΄Π° нашСго ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ всС ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΈΠ»ΠΈ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€ΠΈΡΡ‚ΡƒΠΏΠΈΡ‚ΡŒ ΠΊ самой интСрСсной части β€” написанию ΠΊΠΎΠ΄Π° нашСго ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Beam ΠΈ Python. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Beam-ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π° (p). ПослС Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ ΠΌΡ‹ создали ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ нСсколько Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΎΠ΄Π½Ρƒ Π·Π° Π΄Ρ€ΡƒΠ³ΠΎΠΉ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ pipe (|). Π’ ΠΎΠ±Ρ‰Π΅ΠΌ, Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ процСсс выглядит ΠΊΠ°ΠΊ Π½Π° рисункС Π½ΠΈΠΆΠ΅.

[Final Output PCollection] = ([Initial Input PCollection] | [First Transform]
             | [Second Transform]
             | [Third Transform])

Π’ нашСм ΠΊΠΎΠ΄Π΅ ΠΌΡ‹ создадим Π΄Π²Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π€ΡƒΠ½ΠΊΡ†ΠΈΡŽ regex_clean, которая сканируСт Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅Ρ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ строку Π½Π° основС списка PATTERNS, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ re.search. Ѐункция Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π½ΡƒΡŽ запятыми строку. Если Π²Ρ‹ Π½Π΅ ΡΠ²Π»ΡΠ΅Ρ‚Π΅ΡΡŒ экспСртом ΠΏΠΎ рСгулярным выраТСниям, я Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽ ознакомится с этим Ρ‚ΡƒΡ‚ΠΎΡ€ΠΈΠ°Π»ΠΎΠΌ ΠΈ ΠΏΠΎΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² Π±Π»ΠΎΠΊΠ½ΠΎΡ‚Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ ΠΊΠΎΠ΄. ПослС этого ΠΌΡ‹ опрСдСляСм ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΡƒΡŽ ParDo-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ Split, которая являСтся Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠ΅ΠΉ Beam-прСобразования для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Π’ Python это дСлаСтся особым способом β€” ΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ наслСдуСтся ΠΎΡ‚ класса DoFn Beam. Ѐункция Split ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ€Π°ΡΠΏΠ°Ρ€ΡˆΠ΅Π½Π½ΡƒΡŽ строку ΠΈΠ· ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ список словарСй с ΠΊΠ»ΡŽΡ‡Π°ΠΌΠΈ, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ ΠΈΠΌΠ΅Π½Π°ΠΌ столбцов Π² нашСй Ρ‚Π°Π±Π»ΠΈΡ†Π΅ BigQuery. Π•ΡΡ‚ΡŒ ΠΊΠΎΠ΅-Ρ‡Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ слСдуСт ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎ эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ: ΠΌΠ½Π΅ ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ datetime Π²Π½ΡƒΡ‚Ρ€ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π»Π°. Π― ΠΏΠΎΠ»ΡƒΡ‡Π°Π» сообщСниС ΠΎΠ± ошибкС ΠΏΡ€ΠΈ ΠΈΠΌΠΏΠΎΡ€Ρ‚Π΅ Π² Π½Π°Ρ‡Π°Π»Π΅ Ρ„Π°ΠΉΠ»Π°, Ρ‡Ρ‚ΠΎ Π±Ρ‹Π»ΠΎ странно. Π­Ρ‚ΠΎΡ‚ список Π·Π°Ρ‚Π΅ΠΌ пСрСдаСтся Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ WriteToBigQuery, которая просто добавляСт наши Π΄Π°Π½Π½Ρ‹Π΅ Π² Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. Код для Batch DataFlow Job ΠΈ Streaming DataFlow Job ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ Π½ΠΈΠΆΠ΅. ЕдинствСнноС ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠ°ΠΊΠ΅Ρ‚Π½Ρ‹ΠΌ ΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Ρ‹ΠΌ ΠΊΠΎΠ΄ΠΎΠΌ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΌΡ‹ Ρ‡ΠΈΡ‚Π°Π΅ΠΌ CSV ΠΈΠ· src_path, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ReadFromText ΠΈΠ· Beam.

Batch DataFlow Job (ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²)

import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions
from google.cloud import bigquery
import re
import logging
import sys

PROJECT='user-logs-237110'
schema = 'remote_addr:STRING, timelocal:STRING, request_type:STRING, status:STRING, body_bytes_sent:STRING, http_referer:STRING, http_user_agent:STRING'


src_path = "user_log_fileC.txt"

def regex_clean(data):

    PATTERNS =  [r'(^S+.[S+.]+S+)s',r'(?<=[).+?(?=])',
           r'"(S+)s(S+)s*(S*)"',r's(d+)s',r"(?<=[).d+(?=])",
           r'"[A-Z][a-z]+', r'"(http|https)://[a-z]+.[a-z]+.[a-z]+']
    result = []
    for match in PATTERNS:
      try:
        reg_match = re.search(match, data).group()
        if reg_match:
          result.append(reg_match)
        else:
          result.append(" ")
      except:
        print("There was an error with the regex search")
    result = [x.strip() for x in result]
    result = [x.replace('"', "") for x in result]
    res = ','.join(result)
    return res


class Split(beam.DoFn):

    def process(self, element):
        from datetime import datetime
        element = element.split(",")
        d = datetime.strptime(element[1], "%d/%b/%Y:%H:%M:%S")
        date_string = d.strftime("%Y-%m-%d %H:%M:%S")

        return [{ 
            'remote_addr': element[0],
            'timelocal': date_string,
            'request_type': element[2],
            'status': element[3],
            'body_bytes_sent': element[4],
            'http_referer': element[5],
            'http_user_agent': element[6]
    
        }]

def main():

   p = beam.Pipeline(options=PipelineOptions())

   (p
      | 'ReadData' >> beam.io.textio.ReadFromText(src_path)
      | "clean address" >> beam.Map(regex_clean)
      | 'ParseCSV' >> beam.ParDo(Split())
      | 'WriteToBigQuery' >> beam.io.WriteToBigQuery('{0}:userlogs.logdata'.format(PROJECT), schema=schema,
        write_disposition=beam.io.BigQueryDisposition.WRITE_APPEND)
   )

   p.run()

if __name__ == '__main__':
  logger = logging.getLogger().setLevel(logging.INFO)
  main()

Streaming DataFlow Job (ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΠΎΡ‚ΠΎΠΊΠ°)

from apache_beam.options.pipeline_options import PipelineOptions
from google.cloud import pubsub_v1
from google.cloud import bigquery
import apache_beam as beam
import logging
import argparse
import sys
import re


PROJECT="user-logs-237110"
schema = 'remote_addr:STRING, timelocal:STRING, request_type:STRING, status:STRING, body_bytes_sent:STRING, http_referer:STRING, http_user_agent:STRING'
TOPIC = "projects/user-logs-237110/topics/userlogs"


def regex_clean(data):

    PATTERNS =  [r'(^S+.[S+.]+S+)s',r'(?<=[).+?(?=])',
           r'"(S+)s(S+)s*(S*)"',r's(d+)s',r"(?<=[).d+(?=])",
           r'"[A-Z][a-z]+', r'"(http|https)://[a-z]+.[a-z]+.[a-z]+']
    result = []
    for match in PATTERNS:
      try:
        reg_match = re.search(match, data).group()
        if reg_match:
          result.append(reg_match)
        else:
          result.append(" ")
      except:
        print("There was an error with the regex search")
    result = [x.strip() for x in result]
    result = [x.replace('"', "") for x in result]
    res = ','.join(result)
    return res


class Split(beam.DoFn):

    def process(self, element):
        from datetime import datetime
        element = element.split(",")
        d = datetime.strptime(element[1], "%d/%b/%Y:%H:%M:%S")
        date_string = d.strftime("%Y-%m-%d %H:%M:%S")
        
        return [{ 
            'remote_addr': element[0],
            'timelocal': date_string,
            'request_type': element[2],
            'body_bytes_sent': element[3],
            'status': element[4],
            'http_referer': element[5],
            'http_user_agent': element[6]
    
        }]

def main(argv=None):

   parser = argparse.ArgumentParser()
   parser.add_argument("--input_topic")
   parser.add_argument("--output")
   known_args = parser.parse_known_args(argv)


   p = beam.Pipeline(options=PipelineOptions())

   (p
      | 'ReadData' >> beam.io.ReadFromPubSub(topic=TOPIC).with_output_types(bytes)
      | "Decode" >> beam.Map(lambda x: x.decode('utf-8'))
      | "Clean Data" >> beam.Map(regex_clean)
      | 'ParseCSV' >> beam.ParDo(Split())
      | 'WriteToBigQuery' >> beam.io.WriteToBigQuery('{0}:userlogs.logdata'.format(PROJECT), schema=schema,
        write_disposition=beam.io.BigQueryDisposition.WRITE_APPEND)
   )
   result = p.run()
   result.wait_until_finish()

if __name__ == '__main__':
  logger = logging.getLogger().setLevel(logging.INFO)
  main()

Запуск ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°

ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ нСсколькими Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ способами. Если Π±Ρ‹ ΠΌΡ‹ Π·Π°Ρ…ΠΎΡ‚Π΅Π»ΠΈ, ΠΌΡ‹ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ‹ просто Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π΅Π³ΠΎ локально с Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»Π°, ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎ войдя Π² GCP.

python -m main_pipeline_stream.py 
 --input_topic "projects/user-logs-237110/topics/userlogs" 
 --streaming

Однако ΠΌΡ‹ собираСмся Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π΅Π³ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ DataFlow. ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½ΠΈΠΆΠ΅ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹, установив ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹.

  • project β€” ID вашСго ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° GCP.
  • runner β€” срСдство запуска ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Π²Π°ΡˆΡƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΈ сконструируСт ваш ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€. Для выполнСния Π² ΠΎΠ±Π»Π°ΠΊΠ΅ Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ DataflowRunner.
  • staging_location β€” ΠΏΡƒΡ‚ΡŒ ΠΊ ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠΌΡƒ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Ρƒ Cloud Dataflow для индСксировани ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΊΠΎΠ΄Π°, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ, Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰ΠΈΠΌ Ρ€Π°Π±ΠΎΡ‚Ρƒ.
  • temp_location β€” ΠΏΡƒΡ‚ΡŒ ΠΊ ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠΌΡƒ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Ρƒ Cloud Dataflow для размСщСния Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ² Π·Π°Π΄Π°Π½ΠΈΠΉ, созданных Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°.
  • streaming

python main_pipeline_stream.py 
--runner DataFlow 
--project $PROJECT 
--temp_location $BUCKET/tmp 
--staging_location $BUCKET/staging
--streaming

Пока эта ΠΊΠΎΠΌΠ°Π½Π΄Π° выполняСтся, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π½Π° Π²ΠΊΠ»Π°Π΄ΠΊΡƒ DataFlow Π² google-консоли ΠΈ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ наш ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€. ΠšΠ»ΠΈΠΊΠ½ΡƒΠ² ΠΏΠΎ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Ρƒ, ΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΠΏΠΎΡ…ΠΎΠΆΠ΅Π΅ Π½Π° рисунок 4. Π’ цСлях ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π² Π»ΠΎΠ³ΠΈ, Π° Π·Π°Ρ‚Π΅ΠΌ Π² Stackdriver для просмотра ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Ρ‹Ρ… Π»ΠΎΠ³ΠΎΠ². Π­Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠ³Π»ΠΎ ΠΌΠ½Π΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ΠΎΠΌ Π² рядС случаСв.

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2
Рисунок 4: Beam-ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€

Доступ ΠΊ нашим Π΄Π°Π½Π½Ρ‹ΠΌ Π² BigQuery

Π˜Ρ‚Π°ΠΊ, Ρƒ нас ΡƒΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΏΡƒΡ‰Π΅Π½ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, ΠΏΠΎΡΡ‚ΡƒΠΏΠ°ΡŽΡ‰ΠΈΠΌΠΈ Π² Π½Π°ΡˆΡƒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ это, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ BigQuery ΠΈ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅. ПослС использования ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π½ΠΈΠΆΠ΅ Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ нСсколько строк Π½Π°Π±ΠΎΡ€Π° Π΄Π°Π½Π½Ρ‹Ρ…. Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Ρƒ нас Π΅ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅, хранящиСся Π² BigQuery, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ провСсти дальнСйший Π°Π½Π°Π»ΠΈΠ·, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΅Π»ΠΈΡ‚ΡŒΡΡ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ с ΠΊΠΎΠ»Π»Π΅Π³Π°ΠΌΠΈ ΠΈ Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΎΡ‚Π²Π΅Ρ‡Π°Ρ‚ΡŒ Π½Π° бизнСс-вопросы.

SELECT * FROM `user-logs-237110.userlogs.logdata` LIMIT 10;

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π§Π°ΡΡ‚ΡŒ 2
Рисунок 5: BigQuery

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

НадССмся, Ρ‡Ρ‚ΠΎ этот пост послуТит ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ создания ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠ³ΠΎ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π° Π΄Π°Π½Π½Ρ‹Ρ…, Π° Ρ‚Π°ΠΊΠΆΠ΅ поиска способов ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π±ΠΎΠ»Π΅Π΅ доступными. Π₯Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… Π² Ρ‚Π°ΠΊΠΎΠΌ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ Π΄Π°Π΅Ρ‚ Π½Π°ΠΌ ΠΌΠ½ΠΎΠ³ΠΎ прСимущСств. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΎΡ‚Π²Π΅Ρ‡Π°Ρ‚ΡŒ Π½Π° Π²Π°ΠΆΠ½Ρ‹Π΅ вопросы, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, сколько людСй ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ наш ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚? РастСт Π»ΠΈ со Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ Π±Π°Π·Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ? Π‘ ΠΊΠ°ΠΊΠΈΠΌΠΈ аспСктами ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Π° люди Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ большС всСго? И Π΅ΡΡ‚ΡŒ Π»ΠΈ ошибки, Ρ‚Π°ΠΌ Π³Π΄Π΅ ΠΈΡ… Π±Ρ‹Ρ‚ΡŒ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ? Π­Ρ‚ΠΎ Ρ‚Π΅ вопросы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ интСрСсны для ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ. На основС ΠΈΠ΄Π΅ΠΉ, Π²Ρ‹Ρ‚Π΅ΠΊΠ°ΡŽΡ‰ΠΈΡ… ΠΈΠ· ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ² Π½Π° эти вопросы, ΠΌΡ‹ смоТСм ΡƒΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ ΠΈ ΠΏΠΎΠ²Ρ‹ΡΠΈΡ‚ΡŒ Π·Π°ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΠΎΠ²Π°Π½Π½ΠΎΡΡ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ.

Beam Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ»Π΅Π·Π΅Π½ для Ρ‚Π°ΠΊΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° ΡƒΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠΉ, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΠΌΠ΅Π΅Ρ‚ ряд Π΄Ρ€ΡƒΠ³ΠΈΡ… интСрСсных случаСв использования. НапримСр, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ Π±ΠΈΡ€ΠΆΠ΅Π²Ρ‹ΠΌ Ρ‚ΠΈΠΊΠ°ΠΌ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈ ΡΠΎΠ²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒ сдСлки Π½Π° основС Π°Π½Π°Π»ΠΈΠ·Π°, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Ρƒ вас Π΅ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΏΠΎΡΡ‚ΡƒΠΏΠ°ΡŽΡ‰ΠΈΠ΅ с транспортных срСдств, ΠΈ Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ расчСт уровня Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°. Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π±Ρ‹Ρ‚ΡŒ ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠΉ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠ΅ΠΉ, ΡΠΎΠ±ΠΈΡ€Π°ΡŽΡ‰Π΅ΠΉ Π΄Π°Π½Π½Ρ‹Π΅ ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΡ… ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π΅ΠΉ Π΅Π΅ для создания ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… ΠΏΠ°Π½Π΅Π»Π΅ΠΉ для отслСТивания ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ. Π›Π°Π΄Π½ΠΎ, господа, это Ρ‚Π΅ΠΌΠ° ΡƒΠΆΠ΅ для Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ поста, спасибо Π·Π° Ρ‡Ρ‚Π΅Π½ΠΈΠ΅, Π° для Ρ‚Π΅Ρ…, ΠΊΡ‚ΠΎ Ρ…ΠΎΡ‡Π΅Ρ‚ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄, Π½ΠΈΠΆΠ΅ ссылка Π½Π° ΠΌΠΎΠΉ GitHub.

https://github.com/DFoly/User_log_pipeline

На этом всС. Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π²ΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ