poniedziałek, 27 lutego 2023

GCP Metryki Pub/Sub

 Korzystając z SDK Google możemy w łatwy sposób pobrać metryki dla Pub/Sub.

Aby pobrać metryki dla projektu skorzystamy z biblioteki Google.Cloud.Monitoring.V3. Pozwala ona pobrać metryki dla większości serwisów oferowanych przez GCP. Nas w tym przypadku interesować będą metryki dla Pub/Suba. 

Spis metryk które możemy pobrać znajduje się w oficjalnej dokumentacji: https://cloud.google.com/monitoring/api/metrics_gcp#gcp-pubsub

Rozpoczynamy od instalacji biblioteki, które umożliwi pobranie metryk:


API dla jednego zapytania obsługuje pobranie tylko jednej metryki. Nie możemy zatem w jednym zapytaniu pobrać np. czasu najstarszej wiadomości jak i ilości wiadomości oczekujących na subskrypcji. 


 var metricServiceClient = await MetricServiceClient.CreateAsync();  
 var request = new ListTimeSeriesRequest  
 {  
   ProjectName = new ProjectName("project_id"),  
   Filter = "metric.type = \"pubsub.googleapis.com/subscription/oldest_unacked_message_age\"",  
   Interval = new TimeInterval  
   {  
     StartTime = Timestamp.FromDateTime(DateTime.UtcNow.AddMinutes(-10)),  
     EndTime = Timestamp.FromDateTime(DateTime.UtcNow)  
   },  
   View = ListTimeSeriesRequest.Types.TimeSeriesView.Full  
 };  
 var results = metricServiceClient.ListTimeSeriesAsync(request);  
 await foreach (var result in results)  
 {  
   Console.WriteLine(result.Resource.Labels["subscription_id"]);  
   foreach (var point in result.Points)  
   {  
     Console.Write(point.Interval.StartTime);  
     switch (point.Value.ValueCase)  
     {    
       case TypedValue.ValueOneofCase.BoolValue:  
         Console.WriteLine(point.Value.BoolValue);  
         break;  
       case TypedValue.ValueOneofCase.Int64Value:  
         Console.WriteLine(point.Value.Int64Value);  
         break;  
       case TypedValue.ValueOneofCase.DoubleValue:  
         Console.WriteLine(point.Value.DoubleValue);  
         break;  
       case TypedValue.ValueOneofCase.StringValue:  
         Console.WriteLine(point.Value.StringValue);  
         break;  
       case TypedValue.ValueOneofCase.DistributionValue:  
         Console.WriteLine(point.Value.DistributionValue);  
         break;  
       default:  
         throw new ArgumentOutOfRangeException();  
     }  
   }  
   Console.WriteLine(new string('-', 50));  
 }  

Wynik po wykonaniu kodu:


Otrzymany wynik zgodnie z dokumentacją podany jest w sekundach. 

A teraz przykład jak odfiltrować subskrypcję po jej nazwie (subscription_id).


 request = new ListTimeSeriesRequest  
 {  
   ProjectName = new ProjectName("project_id"),  
   Filter = "metric.type = \"pubsub.googleapis.com/subscription/num_undelivered_messages\" AND (resource.label.subscription_id = starts_with(\"aaa.\") OR resource.label.subscription_id = starts_with(\"bbb.\"))",  
   Interval = new TimeInterval  
   {  
     StartTime = Timestamp.FromDateTime(DateTime.UtcNow.AddMinutes(-1)),  
     EndTime = Timestamp.FromDateTime(DateTime.UtcNow)  
   },  
   View = ListTimeSeriesRequest.Types.TimeSeriesView.Full  
 };  

Oczywiście jeżeli nie chcemy wykonywać operacji typu like możemy od razu podać nazwę subskrypcji.

Pobrać możemy dowolną metrykę z oficjalnej specyfikacji. Metryki mogą być agregowane w różne okienka czasowe (minutowe, lub dłuższe). Za pomocą parametru Interval kontrolujemy przedział czasowy otrzymanych wyników. 

wtorek, 21 lutego 2023

Pobranie listy instancji w GCP

Google Cloud Platform oferuje gotowe SDK dla .NET aby automatyzować (jak i programistyczne wykorzystać) manuale zadania. 

Przydatną funkcję może być pobranie dostępnej listy Manage Instance Groups z GCP (np. w celu późniejszego pobrania maszyn wirtualnych dla każdego z MIGów).


Pierwszym krokiem jest dodanie biblioteki Google.Cloud.Compute.V1 do projektu:


Następnie kod który pozwoli dla danego projektu odczytać wszystkie Manage Instance Groups:

InstanceGroupManagersClient instanceGroupManagersClient = await InstanceGroupManagersClient.CreateAsync();
var pagedAsyncEnumerable = instanceGroupManagersClient.AggregatedListAsync("project_id");
await foreach (var zoneMigs in pagedAsyncEnumerable)
{
    foreach (var instanceGroup in zoneMigs.Value.InstanceGroupManagers)
    {
        Console.WriteLine(instanceGroup.Name);
    }
}


