Datadog + OpenAI: Usando a IA para interpretar dados da saúde da aplicação

Leandro Belo
#LocalizaLabs
Published in
8 min readJul 24, 2023

Recentemente eu estava assistindo um vídeo em que o Luiz Carlos Faria mostra como usar o Chat GTP para interpretar alguns dados extraídos de um sistema de mensageria. Achei bem interessante a forma como ele reuniu os dados e construiu um texto de solicitação para IA, inclusive pedindo que ela construísse a reposta em formato JSON.

Após esse insight e refletindo sobre as possibilidades que podemos ter com a IA, pensei em conectar a IA ao Datadog através de um console .net para que ela interprete dados de performance de aplicações.
Para isso, criei uma API simples para retornar cotações de moedas e coloquei o Datadog para capturar os dados das requisições que essa aplicação recebe.

Agora vamos construir o console application (AI Analyzer) para obter os dados do Datadog e envia-los para a OpenAI.

Antes de aprofundarmos no código é importante falar que, apesar de ser um recurso incrível, devemos usa-lo com responsabilidade. Não é recomendável compartilhar com o o Chat GPT informações e arquivos (GPT-4) contendo dados sensíveis/restritos.
No exemplo que vou mostrar são enviados para IA apenas o valores, sem qualquer conexão com a aplicação ou o que ela faz.

O projeto

Para que a IA receba informações do Datadog, nosso script terá as seguintes etapas:

  1. Buscar informações no Datadog através de sua API e extrair da resposta apenas o tempo de resposta das requisições e o período ao qual se referem;
  2. Adequar esses dados dentro do texto que será enviado para a IA analisar;
  3. Realizar a chamada da API da OpenAI para obter a análise sobre os dados enviados.

Conectando ao Datadog

Não vou passar aqui o processo de criação de conta e configuração do ambiente do Datadog. Falarei sobre isso em outro post.
O Datadog libera alguns dias gratuitos para teste da plataforma. Será mais que suficiente para termos dados de uma aplicação de teste.

Etapa 1. Buscar os dados do Datadog:

Dentro da API do Datadog vou usar o endpoint Query timeseries points para obter os dados da aplicação.
Para realizar a chamada é preciso informar esses valores no header:

-H "Accept: application/json" \
-H "DD-API-KEY: ${CHAVE_VINCULADA_A_CONTA_PROPRIETÁRIA_DATADOG}" \ //LINK ONDE ELA FICA: https://us3.datadoghq.com/organization-settings/api-keys
-H "DD-APPLICATION-KEY: ${CHAVE_VINCULADA_AO_ESCOPO}" //LINK ONDE ELA FICA: https://us3.datadoghq.com/organization-settings/application-keys

E a query string fica dessa forma:

https://api.us3.datadoghq.com/api/v1/query?from=${DATA_FINAL_EM_SEGUNDOS}&to=${DATA_INICIO_EM_SEGUNDOS}&query=${QUERY_PARA_BUSCAR_A_APLICACAO}

A query executada no Datadog obtém a duração das chamadas que o serviço(API) de cotação de moedas recebeu nas últimas horas.

O código em C# para realizar essa consulta fica assim, considerando o header e a query string acima:

public DatadogQueryResponse Query(long dateFrom, long dateTo, string query)
{

Uri baseUrl = new Uri(_datadogConnect.ApiUrl ); //https://api.us3.datadoghq.com/api/v1
RestClient client = new RestClient(baseUrl);

RestRequest request = new RestRequest("query", Method.Get) { }; //Endpoint que vamos chamar

request.AddHeader("Accept", "application/json");
request.AddHeader("DD-API-KEY", _datadogConnect.ApiKey);
request.AddHeader("DD-APPLICATION-KEY", _datadogConnect.AppKey);
request.AddParameter("from", dateFrom);
request.AddParameter("to", dateTo);
request.AddParameter("query", query); //sum:trace.request.duration{env:local,service:currency-conversion}

RestResponse response = client.Execute(request);

if (response.StatusCode.Equals(HttpStatusCode.OK))
{
return JsonConvert.DeserializeObject<DatadogQueryResponse>(response.Content);
}
else
{
Console.WriteLine(response.ErrorMessage);
return null;
}

}

