Una volta che inizi a scavare attorno a New Relic, inizi a capire quante funzioni interessanti il servizio deve aiutare a monitorare le prestazioni e la salute della tua applicazione. È stato davvero difficile scegliere solo cinque cose di cui parlare, quindi piuttosto che concentrarsi sulle caratteristiche ovvie, diamo un'occhiata ad alcune delle funzionalità meno esagerate fornite da New Relic e su come possiamo usarle in modi interessanti e talvolta non ortodossi.
Quando ti abbiamo lasciato l'ultima volta, abbiamo avuto un'applicazione di base "Hello World" Rails (chiamata Nuovo Relic_rails1
, vivere in ~ / project / tmp / New Relic
). Continueremo a utilizzare questa app, estenderla e vedere se possiamo usarla per dimostrare le funzionalità di New Relic che vedremo in.
Questo contenuto è stato commissionato da New Relic ed è stato scritto e / o modificato dal team Tuts +. Il nostro obiettivo con i contenuti sponsorizzati è quello di pubblicare tutorial pertinenti e obiettivi, case study e interviste ispiratrici che offrono un vero valore educativo ai nostri lettori e ci consentono di finanziare la creazione di contenuti più utili.
Questa è una caratteristica di New Relic che di solito non rende la prima pagina del materiale di marketing. Non c'è molto da fare, ma se ci pensi, è più importante assicurarsi che la tua app sia effettivamente funzionante e accessibile dai tuoi utenti?
In primo luogo, quando si imposta il monitoraggio della disponibilità, l'applicazione ottiene un bel asterisco sul dashboard principale delle applicazioni:
È un bel promemoria visivo, quindi puoi vedere quali app necessitano ancora di monitoraggio della disponibilità attivato.
Vediamo ora come possiamo impostare il monitoraggio della disponibilità e cosa possiamo ottenere da esso. In primo luogo, devi entrare nella tua applicazione e poi entrare Impostazioni-> Monitoraggio disponibilità. Vedrai qualcosa di simile a questo:
Devi fornire un URL a cui desideri che New Relic esegua il ping, selezionare la casella, salvare le modifiche e sei pronto. New Relic inizierà a colpire il tuo URL ogni 30 secondi. Ma il divertimento non finisce qui. New Relic eseguirà il ping dell'URL tramite una richiesta HEAD HTTP (e riterrà tutto OK se riceve un codice di risposta 200), ma è possibile fornire una stringa di risposta che si desidera venga cercata da New Relic, nel qual caso eseguirà una richiesta GET e esaminare la risposta per la stringa che hai fornito. Questo può essere molto utile se hai una pagina 'Controllo sanitario' personalizzata che vuoi colpire.
Puoi anche impostare la notifica via email se si verificano tempi di inattività:
Ora che stai monitorando la disponibilità, avrai accesso a un bel rapporto che ti mostrerà visivamente quando si sono verificati dei tempi di inattività:
In effetti, molti dei tuoi grafici (ad esempio la panoramica dell'applicazione) avranno questa indicazione visiva:
Devi ammettere che è una funzionalità piuttosto carina per un così piccolo sforzo.
Ovviamente, puoi disabilitare e riattivare il monitoraggio (tramite l'API REST di New Relic) quando esegui distribuzioni, per assicurarti di non ottenere eventi di downtime spuri.
Un altro effetto collaterale interessante è che se stai distribuendo il tuo progetto domestico su Heroku con un solo dino, puoi usare questa funzionalità ping per impedire che il tuo dyno dorme, il che può rendere il tuo sito fastidiosamente lento se non hai molto traffico.
Se si verificano errori imprevisti nella tua applicazione, New Relic registrerà questi per te e ti darà un bel grafico. La nostra piccola app "Hello World" si è comportata in modo ammirevole per il momento, quindi non c'è niente da vedere su questo fronte. Ma possiamo di proposito interrompere la nostra app e vedere cosa ci offre New Relic.
Modifichiamo il nostro HelloController
per generare un errore casualmente circa il 50% delle volte:
classe HelloController < ApplicationController def index if rand(2) == 0 raise 'Random error' end end end
Effettueremo ora alcune centinaia di chiamate alla nostra app e vedremo cosa succede:
ab -n 300 -c 10 http://127.0.0.1:3000/
Il nostro grafico di errore New Relic ora sembra molto più interessante:
E possiamo approfondire per ottenere alcuni dettagli:
Come puoi vedere, possiamo ordinare i nostri errori e filtrarli, nonché esaminare separatamente gli errori dalle richieste web e le attività in background. Questo è un materiale incredibilmente potente per aiutarti a diagnosticare e risolvere i problemi con la tua applicazione. Ovviamente puoi anche vedere la traccia dello stack per ogni errore:
Ci sono servizi specificamente dedicati alla cattura degli errori dalla tua applicazione, alcuni dei più noti sono Airbrake e Bugsnag. Si tratta di servizi a pagamento utilizzati da molte applicazioni, ma la funzionalità appena fornita da New Relic rende questi servizi ridondanti. Infatti, se potessimo inviare errori personalizzati a New Relic (piuttosto che lasciargli catturare errori che non avevamo salvato) potremmo fare un caso convincente per non utilizzare un servizio di raccolta errori separato (e risparmiare un po 'di soldi e sbarazzarci di un extra gemma nel processo).
Mentre New Relic non documenta alcun modo per farlo, possiamo sempre andare alla fonte per vedere se ciò che vogliamo fare è difficile. Mi sembra che dovrebbe essere piuttosto banale per noi inviare errori personalizzati a New Relic, quindi proviamo. Modificheremo nuovamente l'azione del controller per salvare tutti gli errori e inviare un errore personalizzato a New Relic:
classe HelloController < ApplicationController def index if rand(2) == 0 raise 'Random error' end rescue New Relic::Agent.notice_error(StandardError.new("I caught and reraised an error")) end end
Dopo aver effettuato alcune altre chiamate e atteso il passaggio dei dati, vediamo quanto segue:
Ha funzionato, il nostro errore personalizzato sta arrivando! New Relic può sicuramente funzionare come nostro servizio di raccolta degli errori. Ovviamente stiamo usando un'interfaccia privata che non è molto bella, ma possiamo mettere il notice_error
chiama dietro una facciata che renderà le cose un po 'più facili per noi se l'interfaccia cambia.
Un approccio ancora migliore potrebbe essere quello di non trattare gli errori personalizzati come errori regolari, ma invece di creare una metrica personalizzata per tracciare e quindi creare una dashboard personalizzata da visualizzare. In questo modo non usiamo alcuna funzionalità non documentata e otterremmo comunque tutti i vantaggi: brillante!
New Relic traccia normalmente le tue transazioni per te:
Sarai in grado di vedere dove trascorre la maggior parte del tempo la tua applicazione (ad es. Nel controller, nel modello, nel database, ecc.). Tuttavia, New Relic non acquisirà una traccia dettagliata a meno che la transazione richieda più tempo di Appdex * 4 secondi. Normalmente questo è OK, ma a volte hai transazioni che sono molto più importanti per la tua applicazione o per la tua azienda. Forse queste transazioni sono estremamente voluminose o riguardano eventi importanti come i pagamenti. Basti dire che è necessario assicurarsi che questo tipo di transazione funzioni sempre estremamente bene.
Il fatto è che, quando una transazione è così importante, probabilmente ha già ricevuto molto amore da parte tua e potrebbe comportarsi abbastanza bene. Supponiamo che tu abbia una transazione con un throughput estremamente elevato (si verifica molte volte al minuto). Se questa transazione sta funzionando in modo ottimale, tutto andrà bene, ma se la performance dovesse degradarsi leggermente, a causa del volume del traffico potrebbe avere un effetto sproporzionatamente negativo sull'applicazione. Quello che vuoi è qualcosa di simile:
Questo è esattamente ciò che le principali transazioni chiave ti danno!
Prima di impostare una transazione chiave per la nostra app "Hello World", dobbiamo creare una transazione più interessante che di solito si comporta bene, ma a volte si comporta in modo un po 'male. Costruiremo la capacità di guardare marche e modelli di auto e ottenere una macchina particolare per rallentare la transazione. In primo luogo il percorso:
New RelicRails1 :: Application.routes.draw ottiene 'random_car', in: 'cars # show_random' root 'ciao # index' fine
Vogliamo essere in grado di ottenere un'auto a caso, questo verrà mappato al CarsController
:
classe CarsController < ApplicationController def show_random @car = Car.offset(rand(Car.count)).first if @car.make == 'Ford' sleep(2) end end end
Prendiamo una macchina a caso dal database e se la macchina fa "Ford" avremo una transazione lenta tra le nostre mani. Certo, abbiamo bisogno di un Auto
modello:
auto di classe < ActiveRecord::Base end
Dovremo configurare il nostro database per usare MySql in fase di sviluppo (l'ho fatto, ma puoi continuare a farlo sqlite
):
base: adattatore & BASE: codifica mysql2: utf8 host: "localhost" nome utente: "root" max_connections: 10 timeout: 5000 sviluppo: & DEV <<: *BASE database: "New Relic_rails1_development" sql_log_level: debug
Abbiamo bisogno di una migrazione per creare un macchine
tavolo:
auto di classe < ActiveRecord::Migration def change create_table :cars, force: true do |t| t.string :make t.string :model end end end
E abbiamo bisogno di alcuni dati sulle sementi che inseriremo nella nostra db / seeds.rb
file:
Car.create (marca: 'Ford', modello: 'Mondeo') Car.create (marca: 'Honda', modello: 'Accord') Car.create (marca: 'Audi', modello: 'A4') Car. creare (marca: 'Lamborghini', modello: 'Murcielago') Car.create (marca: 'Toyota', modello: 'Prius')
Infine dovremmo probabilmente avere una visione Auto / show_random.html.erb
:
Rendere: <%= @car.make %>
Modello: <%= @car.model %>
Dovrai anche aggiungere il mysql2
gemma per il Gemfile
se sei andato con MySql. Dopo questo, abbiamo solo bisogno di creare e popolare il database, riavviare il nostro server e siamo a posto:
bundle rake db: crea && rake db: migrate && rake db: seed rails s
Dovrai premere l'URL per assicurarti che New Relic riconosca che questa transazione esiste:
arricciamento localhost: 3000 / random_car
Ora siamo pronti a monitorare questa transazione come una transazione chiave. Innanzitutto, passa alla scheda della transazione:
Fai clic sul pulsante "Traccia una transazione chiave" e seleziona la nostra transazione appena creata:
Possiamo dare un nuovo nome alla nostra nuova transazione chiave, scegliere l'Apdex T di cui siamo felici e impostare alcuni avvisi. Quando la nostra transazione richiede più tempo dell'Apdex che abbiamo scelto, New Relic acquisirà una traccia dettagliata che saremo in grado di utilizzare per capire da dove proviene il problema di prestazioni. Facciamo alcune chiamate contro il nostro nuovo URL e vediamo quali dati otteniamo:
ab -n 300 -c 20 http://127.0.0.1:3000/random_car
Hmm, sembra che alcune delle nostre transazioni siano frustranti per i nostri utenti:
Vediamo se New Relic ha catturato alcune tracce di transazione per noi:
Diamo un'occhiata a una di queste tracce. Ci sono voluti circa 2 secondi per rispondere, ma solo 10 millisecondi stavano usando la CPU:
Tutte le nostre istruzioni SQL erano veloci, quindi il database non è il problema:
Sembra che la maggior parte del tempo venga spesa nell'azione del controller:
Scaviamo un po 'nella traccia. Sembra che SQL SELECT sia veloce, a Car.find
era anche veloce. Quindi perdiamo circa 2 secondi, seguito da un rendering dei template molto veloce:
New Relic ha gentilmente evidenziato per noi dove abbiamo perso quei due secondi. Dobbiamo guardare il nostro codice del controller dopo un Car.find
chiamata:
classe CarsController < ApplicationController def show_random @car = Car.offset(rand(Car.count)).first if @car.make == 'Ford' sleep(2) end end end
Hmm, il SELECT iniziale deve essere il Car.count
chiamata, e il Car.find
, deve essere dovuto al Car.offset
chiamata. Il nostro grande ritardo è giusto dopo questo però. Ahh guarda questo, una persona sciocca ha messo un secondo ritardo nel nostro codice quando la marca della vettura è "Ford". Questo spiegherebbe perché il nostro ritardo di 2 secondi si verifica solo una parte del tempo. Farò meglio a prendi la colpa
sul nostro repository per scoprire chi ha messo quel codice orribile lì dentro! Ripensandoci, è meglio che no, perché potrebbe dire che ero io.
Ogni volta che effettui chiamate ad altri servizi dall'interno dell'app (ad esempio una richiesta HTTP a un'API come Twitter), New Relic li monitorerà come chiamate esterne. Oggigiorno un'applicazione seria può integrarsi con un numero di API esterne. Spesso questi servizi esterni possono peggiorare significativamente le prestazioni della tua app, specialmente se fai queste chiamate in-process. New Relic può mostrare quali delle tue chiamate esterne sono più lente, quali quelle che chiami di più e che rispondono in media alla media più lenta. Puoi anche guardare le prestazioni di ciascuno dei servizi esterni che utilizzi individualmente. Proviamolo.
Creeremo un nostro servizio esterno, costruendo una piccola app Sinatra. Per prima cosa installiamo la gemma:
gemma installa sinatra
Crea un nuovo file per il nostro servizio:
tocca external_service.rb
E inserisci il seguente codice:
richiede 'sinatra' get '/ hello' fa sleep_time = rand (2000) /1000.0 sleep (sleep_time) "Hello External World # sleep_time!" fine
Questo servizio verrà sospeso per un tempo casuale (tra 0 e 2000 millisecondi) e quindi restituirà una risposta "Ciao" con il tempo per cui ha dormito. Ora tutto ciò che dobbiamo fare è avviarlo:
ruby external_service.rb
Tornando alla nostra app Rails costruiremo un nuovo controller per chiamare il nostro servizio esterno. Useremo questa rotta:
New RelicRails1 :: Application.routes.draw do ... ottieni 'external_call', per: 'external_calls # external_call' ... end
Il nostro controller chiamerà il nostro servizio Sinatra via HTTP:
richiede la classe 'net / http' ExternalCallsController < ApplicationController def external_call url = URI.parse('http://localhost:4567/hello') external_request = Net::HTTP::Get.new(url.to_s) external_response = Net::HTTP.start(url.host, url.port) do |http| http.request(external_request) end @result = external_response.body end end
E abbiamo bisogno di una vista per visualizzare i risultati:
<%= @result %>
Tutto ciò che dobbiamo fare ora è effettuare alcune chiamate al nostro nuovo endpoint:
ab -n 100 -c 10 http://127.0.0.1:3000/external_call
Vediamo cosa ha prodotto New Relic per noi.
New Relic ha effettivamente raccolto la nostra nuova chiamata esterna. Abbiamo le chiamate totali al minuto che stiamo facendo all'endpoint esterno. E il totale che è stato speso rispondendo dal servizio esterno. Ovviamente il nostro grafico sembra un po 'scarso poiché abbiamo solo un servizio esterno, il che significa che non abbiamo nulla da confrontare.
Possiamo anche ottenere dati più dettagliati sulla chiamata esterna specifica e su dove nella nostra app viene effettuata questa chiamata:
Possiamo vedere quando sono state fatte le chiamate, il throughput e il tempo medio di risposta. Questo può sembrare semplice, ma quando hai un'app con molti servizi esterni questa funzione può darti una panoramica molto buona di come questi servizi esterni stanno funzionando, così come quando e dove vengono utilizzati. Ciò può consentire di prendere decisioni riguardanti il caching di alcune risposte del servizio esterno, se possibile, o anche di abbandonare particolari servizi esterni se le loro prestazioni non sono all'altezza. E non devi più discutere queste cose basandoti su parametri intuitivi e misurazioni casalinghe, avrai dati concreti per dimostrare il tuo punto di vista.
Non c'è nulla di più frustrante per uno sviluppatore di avere la tua applicazione cadere a causa di un picco di traffico. Tutto andava liscio fino a quando sono arrivati centinaia di utenti extra e la tua applicazione è esplosa. Avevi la sensazione che ciò potesse accadere, ma non potevo esserne sicuro: l'atteggiamento di attesa e di osservazione sembrava essere l'approccio più pragmatico. Bene con i nuovi report di capacità e scalabilità di Relic, non è più necessario "aspettare e vedere". Puoi capire subito in che misura la tua app si sta ridimensionando, puoi eseguire test di caricamento e vedere immediatamente se l'applicazione è in grado di gestire il carico. È possibile osservare le tendenze del tempo di risposta delle applicazioni man mano che la base di utenti cresce e prevedere quando sarà necessario aggiungere capacità. Tutte queste sono cose veramente meravigliose.
Per prima cosa, diamo un'occhiata ai rapporti sulla capacità:
Hmm, questo mostra un grande picco, ma per il resto niente. Bene, stiamo correndo in modalità sviluppo, quindi è comprensibile. Quel picco è per quando abbiamo fatto un po 'di richieste contemporaneamente poco fa. Come puoi vedere quando abbiamo fatto quelle richieste simultanee, abbiamo superato la nostra povera istanza di Webrick. Se si trattava di produzione e il carico era costante, la nostra istanza sarebbe sempre occupata al 100%, il che probabilmente indica che abbiamo bisogno di un'altra istanza.
Il rapporto dell'analisi di istanza è leggermente diverso:
Nel nostro caso non ne ricaviamo molto, ma normalmente ci mostra il numero di istanze in esecuzione e il numero di istanze in cui dobbiamo effettivamente gestire il carico se tutte le istanze erano occupate al 100%. Quindi, se avessimo eseguito 10 istanze e il carico dell'istanza simultanea fosse 2, potremmo facilmente dimezzare (o anche più della metà) il numero di istanze in esecuzione e non degradare affatto le prestazioni. Per una piccola app che esegue solo poche istanze, questo non è un grosso problema, ma per una grande applicazione con dozzine e centinaia di istanze, questo può tradursi in notevoli risparmi sui costi.
E poi ci sono i rapporti di scalabilità. Il rapporto sui tempi di risposta è probabilmente il più interessante / importante:
Ancora una volta, il nostro grafico è molto distorto perché è un'app di sviluppo che abbiamo giocato in modo casuale. L'idea con questo report è che con l'aumento della velocità di trasmissione della tua applicazione (più richieste al minuto), il tempo di risposta dovrebbe rimanere vicino alla costante (ad esempio, le prestazioni non diminuiscono quando c'è più traffico). Ciò significa che dovresti sempre vedere qualcosa di simile a una linea piatta qui. Se la tua linea è in forte pendenza verso l'alto, probabilmente la tua app non riesce a gestire il traffico e potresti aver bisogno di cercare di aggiungere più capacità. Dove aggiungere la capacità è completamente un'altra questione (ad esempio capacità del database, più server, ecc.). Gli altri due rapporti di scalabilità possono aiutarti a rispondere. C'è il rapporto del database:
Non ci si può aspettare che il tuo database non subisca un carico maggiore, quindi quello che dovresti vedere qui è una linea che aumenta lentamente con l'aumentare della velocità della tua applicazione. Spetta a te quando il tempo di risposta del database è ritenuto inaccettabile (cioè influisce troppo sulla risposta dell'applicazione), ma quando decidi che le risposte del database sono troppo lente, sai che è ora di aggiungere capacità del database. L'altro report è la CPU:
Ancora una volta non puoi davvero aspettarti che un throughput più elevato non influenzi il carico della tua CPU, dovresti vedere una linea che aumenta lentamente con un throughput maggiore. Questo, insieme ai rapporti sulla capacità di cui abbiamo parlato in precedenza, può consentirti di decidere quando aggiungere più processi / server di Rails per garantire che le tue prestazioni rimangano decenti.
Se una o tutte queste caratteristiche hanno alzato un sopracciglio (o due) per te, la buona notizia è che abbiamo appena scalfito la superficie. Ognuna di queste caratteristiche merita un articolo approfondito a parte. Ma New Relic ha anche una serie di altre funzionalità che sono potenzialmente ancora più potenti, tra cui Real User Monitoring, The New Relic Platform, The Thread Profiler, Alert Thresholds e Notification e molti altri. Cercheremo di coprire alcuni o forse anche tutti questi in tutorial successivi.
Per ora, prova New Relic out, distribuisci un agente nella tua lingua preferita e vedi se riesci a scoprire un modo immediato di utilizzare alcune delle funzionalità offerte da New Relic. E se hai qualche modo innovativo per usare New Relic, assicurati di far sapere a tutti lasciando un commento.