Korzystanie z gotowych bibliotek SDKa niesamowicie ułatwia kodowanie. API wymagałoby znacznie większej ilości kroków aby uzyskać ten sam efekt. 

poniedziałek, 6 lutego 2023

IIS Tracing - czyli jak debugować problemy, które nie zostawiają śladów w logach

 Pracując z produkcyjnymi aplikacji hostowanymi na IISie możemy napotkać na trudności z błędami typu 500. Błędy te są trudne w debugowaniu, zwłaszcza, gdy pojawiają się sporadycznie a w aplikacji nie ma wystarczającego logowania, które przechwytuje wszystkie wyjątki. 

Pomóc w takim przypadku może opcja Tracingu dostępna w serwerze IIS. Na początek należy sprawdzić czy potrzebne funkcje są zainstalowane:


Po instalacji Tracingu w IIS - przystępujemy do konfiguracji. Aktywować Tracing możemy zarówno poprzez klikanie w UI IISa, jak i dużo łatwiej i szybciej za pomocą PowerShella (to rozwiązane także łatwo zautomatyzować w przypadku dużej ilości serwerów). 

1 Sposób - UI IIS Console

Pierwszy sposób polega na wyklikaniu wszystkiego w interfejsie graficznym. Konfigurację możemy dokonać na poziomie Serwera lub konkretnej aplikacji. Jeżeli dokonamy konfiguracji na poziomie Serwera, wszystkie strony będą niejako dziedziczyły ją. Zaczniemy od zdefiniowania kryteriów logowania, następnie włączymy Tracking i ustawimy gdzie i ile plików ma zostać zapisane. 



W nowym okienku klikamy po prawej stronie w manu Actions -> Add... Otworzy się kreator, w którym możemy dokonać wyboru opcji. W pierwszym kroku możemy wybrać co chcemy logować:

W kolejnym kroku wybieramy warunki logowania (np. wszystkie wiadomości które zakończyły się błędem 500):

Ostatni krok pozwala wybrać poziom prowidera i poziom logowania:

Polecam na początek ustawić logowanie na wszystko na poziome Verbose. Pliki logów nie zajmują dużo a więcej detali ułatwi szukanie odpowiedzi dlaczego aplikacja nie działa poprawnie.

Ostatnim krokiem jest właściwie włączenie Tracingu na Site. Podobnie jak poprzednio wykorzystamy UI IISa:
Po lewej strony z menu wybieramy interesujący nas Site. Następnie po prawej stronie Configuration -> Failed Request Tracking...

W nowym okienku wybieramy:
  • zaznaczamy Enable aby włączyć logowanie
  • Directory - miejsce gdzie zostaną zapisane logi
  • Maximum number of trace files - 50 logów wydaje się nie dużą ilością, polecam ustawić co najmniej 1000 logów

Po zaakceptowaniu ustawień, wszystko jest gotowe i możemy czekać na pierwsze logi. 

2 Sposób - PowerShell

Moim zdaniem dużo prostszy i łatwiejszy sposób konfiguracji. Zacznijmy od komendy która dodaje Tracing na błędy z kodem 500 (czyli de fakto to co poprzednio wyklikiwaliśmy ręcznie):
Enable-WebRequestTracing -StatusCodes 500 -MaxLogFiles 2000

Jeżeli chcemy wskazać dokładnie jeden Site do tracowania wystarczy dodać parametr -Name "Site Name"

Do wyłączenia tracingu służy komenda:

Disable-WebRequestTracing

Tak samo możemy wyspecyfikować Site na którym chcemy wyłączyć tracing za pomocą parametru -Name. Wyłączenie tracingu nie powoduje usunięcia jego ustawień. Aby wyczyścić wszystkie ustawienia, należy skorzystać z komendy:

Clear-WebRequestTracingSettings


Przeglądanie plików Traca

Pliki traców zapisywane są jako pliki typu XML wraz z jednym plikiem transformacji XSL.

Otworzyć je możemy tylko po uprzednim zahostowaniu ich na serwerze WWW. Jeżeli spróbujemy otworzyć plik bezpośrednio w przeglądarce zobaczymy błąd bezpieczeństwa. 

Ja użyłem IISa aby zahostować plik i to wynik po nałożeniu formatowania:

Logi traca dostarczają wielu przydatnych informacji, jak:
  • zdarzenia dla każdego modułu, który brał udział przy procesowaniu requestu
  • który moduł zawiódł
  • hedery z requesta
  • body requesta
  • response wychodzący do klienta

W przypadku powyżej po anallizie, okazało się, że request zawierał niedozwolone znaki dla XMLa. Bez możliwości szybkiego wrzucenia nowej wersji kodu z odpowiednim logowaniem, trace wydaje się idealnym narzędziem pozwalającym zidentyfikować problem.