Vai al contenuto
Profilazione continua

Profilazione continua

La profilazione continua mostra come la vostra applicazione spende tempo CPU e memoria, funzione per funzione. Status200 espone un'API di acquisizione compatibile con Pyroscope, quindi tutto ciò che può inviare dati a un server Pyroscope (il profiler eBPF di Grafana Alloy o un SDK Pyroscope per il vostro linguaggio) può inviarli a Status200, e leggete il risultato come flame graph accanto a log, metriche e tracce.

Come funziona

Un profiler campiona i vostri processi e carica un profilo ogni pochi secondi sull'endpoint /pyroscope di Status200, con la vostra chiave di acquisizione. Status200 memorizza ogni profilo sotto il servizio che indica e lo disegna come flame graph in Profili di prestazioni.

flowchart TB subgraph profilers["Profiler"] direction LR alloy["Grafana Alloy (eBPF)"] sdk["SDK Pyroscope<br/>nella vostra app"] end alloy -->|"API push"| endpoint["Status200 /pyroscope"] sdk -->|"API ingest o push"| endpoint endpoint --> profiles["Profili di prestazioni"] profiles -.->|"ID di traccia e di span"| traces["Tracce collegate"]

Come i profili arrivano a Status200

Prima di iniziare

Vi serve una chiave di acquisizione della telemetria di tipo Server. Se non ne avete ancora una:

  1. Aprire le chiavi di acquisizione

    Andate in Prodotti → Impostazioni del progetto, aprite Telemetria e APM nel menu laterale e selezionate Chiavi di acquisizione.

    La pagina delle chiavi di acquisizione della telemetria nelle impostazioni del progetto

  2. Creare una chiave

    Fate clic su Crea chiave di ingestione. La finestra di dialogo ha già il nome della chiave compilato e Server selezionato (il tipo di chiave con cui invia un'applicazione o un collector), quindi fate clic su Crea chiave di ingestione per crearla, oppure rinominatela prima.

  3. Copiare il segreto

    La nuova chiave si apre nella sua pagina. Copiatene la Chiave segreta: è il token di acquisizione che gli esempi qui sotto chiamano YOUR_STATUS200_INGESTION_TOKEN.

    La pagina di una chiave di acquisizione della telemetria, con la sua chiave segreta

Endpoint di acquisizione

ImpostazioneValore
URL di base (indirizzo del server Pyroscope)https://status200.ru/pyroscope
Intestazione di autenticazionex-status200-token: YOUR_STATUS200_INGESTION_TOKEN

I client aggiungono il proprio percorso all'URL di base (/ingest per la maggior parte degli SDK Pyroscope, /push.v1.PusherService/Push per Grafana Alloy e per l'SDK .NET da v0.14), quindi configurate sempre solo l'URL di base, senza barra finale.

Status200 legge il token di acquisizione da una qualsiasi di queste fonti; usate quella supportata dal vostro client:

MetodoQuando usarlo
Intestazione x-status200-tokenClient che permettono di aggiungere intestazioni personalizzate.
Authorization: Bearer <token>SDK con un'opzione authToken / auth_token: è ciò che inviano.
Autenticazione HTTP basic, con il token come password (qualsiasi nome utente)Client che offrono solo utente e password per l'autenticazione basic.
Nota

Ospitate Status200 in autonomia? Sostituite https://status200.ru con il vostro host, per esempio https://YOUR-ONEUPTIME-HOST/pyroscope.

Formati di profilo supportati

FormatoInviato daSupportato
pprof (protobuf binario, eventualmente compresso con gzip)SDK Pyroscope per Go, Node.js e .NET; Grafana AlloySì
Testo folded / collapsedSDK Pyroscope per Python, Ruby e Rust (il loro formato di caricamento predefinito)Sì
JFR (Java Flight Recorder)Agente Java di PyroscopeNon ancora: usate Grafana Alloy per i servizi Java

Inviare i profili

Grafana Alloy profila ogni processo di un host senza modifiche al codice ed è il modo consigliato per iniziare. Un SDK Pyroscope, invece, gira all'interno della vostra applicazione.

Grafana Alloy

