Jakie są najlepsze biblioteki Haskell do operacjonalizacji programu? [Zamknięte]

115

Jeśli mam zamiar wprowadzić program do produkcji, jest kilka rzeczy, które muszę zrobić, aby program mógł zostać uznany za „zoperacjonalizowany” - to znaczy działający i możliwy do utrzymania w sposób mierzalny i weryfikowalny zarówno przez inżynierów, jak i personel operacyjny. Dla moich celów zoperacjonalizowany program musi:

  • Móc logować się na wielu poziomach (np. Debugowanie, ostrzeżenia itp.).
  • Umiejętność gromadzenia i udostępniania metryk / statystyk dotyczących rodzajów pracy wykonywanej przez program i czasu jej trwania. Idealnie byłoby, gdyby zebrane metryki były dostępne w formacie zgodnym z powszechnie używanymi narzędziami do monitorowania, takimi jak Ganglia , lub można je w ten sposób zmienić.
  • Być konfigurowalne, najlepiej za pośrednictwem systemu, który umożliwia aktualizację skonfigurowanych właściwości w uruchomionych programach bez ponownego uruchamiania programów.
  • Możliwość wdrożenia na zdalnych serwerach w powtarzalny sposób.

W świecie Scala istnieją dobre biblioteki, które radzą sobie z co najmniej trzema pierwszymi wymaganiami. Przykłady:

Jeśli chodzi o wdrażanie, jednym podejściem przyjętym w świecie Scala jest połączenie kodu bajtowego i bibliotek, które składają się na program z czymś w rodzaju assemblera-sbt , a następnie wysłanie powstałego pakietu („grubego JAR”) na zdalne serwery za pomocą narzędzia takiego jak Capistrano który wykonuje polecenia równolegle przez SSH. Nie jest to problem, który wymaga narzędzi specyficznych dla języka, ale jestem ciekawy, czy takie narzędzie istnieje w społeczności Haskell.

Prawdopodobnie istnieją biblioteki Haskell, które zapewniają cechy, które opisałem powyżej. Chciałbym wiedzieć, które z dostępnych bibliotek są uważane za „najlepsze”; to znaczy, które są najbardziej dojrzałe, dobrze utrzymane, powszechnie stosowane w społeczności Haskell i stanowią przykład najlepszych praktyk Haskell.

Jeśli istnieją inne biblioteki, narzędzia lub praktyki związane z przygotowywaniem kodu Haskell do produkcji, chciałbym również o nich wiedzieć.

Alex Payne
źródło
1
Czwarta kula może powodować kłopoty, ponieważ Haskell jest skompilowany do natywnego. Możesz spróbować kompilacji statycznej, która może działać lub nie, ale optymalnie byłoby mieć podobne środowisko na serwerze produkcyjnym niż na serwerze deweloperskim. Cabal-dev jest środowiskiem piaskownicy, które może być odpowiednie do przenoszenia na inne maszyny. Nawet wtedy wymagałoby to zainstalowania przynajmniej bibliotek podstawowych na maszynie docelowej.
Masse
1
Jeśli chodzi o inne narzędzia i techniki, to pytanie SO zawiera przegląd: stackoverflow.com/questions/3077866/ ...
Don Stewart
1
Jeszcze jedno - w systemach * nix można uzyskać dostęp do ogromnej ilości statystyk procesów i metadanych bezpośrednio przez system plików / proc. Więc jeśli napiszesz kilka procedur, aby to zinterpretować, pomoże to zastąpić brak bezpośrednich punktów zaczepienia w środowisku wykonawczym.
sclv
1
wdrażanie pliku binarnego jest łatwe, o ile tworzysz w tym samym środowisku (powinieneś mieć serwer pomostowy, jeśli twój komputer ma inną architekturę). Następnie możesz zsynchronizować pliki binarne i dowolne pliki zewnętrzne. Nie ma biblioteki ssh dla haskell do automatycznego wykonywania poleceń restartu, ale możesz użyć capistrano.
Greg Weber
1
@tchrist Spędza reszta akapitu pierwszego i wypunktowanie bezpośrednio po słowie operacjonalizacji wyjaśniając jego znaczenie w prostym języku angielskim.
Will McCutchen

