Miałem już zakończyć serię o serverless w gogle gdyż o cloud functions dużo więcej napisać się po prostu nie dało. Tak przynajmniej myślałem. Mimo wszystko kontynuowałem czytanie na temat funkcji, co jest możliwe a co nie. Jakie są opcje i gdzie te funkcje mogą być wykorzystane. I gdyby nie ślepy traf to tego postu by nie było a moja opinia o funkcjach w googlach była by dość słaba – przynajmniej gorsza niż teraz jest.
Przez zupełny przypadek trafiłem na opcję Debug w konsoli do zarządzania chmurą googla. Opcja ta umożliwia nam… tak jakby “debugowanie” funkcji, która działa na produkcji bez blokowania jej wykonania. “Debugowanie” a nie debugowanie, gdyż to wygląda jakby było zwykłym normalnym debugowanie a nie jest :) Po co coś takiego? No chociażby po to, że jak coś nam nie działa i nie wiemy co to zamiast co chwilę wgrywać nowszą wersję z odpowiednimi linijkami logowania danych i zagłębiania się w nich, możemy skorzystać z opcji “debugowania”. Bardzo przydatne dla edge case gdzie na wszystkich pozostałych środowiskach śmigało, ale akurat na produkcji coś idzie nie tak.
Jednak zaraz do tego dojdziemy co i jak. Przygotujmy sobie nasze środowisko i przy okazji poznamy trochę bliżej chmurę googla plus narzędzie gcloud
.
Pre-wymagania
Trzeba zainstalować Cloud SDK.
Przygotowanie rozwiązania
Uwaga, może się okazać, że wam w ten sposób proces nie zadziała. Cały cloud jest raczej wersji beta w google. Więc jeżeli wam to nie działa, to należy podskoczyć do kroku Podłączenie do repozytorium na google i potem wrócić tutaj i wykonać all bez git init
.
Stwórzmy sobie prosty katalog a w nim wykonajmy dwa bardzo ważne polecenia:
git init npm init
Do gita dodajmy odpowiedni .gitignore
– potrzebujemy przefiltrować po node.js jak i naszym edytorze, może być przydatny generator tego pliku – gitignore.io.
Mając wszystko gotowe, dodajmy plik .gitignore
oraz packages.json
to repozytorium.
Na razie możemy działać na lokalnym repo później, coś z nim zrobimy. Stwórzmy także plik index.js
który będzie zawierał następujący kod:
exports.debugWorld = function (req, res) { let name = req.query.name || 'SomeName'; if(true) { console.error('This IS ERROR!'); } console.log('My custom awesome message to log!'); res.status(200).send(`Hello, you can debug me ${name}!`); }
Ponownie, dodajmy i commitujemy plik. Jesteśmy prawie gotowi!
Podłączenie do repozytorium na google cloud
By móc skorzystać z tej super fajnej funkcji potrzebujemy repozytorium do którego jest dostęp zewnątrz. To może być bitbucket albo github. Jednak by było zabawnie skorzystamy z opcji repozytoriów googla.
Otwieramy Source Repository i tworzymy nowe. Wystarczy podać nazwę i wtedy naszym oczom pokaże się ekran:
Możemy teraz wykonać podane kroki (najlepiej w katalogu naszego repozytorium). Należy też czytać informacje które się pojawią na konsoli – warningi itp. Gdyż tam są informacje typu: jak zostaniecie poproszeni o podanie hasła to kliknijcie anuluj.
Jeżeli się wam udało wykonać wszystkie kroki bez błędów to super!
Jeżeli jednak mieliście taki problem jak ja:
> git push --all google fatal: unable to access 'https://source.developers.google.com/p/func-tests/r/debugWorld/': Unknown SSL protocol error in connection to source.developers.google.com:443
To rozwiązaniem problemu jest po prostu wykonanie drugiej opcji z podanych po utworzeniu repozytorium:
W tym wypadku jak zrobiłem push origin master to zadziałało to wszystko jak miodzio.
Pewny magiczny dodatek, który umożliwi nam debugowanie
Mając już wszystko podłączone, możemy zacząć przygotowywać nasze rozwiązanie pod debugger. By to zrobić, trzeba dodać paczkę @google-cloud/debug-agent
do projektu:
npm install @google-cloud/debug-agent --save
A następnie w pliku index.js
dodać:
require('@google-cloud/debug-agent').start({ allowExpressions: true });
Tak zmieniony plik packages.json
jak i index.js
pushujemy do origin master
. Co to robi? Umożliwia nam to co zrobimy później.
PS.: ja korzystałem ze starej paczki @google/cloud-debug i też działało.
Ready, steady… jeszcze jeden krok
By móc debugować naszą funkcję musi ona zostać z deployowana. Jako, że przeszliśmy ścieżkę od repo to możemy dalej tak kontynuować. Czyli z wgrać naszą funkcję jako plik zip.
W tym celu wystarczy wykonać polecenie w naszym katalogu:
> gcloud beta functions deploy debugWorld --stage-bucket gutek-functions-src --trigger-http Copying file://c:\users\gutek\appdata\local\temp\tmpwmszze\fun.zip [Content-Type=application/x-zip-compressed]... - [1 files][ 598.0 B/ 598.0 B] Operation completed over 1 objects/598.0 B. Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 entryPoint: debugWorld httpsTrigger: url: https://us-central1-func-tests.cloudfunctions.net/debugWorld latestOperation: operations/ZnVuYy10ZXN0cy91cy1jZW50cmFsMS9kZWJ1Z0hlbGxvL004TVUxdUdVZlBv name: projects/func-tests/locations/us-central1/functions/debugWorld serviceAccount: func-tests AT appspot.gserviceaccount.com sourceArchiveUrl: gs://gutek-functions-src/us-central1-debugWorld-jifytvzyokfz.zip status: READY timeout: 60s updateTime: '2017-07-26T14:19:12Z'
To nam wgra funkcję (stworzy ją) i udostępni pod url:
https://us-central1-func-tests.cloudfunctions.net/debugWorld
Uwaga: --stage-bucket
musi istnieć. Możecie go sobie stworzyć tutaj.
Jeżeli zaś o was mało interesuje i nie chcecie się bawić w taki deploy, to możemy stworzyć nową funkcję z poziomu UI i wskazać nasze istniejące repo jako źródło kodu. Dosłownie tylko tyle i aż tyle. Szkoda, że nie da się wybrać repo a trzeba to z palca robić. Ale działa.
Niezależnie jaki sposób deploymentu został użyty, funkcje trzeba przynajmniej raz odpalić by móc ją debugować.
Debuggowanie
Mając już all w repozytorium jak i z deployowane i przynajmniej raz odpalone to możemy testować. W tym celu w menu dostępnych aplikacji wybieramy Debug:
Ekran nas sam poprosi o dodanie kodu który ma zostać załadowany. Może to by repozytorium googla, github, bitbucket lub plik z naszego kompa. Skoro mamy kod w repo na google to skorzystajmy z tego:
Dzięki któremu nasz kod będzie dostępny na ekranie.
Następnie trzeba wybrać odpowiedni worker (jeżeli odpaliliśmy naszą funkcję to będzie worker):
Mając tak wybrane opcje, możemy zacząć się bawić dwoma opcjami testowania/debugowania kodu jakie są dostępne:
- Snapshot
- Logpoint
To czy działamy w kontekście snapshota czy logpointa określna wybrana zakładka po prawej stronie:
To też jest ważne na której zakładce jesteśmy w trakcie wykonywania zapytania do naszej funkcji. Gdyż jeżeli będziemy na logpoint, to dane ze snapshot nie zostaną przechwycone. Zaś jak jesteśmy na snapshot to logpointy działają, ale nie możemy ich ustawiać.
Snapshoty
Snapshot to jak sama nazwa wskazuje, migawka z wykonania naszej funkcji w danym miejscu. To znaczy, jeżeli ustawimy breakpoint na linijce 12 to jak wykonamy naszą funkcję, ten breakpoint będzie zawierał informacje o całym kontekście danej funkcji: zmienne lokalne, parametry funkcji jak i stack trace.
Ważne jest by pamiętać, że to nie jest prawdziwy breakpoint ale po prostu miejsce w którym robiony jest snapshot. Narzut na wydajność jest niski, tak jakby bardziej zaawansowany jakiś log. Ale przynajmniej funkcja nie jest blokowana do póki nie zwolnimy jej z procesu debugowania.
Logpointy
Logpointy to nic innego jak dodatkowe logowanie które możemy dodać do już istniejącej funkcji nie zmieniając jej kodu źródłowego. To znaczy, mamy jakiś problem, nie wiem zbytnio o co chodzi, dodajemy kilka dodatkowych logów i boom, już wiemy, że to jest jakiś dziwny przypadek i że snapshot się nam przyda :)
W logpointy ustawiamy podobnie jak breakpointy. Ale z tą różnicą iż będziemy podawać warunek kiedy ma być coś zalogowane oraz co ma być zalogowane:
Każdy taki log trafia do globalnego logowania wykonania funkcji. Można go przejrzeć w log viewer – link jest dostępny w dolnym panelu w zakładce Logs. Na razie jeszcze nie możemy tego przeglądać w oknie Debug. Przynajmniej dla cloud functions.
Taki log wygląda mniej więcej tak:
I zawiera takie informacje:
{ insertId: "000000-9e17da84-4649-495d-9fc4-addf7c091706" labels: { execution_id: "36fjd5rm36t5" } logName: "projects/func-tests/logs/cloudfunctions.googleapis.com%2Fcloud-functions" payload: "LOGPOINT: his name is "gutek"" receiveTimestamp: "2017-07-26T14:59:56.405687048Z" resource: { labels: { function_name: "debugWorld" project_id: "func-tests" region: "us-central1" } type: "cloud_function" } severity: "INFO" textPayload: "LOGPOINT: his name is "gutek"" timestamp: "2017-07-26T14:59:46.364Z" }
Jest jednak małe ale. Nie działały mi typy logpointów. Czy to był warning czy error, zawsze logowało się jako info. Może to naprawią a może tak ma być. Nie wiem.
Podsumowanie
To tyle co miałem dzisiaj do pokazania. Mi się osobiście funkcjonalność bardzo, ale to bardzo spodobała. Po pierwsze, wiem jak trudno jest czasami coś z produkcji wyciągnąć i wgrywanie częste nowego kodu by coś ekstra wyciągnąć nie należy do dobrych rozwiązań. Po drugie podoba mi się opcja debugowania bez zatrzymywania procesu. Nie jest to coś z czego zawsze będziemy korzystać. Ale kiedy coś pójdzie nie tak, te funkcję mogą uratować nam tyłek.
Jestem ciekawe czy mieliście przypadek by takie logowanie/debugowanie by was uratowało/wspomogło/przyspieszyło rozwiązanie problemu? Co sądzicie o takiej opcji jaką daje google, fajna? Niefajna?
PS.: Z góry napiszę, nie wiem co oferuje Application Insights więc ciężko się mi do tego odnieść. Możliwe, że MS też ma taką funkcję :)
Serverless – Non-blocking debugowanie na produkcji (Cloud Functions Część 3) – Jakub Gutkowski
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl
Comments are closed.