Grafana Alloy raccoglie con eBPF i profili CPU di ogni processo di un host Linux: nessun agente nella vostra applicazione e nessuna modifica al codice. Funziona per Go, Rust, C/C++, Java, Python, Ruby, PHP, Node.js e .NET.

Create la configurazione di Alloy:

alloy-config.alloyHCL
discovery.process "all" {
  refresh_interval = "60s"
}

discovery.relabel "alloy_profiles" {
  targets = discovery.process.all.targets

  rule {
    action       = "replace"
    source_labels = ["__meta_process_exe"]
    target_label  = "service_name"
  }
}

pyroscope.ebpf "default" {
  targets    = discovery.relabel.alloy_profiles.output
  forward_to = [pyroscope.write.status200.receiver]

  collect_interval = "15s"
  sample_rate      = 97
}

pyroscope.write "oneuptime" {
  endpoint {
    url = "https://status200.ru/pyroscope"
    headers = {
      "x-status200-token" = "YOUR_STATUS200_INGESTION_TOKEN",
    }
  }
}

Eseguitelo con Docker. eBPF richiede un container privilegiato con lo spazio dei nomi PID dell'host:

docker-compose.ymlYAML
services:
  alloy:
    image: grafana/alloy:latest
    privileged: true
    pid: host
    volumes:
      - ./alloy-config.alloy:/etc/alloy/config.alloy
      - /proc:/proc:ro
      - /sys:/sys:ro
    command:
      - run
      - /etc/alloy/config.alloy

Oppure eseguitelo direttamente sull'host:

Bash
alloy run alloy-config.alloy

La regola di rietichettatura dà al servizio di ogni profilo il nome dell'eseguibile del processo.

Go

L'SDK Go carica pprof. Puntate il suo indirizzo del server all'URL di base di Status200 e passate il vostro token di acquisizione come token di autenticazione:

Go
import "github.com/grafana/pyroscope-go"

pyroscope.Start(pyroscope.Config{
    ApplicationName: "my-service",
    ServerAddress:   "https://status200.ru/pyroscope",
    AuthToken:       "YOUR_STATUS200_INGESTION_TOKEN",
    ProfileTypes: []pyroscope.ProfileType{
        pyroscope.ProfileCPU,
        pyroscope.ProfileAllocObjects,
        pyroscope.ProfileAllocSpace,
        pyroscope.ProfileInuseObjects,
        pyroscope.ProfileInuseSpace,
        pyroscope.ProfileGoroutines,
    },
})

Node.js

L'SDK Node.js carica pprof:

JavaScript
const Pyroscope = require("@pyroscope/nodejs");

Pyroscope.init({
  serverAddress: "https://status200.ru/pyroscope",
  appName: "my-service",
  authToken: "YOUR_STATUS200_INGESTION_TOKEN",
});

Pyroscope.start();

Python

L'SDK Python carica testo folded:

Python
import pyroscope

pyroscope.configure(
    application_name="my-service",
    server_address="https://status200.ru/pyroscope",
    auth_token="YOUR_STATUS200_INGESTION_TOKEN",
)

.NET

Il profiler .NET di Pyroscope è un profiler CLR nativo: non richiede modifiche al codice e si attiva interamente tramite variabili d'ambiente. Scaricate la versione per la vostra immagine da pyroscope-dotnet releases (glibc o musl per Alpine, x86_64 o aarch64) e caricatela nel runtime:

DockerfileDockerfile
FROM alpine:3.20 AS pyroscope-profiler
ARG PYROSCOPE_DOTNET_VERSION=1.5.1
ADD https://github.com/grafana/pyroscope-dotnet/releases/download/pyroscope-${PYROSCOPE_DOTNET_VERSION}/pyroscope.${PYROSCOPE_DOTNET_VERSION}-glibc-x86_64.tar.gz /tmp/pyroscope.tar.gz
RUN mkdir -p /pyroscope && tar -xzf /tmp/pyroscope.tar.gz -C /pyroscope