Odpowiedzi:

54

To świetne pytanie! Oto pierwsze cięcie.

Móc logować się na wielu poziomach (np. Debugowanie, ostrzeżenia itp.).

hslogger to z pewnością najpopularniejszy framework do logowania.

Umiejętność gromadzenia i udostępniania metryk / statystyk dotyczących rodzajów pracy wykonywanej przez program i czasu jej trwania. Idealnie byłoby, gdyby zebrane metryki były dostępne w formacie zgodnym z powszechnie używanymi narzędziami do monitorowania, takimi jak Ganglia, lub można je w ten sposób zmienić.

Nie znam żadnych standardowych narzędzi raportowania, jednak wyodrębnianie raportów ze +RTS -sstrumieni (lub poprzez profilowanie flag wyjściowych) było czymś, co robiłem w przeszłości.

$ ./A +RTS -s
64,952 bytes allocated in the heap
1 MB total memory in use
 %GC time       0.0%  (6.1% elapsed)
 Productivity 100.0% of total user, 0.0% of total elapsed

Możesz to również uzyskać w formacie do odczytu maszynowego:

$ ./A +RTS -t --machine-readable

 [("bytes allocated", "64952")
 ,("num_GCs", "1")
 ,("average_bytes_used", "43784")
 ,("max_bytes_used", "43784")
 ,("num_byte_usage_samples", "1")
 ,("peak_megabytes_allocated", "1")
 ,("init_cpu_seconds", "0.00")
 ,("init_wall_seconds", "0.00")
 ,("mutator_cpu_seconds", "0.00")
 ,("mutator_wall_seconds", "0.00")
 ,("GC_cpu_seconds", "0.00")
 ,("GC_wall_seconds", "0.00")
 ]

Idealnie byłoby podłączyć się do działającego środowiska wykonawczego GHC przez gniazdo i spojrzeć na te statystyki GC interaktywnie, ale obecnie nie jest to super łatwe (potrzebne są powiązania FFI z interfejsem "rts / Stats.h"). Możesz dołączyć do procesu przy użyciu ThreadScopei monitorować zachowanie GC i wątków.

Podobne flagi są dostępne dla przyrostowego, rejestrowanego profilowania czasu i przestrzeni , które można wykorzystać do monitorowania (np. Te wykresy mogą być budowane przyrostowo).

hpczbiera wiele statystyk dotyczących wykonywania programu, poprzez jego Tixtyp, a ludzie napisali narzędzia do rejestrowania według przedziału czasu, jaki kod jest wykonywany.

Być konfigurowalne, najlepiej za pośrednictwem systemu, który umożliwia aktualizację skonfigurowanych właściwości w uruchomionych programach bez ponownego uruchamiania programów.

Dostępnych jest do tego kilka narzędzi, możesz przeładować stan w stylu xmonad; lub przejdź do kodowania hotswapping poprzez pluginspakiety * lubhint . Niektóre z nich są bardziej eksperymentalne niż inne.

Powtarzalne wdrożenia

Niedawno wydany Galois cabal-dev, który jest narzędziem do tworzenia odtwarzalnych kompilacji (tj. Zależności są określane i kontrolowane).