Pronto, temos a extração dos dados da aplicação no Datadog automatizada. Agora vamos partir para a segunda etapa, adequar esses dados dentro do texto enviado para a IA analisar.

Configurando chamada a Open IA
Para quem já conhece o ChatGTP, sabe que para extrair o que a IA tem de melhor precisamos ser bem detalhistas no texto que mandamos para ela. Aqui no código vamos fazer algo parecido.

Utilizando algumas frases demonstradas pelo Luiz no seu exemplo e adaptando o texto para o que queremos extrair, o método que irá compor o texto a ser enviado fica assim:

private static string IARequest(List<Latency> dataRequests)
{
string requestModel =
@"Você é gestora de um time de engenharia de software e precisa fornecer uma visão analítica sobre a saúde das aplicações que seu time é responsável.
Faça a análise da latência dessa aplicação. Os dados disponíveis são:

{0}

Se comporte como um especialista em estatística e métricas e forneça insights sobre a saúde da aplicação.
Faça sugestão de mudanças e diga qual o resultado esperado com a mudança.
Não explique nem repita meus dados.

Responda separado pelos tópicos:
Análise
Sugestões de melhorias
Resultados esperados
";

var sentencesWithData = DataRequests(dataRequests);

sentencesWithData.ForEach(delegate (string sentence)
{
Console.WriteLine(sentence);
});

string request = String.Format(requestModel, string.Join(".", sentencesWithData));

return request;
}

As sentenças com os dados retornados pela API do Datadog serão inseridas no {0} do código acima, após serem formatadas pelo seguinte método:

    private static List<string> DataRequests(List<Latency> data)
{
List<string> dataRequests = new List<string>();

foreach (var item in data)
{
string setence = $"Na data {item.DateTimeRequest} a aplicação apresentou uma latência de {item.RequestDurationSec} segundos";
dataRequests.Add(setence);
}

return dataRequests;
}

E por fim essa é a versão final do texto que a aplicação enviará para API da OpenIA:

Você é gestora de um time de engenharia de software e precisa fornecer uma visão analítica sobre a saúde das aplicações que seu time é responsável. 
Faça a análise da latência dessa aplicação. Os dados disponíveis são:

Na data 18/07/2023 04:00:00 a aplicação apresentou uma latência de 0,10135933825513348 segundos
Na data 18/07/2023 04:20:00 a aplicação apresentou uma latência de 0,11036452504340559 segundos
Na data 18/07/2023 04:40:00 a aplicação apresentou uma latência de 1,0412128228112123 segundos
Na data 18/07/2023 05:00:00 a aplicação apresentou uma latência de 0,10449184168828651 segundos
Na data 18/07/2023 05:20:00 a aplicação apresentou uma latência de 0,10022268968168646 segundos
Na data 18/07/2023 05:40:00 a aplicação apresentou uma latência de 0,38288891852134843 segundos
Na data 18/07/2023 06:00:00 a aplicação apresentou uma latência de 3,8831229052040723 segundos
Na data 18/07/2023 06:20:00 a aplicação apresentou uma latência de 0,09682298825355247 segundos
Na data 18/07/2023 06:40:00 a aplicação apresentou uma latência de 0,14978983518667519 segundos
Na data 18/07/2023 07:00:00 a aplicação apresentou uma latência de 0,10085981563897803 segundos
Na data 18/07/2023 07:20:00 a aplicação apresentou uma latência de 0,10862524722469971 segundos
Na data 18/07/2023 07:40:00 a aplicação apresentou uma latência de 0,0949844301212579 segundos
Na data 18/07/2023 08:00:00 a aplicação apresentou uma latência de 4,493771197751631 segundos
Na data 18/07/2023 08:20:00 a aplicação apresentou uma latência de 0,08912829736946151 segundos
Na data 18/07/2023 08:40:00 a aplicação apresentou uma latência de 0,13936400617239997 segundos
Na data 18/07/2023 09:00:00 a aplicação apresentou uma latência de 2,71041257478452 segundos
Na data 18/07/2023 09:20:00 a aplicação apresentou uma latência de 0,9279229113025524 segundos
Na data 18/07/2023 09:40:00 a aplicação apresentou uma latência de 4,837793201045133 segundos
Na data 18/07/2023 10:00:00 a aplicação apresentou uma latência de 2,5243992862669984 segundos
Na data 18/07/2023 10:20:00 a aplicação apresentou uma latência de 3,0288982882763125 segundos
Na data 18/07/2023 10:40:00 a aplicação apresentou uma latência de 3,8260643202834763 segundos
Na data 18/07/2023 11:00:00 a aplicação apresentou uma latência de 34,23384289526465 segundos
Na data 18/07/2023 11:20:00 a aplicação apresentou uma latência de 21,33054632814052 segundos
Na data 18/07/2023 11:40:00 a aplicação apresentou uma latência de 29,606579224281575 segundos
Na data 18/07/2023 12:00:00 a aplicação apresentou uma latência de 34,83197215013977 segundos
Na data 18/07/2023 12:20:00 a aplicação apresentou uma latência de 27,964514208257818 segundos
Na data 18/07/2023 12:40:00 a aplicação apresentou uma latência de 31,787365863385737 segundos
Na data 18/07/2023 13:00:00 a aplicação apresentou uma latência de 43,780573587240134 segundos
Na data 18/07/2023 13:20:00 a aplicação apresentou uma latência de 38,043917640134 segundos
Na data 18/07/2023 13:40:00 a aplicação apresentou uma latência de 26,580186859654162 segundos
Na data 18/07/2023 14:00:00 a aplicação apresentou uma latência de 27,81742878176018 segundos
Na data 18/07/2023 14:20:00 a aplicação apresentou uma latência de 41,62026458063289 segundos
Na data 18/07/2023 14:40:00 a aplicação apresentou uma latência de 28,731906008223458 segundos
Na data 18/07/2023 15:00:00 a aplicação apresentou uma latência de 25,12068699802371 segundos
Na data 18/07/2023 15:20:00 a aplicação apresentou uma latência de 32,43453590801154 segundos
Na data 18/07/2023 15:40:00 a aplicação apresentou uma latência de 37,46454263807097 segundos
Na data 18/07/2023 16:00:00 a aplicação apresentou uma latência de 44,65658918828073 segundos
Na data 18/07/2023 16:20:00 a aplicação apresentou uma latência de 28,01637012651817 segundos
Na data 18/07/2023 16:40:00 a aplicação apresentou uma latência de 20,765434945340523 segundos
Na data 18/07/2023 17:00:00 a aplicação apresentou uma latência de 49,31886588202583 segundos
Na data 18/07/2023 17:20:00 a aplicação apresentou uma latência de 22,5128904144382 segundos
Na data 18/07/2023 17:40:00 a aplicação apresentou uma latência de 30,570371930381576 segundos
Na data 18/07/2023 18:00:00 a aplicação apresentou uma latência de 34,33580842029904 segundos
Na data 18/07/2023 18:20:00 a aplicação apresentou uma latência de 29,280584575636254 segundos
Na data 18/07/2023 18:40:00 a aplicação apresentou uma latência de 63,374238206137576 segundos
Na data 18/07/2023 19:00:00 a aplicação apresentou uma latência de 40,25950184485815 segundos
Na data 18/07/2023 19:20:00 a aplicação apresentou uma latência de 49,595803626092035 segundos
Na data 18/07/2023 19:40:00 a aplicação apresentou uma latência de 34,52664520407407 segundos
Na data 18/07/2023 20:00:00 a aplicação apresentou uma latência de 40,88758949778556 segundos
Na data 18/07/2023 20:20:00 a aplicação apresentou uma latência de 31,735455997280283 segundos