FROM mcr.microsoft.com/dotnet/aspnet:10.0
# ... your application ...
COPY --from=pyroscope-profiler /pyroscope /pyroscope
ENV CORECLR_ENABLE_PROFILING=1
ENV CORECLR_PROFILER={BD1A650D-AC5D-4896-B64F-D6FA25D6B26A}
ENV CORECLR_PROFILER_PATH=/pyroscope/Pyroscope.Profiler.Native.so
ENV LD_PRELOAD=/pyroscope/Pyroscope.Linux.ApiWrapper.x64.so
ENV LD_LIBRARY_PATH=/pyroscope

Poi puntatelo a Status200, per esempio nel vostro ambiente Kubernetes / Helm:

Bash
PYROSCOPE_APPLICATION_NAME=my-service
PYROSCOPE_PROFILING_ENABLED=1
PYROSCOPE_SERVER_ADDRESS=https://status200.ru/pyroscope
PYROSCOPE_BASIC_AUTH_USER=oneuptime
PYROSCOPE_BASIC_AUTH_PASSWORD=YOUR_STATUS200_INGESTION_TOKEN

Il token di acquisizione va nella password dell'autenticazione basic. Il nome utente può essere qualsiasi valore non vuoto, ma il profiler non invia alcuna credenziale se non sono impostati entrambi. Per inviare invece il token come intestazione, impostate PYROSCOPE_HTTP_HEADERS={"x-status200-token":"YOUR_STATUS200_INGESTION_TOKEN"}.

Come si passa il token dipende dalla versione del profiler. Le versioni 1.5 e successive ignorano PYROSCOPE_AUTH_TOKEN, quindi se aggiornate da una versione precedente mantenendo quell'impostazione, ogni caricamento viene rifiutato con 401:

Versione di pyroscope-dotnetCarica suImpostazione del token
v0.13 e precedenti/pyroscope/ingestPYROSCOPE_AUTH_TOKEN
da v0.14 a 1.4/pyroscope/push.v1.PusherService/PushPYROSCOPE_AUTH_TOKEN
1.5 e successive/pyroscope/push.v1.PusherService/PushPYROSCOPE_BASIC_AUTH_USER=oneuptime e PYROSCOPE_BASIC_AUTH_PASSWORD=<token> (vanno impostate entrambe), oppure PYROSCOPE_HTTP_HEADERS={"x-status200-token":"<token>"}