Don Stewart
źródło
6
Pakiet dyrektorów ma na celu wyodrębnienie przeładowywania stanu w stylu xmonad, więc myślę, że należy o tym szczególnie wspomnieć. Jednak wiąże się ze sobą rekompilację i ponowne wdrażanie, więc tak naprawdę dotyczy zmian na maszynie z całym łańcuchem narzędzi. Do zdalnych zmian potrzebujesz czegoś bardziej podobnego do stanu kwasowego, choć jak na mój gust jest nieco ciężki. Mam tę trwałą abstrakcję mvar, która ma słabsze gwarancje, ale którą można traktować jak zwykły MVar, który jest magicznie zapełniany przy każdym uruchomieniu pliku binarnego ostatnimi przechowywanymi danymi.
sclv
2
Ponadto nowa EventLogstruktura rejestrowania GHC (używana +RTS -lw czasie wykonywania) przesyła dane wyjściowe do pliku, który można wizualizować za pomocą dowolnego narzędzia odczytującego format dziennika zdarzeń.
Don Stewart
2
Program wyemituje dzienniki swoich zdarzeń, na przykład: galois.com/~dons/tmp/A.event.log - co można zobaczyć jako - i.imgur.com/QAe6r.png . Mogę sobie wyobrazić tworzenie innych narzędzi do monitorowania na podstawie tego formatu.
Don Stewart
2
Zwróć również uwagę, że wiele narzędzi do profilowania świetnie nadaje się do testowania, ale nie do kodu produkcyjnego. Pomijając narzut, na przykład -prof może być używany tylko z jednym procesorem.
sclv
9
  • Jeśli chodzi o konfigurację, zauważyłem, że plik ConfigFile jest przydatny w moich projektach. Używam go do wszystkich moich demonów w produkcji. Nie aktualizuje się automatycznie.
  • Używam cabal-dev do tworzenia odtwarzalnych kompilacji w różnych środowiskach (lokalnych, deweloperskich, lokalnych współpracowników). Naprawdę cabal-dev jest niezbędny, zwłaszcza ze względu na możliwość obsługi lokalnych, poprawionych wersji bibliotek w katalogu projektu.
  • Bez względu na to, co jest warte, wybrałbym przeładowywanie stanu w stylu xmonad. Czystość Haskella sprawia, że ​​jest to trywialne; migracja to problem, ale tak jest. Eksperymentowałem z hsplugins i wskazówką dotyczącą mojego IRCd iw pierwszym przypadku wystąpił problem z uruchomieniem GHC, aw drugim błąd segmentacji. Zostawiłem oddziały na Githubie do późniejszej sekcji: https://github.com/chrisdone/hulk

Przykład pliku ConfigFile:

# Default options
[DEFAULT]
hostname: localhost
# Options for the first file
[file1]
location: /usr/local
user: Fred
Christopher Gotowe
źródło
9

Powtórzę wszystko, co powiedział Don, i dodam kilka ogólnych rad.

Na przykład dwa dodatkowe narzędzia i biblioteki, które warto rozważyć:

  • QuickCheck do testowania opartego na właściwościach
  • hlint jako rozszerzona wersja-Wall

Oba są ukierunkowane na jakość kodu.

W ramach praktyki kodowania unikaj Lazy IO. Jeśli potrzebujesz przesyłania strumieniowego we / wy, skorzystaj z jednej z iteracyjnych bibliotek, takich jak moduł wyliczający . Jeśli spojrzysz na Hackage , zobaczysz biblioteki, takie jak http-enumerator, które używają stylu modułu wyliczającego dla żądań http.

Jeśli chodzi o wybieranie bibliotek podczas hakowania, czasami może pomóc przyjrzenie się, ile pakietów zależy od czegoś. Łatwo zobacz odwrotne zależności pakietu, którego możesz użyć na tej stronie internetowej, która odzwierciedla hakowanie:

Jeśli aplikacja kończy się w ciasnych pętlach, jak serwer WWW obsługujący wiele żądań, lenistwo może być problemem w postaci wycieków przestrzeni. Często jest to kwestia dodania adnotacji dotyczących ścisłości w odpowiednich miejscach. Profilowanie, doświadczenie i rdzeń czytania to główne techniki, które znam w walce z tego typu rzeczami. Najlepszym odniesieniem do profilowania, jakie znam, jest rozdział 25 książki Real-World Haskell .

Jason Dagit
źródło