Se comporte como um especialista em estatística e métricas e forneça insights sobre a saúde da aplicação.
Faça sugestão de mudanças e diga qual o resultado esperado com a mudança.
Não explique nem repita meus dados.

Responda separado pelos tópicos:
Análise
Sugestões de melhorias
Resultados esperados

Essa é a análise realizada pela IA:

Analisando os dados acima, podemos observar que em alguns momentos a latência da aplicação foi extraordinariamente alta, como, por exemplo, os valores superiores aos 34 segundos nos momentos 11:00:00, 12:00:00, 18:00:00 e 19:20:00.

Sugestões de melhorias:
Dado que tais picos de latência ocorrem especificamente em determinados horários, algumas ações podem ser realizadas para reduzir este problema, como aumento do processamento do servidor para suportar essa alta demanda em esses horários, permitindo assim uma maior estabilidade na latência. Outra sugestão é a otimização das consultores que contribuem para esses picos, a fim de melhorar a eficiência da aplicação e reduzir o tempo gasto em consultas.

Resultados esperados:
Depois de realizar essas melhorias, espera-se um melhor desempenho no tempo de resposta da aplicação, especialmente durante os momentos em que a latência foi maior que o normal. Também espera-se um aumento na qualidade da experiência do usuário, já que eles poderão usufruir dessa aplicação sem longos tempos de espera entre as consultas.

Muito bacana, não é? Não é uma análise muito profunda, mas nos dá uma boa noção de possíveis ofensores e onde devemos atuar para que tenhamos melhorias nos números de latência da aplicação.

O que eu acho mais legal é pensar nas possibilidades que temos ao automatizar esse tipo de análise, por exemplo: um time tendo acesso a estas informações pode mitigar riscos, antecipando a resolução de problemas e incidentes, ou então em um cenário de crise, uma automação como esta pode garantir que os desenvolvedores sejam mais assertivos na tratativa de erros.

O código da Main fica assim:

 private static void Main(string[] args)
{
Console.WriteLine("Starting work");

var datadogConnect = new DatadogConnect()
{
ApiKey = "",
ApiUrl = "https://api.us3.datadoghq.com/api/v1",
AppKey = ""
};

var openAIConfigurations = new OpenAIConfigurations
{
ApiKey = "",
ApiUrl = "https://api.openai.com/"
};

IOpenAIClient openAIClient =
new OpenAIClient(openAIConfigurations);


Console.WriteLine("GET Datadog metrics - Latency");

var datadogRepository = new DatadogRepository(datadogConnect);

var fromDateUnix = CommonFunctions.DatetimeToUnix(DateTime.Now.AddDays(-3));
var toDateUnix = CommonFunctions.DatetimeToUnix(DateTime.Now);


var result = datadogRepository.Query(fromDateUnix, toDateUnix, "sum:trace.request.duration{env:local,service:currency-conversion}");

var listLatency = ListLatency(result).OrderBy(p => p.DateTimeRequest).TakeLast(50).ToList();

Console.WriteLine("Send data to OpenAI...");

var inputCompletion = new Completion
{
Request = new CompletionRequest
{
Prompts = new string[] { IARequest(listLatency) },

Model = "text-davinci-003",
MaxTokens = 1000
}
};

var iaResult = openAIClient.Completions.PromptCompletionAsync(inputCompletion).Result;

Console.WriteLine("");
Console.WriteLine("Result:");
Console.WriteLine("");
Console.WriteLine(iaResult.Response.Choices[0].Text);
Console.WriteLine("");
}

--

--

Leandro Belo
#LocalizaLabs

Há 10 anos atuando com análise e desenvolvimento de software, atualmente atuando como líder de engenharia na Localiza💚.