Le versioni precedenti alla 1.0 hanno il tag v<version>-pyroscope invece di pyroscope-<version> (per esempio https://github.com/grafana/pyroscope-dotnet/releases/download/v0.13.0-pyroscope/pyroscope.0.13.0-glibc-x86_64.tar.gz); il GUID del profiler e i nomi dei file sono gli stessi in ogni versione.

La profilazione della CPU è attiva per impostazione predefinita. Le profilazioni di tempo reale, allocazioni, eccezioni e contesa dei lock sono facoltative: impostate PYROSCOPE_PROFILING_WALLTIME_ENABLED, PYROSCOPE_PROFILING_ALLOCATION_ENABLED, PYROSCOPE_PROFILING_EXCEPTION_ENABLED o PYROSCOPE_PROFILING_LOCK_ENABLED su true. Le etichette statiche vanno in PYROSCOPE_LABELS (key:value,key:value).

Il profiler carica ogni 15 secondi e non comprime i caricamenti, quindi un servizio sotto carico può inviare diversi MB per caricamento. L'ingress di Status200 accetta fino a 16 MB su /pyroscope; se davanti a Status200 c'è un altro proxy (per esempio ingress-nginx, il cui proxy-body-size predefinito è 1 MB), alzate anche il suo limite di dimensione per /pyroscope, altrimenti i caricamenti grandi vengono rifiutati con 413 prima di raggiungere Status200.

Java

L'agente Java di Pyroscope carica i profili in formato JFR, che Status200 non acquisisce ancora. Profilate invece i servizi Java con Grafana Alloy (la scheda Grafana Alloy): cattura i profili CPU della JVM senza agente né modifiche al codice.

Ruby e Rust funzionano come Go, Node.js e Python: installate l'SDK Pyroscope per il vostro linguaggio e impostate l'indirizzo del server su https://status200.ru/pyroscope con il vostro token di acquisizione come token di autenticazione (oppure, se la vostra versione dell'SDK offre solo l'autenticazione basic, come password basic).

Tipi di profilo supportati

Un pprof può dichiarare più tipi di campione; ogni profilo caricato viene memorizzato sotto uno di essi: il tempo CPU (cpu in nanosecondi) se lo ha, altrimenti il tempo reale, altrimenti i byte in uso e poi quelli allocati, altrimenti il primo tipo che dichiara. Qualsiasi tipo viene memorizzato e si può consultare; i tipi seguenti hanno raggruppamento, unità ed etichette dedicati in Status200:

Tipo di profiloMostrato comeUnità
cpu, samplesTempo CPUnanosecondi
wallTempo realenanosecondi
inuse_space, alloc_space, heapMemoria (byte)byte
inuse_objects, alloc_objectsMemoria (numero di oggetti)conteggio
mutex, contention, blockContesa dei locknanosecondi
goroutineGoroutines (Go)conteggio

Tutto il resto (per esempio un tipo di campione personalizzato) compare in «Altro» con il suo nome originale.

Verificare che funzioni

  1. Controllare il token

    Gli endpoint di acquisizione rispondono 401 a un token mancante o non valido, ma la maggior parte dei profiler non lo mostra da nessuna parte dove lo vedreste (il profiler .NET, per esempio, registra le risposte HTTP solo a livello debug). Interrogate direttamente l'endpoint di convalida:

    Bash
    curl -i -H "x-status200-token: YOUR_STATUS200_INGESTION_TOKEN" \
      https://status200.ru/otlp/v1/validate

    Un token valido restituisce 200 con {"valid": true, ...}, e il suo keyType deve essere Server: anche una chiave per browser è valida, ma non può inviare profili. Un token sconosciuto, revocato, disattivato o scaduto restituisce 401.

  2. Aprire la pagina dei profili

    Nella dashboard di Status200 andate in Prodotti → Profili di performance. Con l'intervallo di raccolta di 15 secondi di Alloy (o l'intervallo di caricamento degli SDK, da 10 a 15 secondi), i primi profili e i loro flame graph compaiono entro un paio di minuti dall'avvio dell'agente.

  3. Controllare il servizio

    I profili vengono associati al servizio di telemetria indicato da application_name / appName / PYROSCOPE_APPLICATION_NAME dell'SDK (o dal nome dell'eseguibile del processo con la regola di rietichettatura di Alloy vista sopra).

  4. Ancora niente? Guardate lo stato dei caricamenti

    Per il profiler .NET, impostate DD_TRACE_DEBUG=1 sull'applicazione per un minuto: registrerà una riga PyroscopePprofSink <status> per ogni caricamento. 200 significa che Status200 l'ha accettato; 401 è il token; 404 di solito significa che a PYROSCOPE_SERVER_ADDRESS manca il suffisso /pyroscope; 413 significa che un proxy davanti a Status200 ha rifiutato il caricamento per le sue dimensioni (vedete la scheda .NET in Inviare i profili). Se ospitate Status200 in autonomia, il log di accesso dell'ingress (nginx) registra lo stesso stato per ogni richiesta a /pyroscope.

Esplorare i profili in Status200

Prodotti → Profili di performance apre il Profiler sulla sua Panoramica. Risponde a parole prima di qualsiasi grafico: dove va il tempo («JSON.parse occupa 42% del totale di tempo CPU in checkout.») e, quando la funzione più impegnata è di una libreria o del runtime, la funzione del vostro codice che occupa di più, con il codice di librerie e runtime che chiama. In alto, scegliete un servizio, un tipo di profilo per cui ha dati (Tempo CPU, Tempo reale, Memoria, Allocazioni, Lock o Goroutines, oppure un tipo in Altri tipi di profilo) e un intervallo.

SchedaCosa mostra
Dove va il tempo CPUTutti i profili dell'intervallo, uniti in un unico flame graph. Più un frame è largo, più grande è la sua quota. Fate clic su un frame per ingrandirlo.
FunzioniLe funzioni che occupano di più, ordinate per Proprio (il tempo nel codice proprio della funzione), Totale (con tutto ciò che chiama) o Il tuo codice (le vostre funzioni, ciascuna con il codice di librerie e runtime che chiama: il tempo che una modifica può recuperare).
Servizi profilatiOgni servizio profilato, i più impegnati per primi. I thread del kernel che il profiler eBPF campiona sono nascosti.

Confrontare due intervalli

Confronta con stabilisce con cosa viene confrontato l'intervallo: Il periodo precedente, La stessa ora di ieri, La stessa ora della settimana scorsa, oppure un deploy in Prima e dopo una modifica. Si confrontano le quote, non i totali, quindi più traffico da solo non sposta nulla. Il titolo nomina la funzione la cui quota è cresciuta di più, e il vostro codice che è cresciuto; il flame graph diventa Cosa è cambiato, dove i frame rossi occupano una quota maggiore dopo e quelli verdi una minore; e Funzioni cambiate elenca la quota di ogni funzione prima e dopo.

Una funzione

Fate clic su una funzione per aprirne il pannello: la sua quota come Proprio, Totale e Il tuo codice, Chi la chiama e Cosa chiama, un link al suo file e alla sua riga nel vostro repository quando ne è collegato uno, e Evidenzia nel flame graph. Per una funzione di una libreria o del runtime, il pannello nomina la funzione del vostro codice che la chiama, dove una modifica può renderla più economica. Un link sotto le quote imposta un avviso sulla quota della funzione, sopra quanto occupa oggi: vedete Monitor profili.

Quando una funzione del vostro codice occupa almeno il 5% del tempo o della memoria del profilo, o la sua quota è cresciuta di 3 punti o più rispetto all'intervallo con cui è confrontata, il pannello offre Correggi con l'IA: Status200 AI avvia un'attività nel repository che contiene la funzione, con il profilo come prova, e apre una pull request da rivedere (vedete Code). Status200 AI legge i profili anche nelle sue risposte e nelle indagini, quindi potete chiedergli quali funzioni usano più tempo CPU.

Un singolo profilo

Tutti i profili elenca ogni caricamento. La pagina di un profilo ha tre viste:

VistaCosa mostra
Flame graphOgni barra è una funzione dello stack di chiamate, e la sua larghezza è proporzionale al tempo o alle risorse consumati. Fate clic su una funzione per ingrandirla e vederne chiamanti e chiamate.
Top functionsLe funzioni del profilo, ordinate per tempo proprio o totale. Solo il mio codice nasconde i frame delle librerie.
Diff vs. baselineIl profilo confrontato con un periodo precedente (rispetto a 1 ora fa, rispetto a ieri o rispetto alla scorsa settimana), con le funzioni Most regressed e Most improved.

Download pprof salva il profilo per strumenti locali come go tool pprof.

Correlazione con le tracce

Quando un profilo contiene ID di traccia e di span (per esempio come etichette di campione trace_id / span_id), potete passare direttamente da uno span lento di una traccia al profilo CPU o di memoria corrispondente per capire esattamente quale codice era in esecuzione, e Open linked trace fa il percorso inverso.

La scheda Profilo di uno span include anche i campioni collegati agli span annidati sotto di esso, perché i profiler spesso attribuiscono il tempo CPU di una richiesta a uno span figlio anziché allo span della richiesta stessa.

La pagina di una traccia rimanda anche al Profiler sul servizio della traccia, per i 15 minuti prima e dopo, quando quel servizio era profilato in quel momento, e la pagina Profili di prestazioni di un servizio o di un host apre il Profiler su quel servizio o host.

Conservazione dei dati

I profili vengono conservati per la durata della conservazione della telemetria del vostro progetto: Impostazioni del progetto → Telemetria e APM → Conservazione dei dati imposta la Conservazione predefinita (giorni), 15 giorni se non la cambiate. I dati vengono eliminati automaticamente alla fine del periodo di conservazione. I piani che includono eccezioni alla conservazione possono anche tenere i profili più o meno a lungo rispetto al resto della telemetria, o impostare la conservazione per singolo servizio nella pagina Impostazioni del servizio.

Passaggi successivi