Une fois que vous commencez à explorer New Relic, vous commencez à réaliser à quel point le service propose de nombreuses fonctionnalités intéressantes pour vous aider à surveiller les performances et la santé de votre application. Il était vraiment difficile de choisir seulement cinq sujets à aborder. Par conséquent, plutôt que de vous concentrer sur les fonctionnalités évidentes, examinons certaines des fonctionnalités les moins en vogue de New Relic et la manière dont nous pouvons les utiliser de manière intéressante et parfois peu orthodoxe..
Lorsque nous vous avons quitté la dernière fois, nous avions une application de base 'Hello World' Rails (appelée New Relic_rails1
, vivre dans ~ / project / tmp / New Relic
). Nous allons continuer à utiliser cette application, l'étendre et voir si nous pouvons l'utiliser pour démontrer les fonctionnalités de New Relic que nous allons examiner.
Ce contenu a été commandé par New Relic et a été écrit et / ou édité par l'équipe de Tuts +. Notre objectif avec le contenu sponsorisé est de publier des tutoriels pertinents et objectifs, des études de cas et des interviews inspirantes qui offrent une véritable valeur éducative à nos lecteurs et nous permettent de financer la création de contenu plus utile..
Il s’agit d’une fonctionnalité Nouvelle Relique qui ne fait généralement pas la une du matériel marketing. Il n'y a pas grand-chose à cela, mais si vous y réfléchissez, quoi de plus important que de vous assurer que votre application est réellement opérationnelle et accessible par vos utilisateurs?
Tout d'abord, lorsque vous configurez la surveillance de la disponibilité, votre application reçoit un astérisque sur le tableau de bord de vos applications principales:
C'est un rappel visuel intéressant qui vous permet de voir quelles applications nécessitent encore une surveillance de la disponibilité activée..
Voyons maintenant comment nous pouvons configurer la surveillance de la disponibilité et ce que nous pouvons en retirer. Tout d’abord, vous devez vous lancer dans votre application puis passer à Paramètres-> Surveillance de la disponibilité. Vous verrez quelque chose comme ça:
Vous devez fournir à l'URL que vous voulez que New Relic envoie, cochez la case, enregistrez vos modifications et vous êtes prêt à partir. New Relic commencera à frapper votre URL toutes les 30 secondes. Mais le plaisir ne s'arrête pas là. New Relic enverra une requête ping à votre URL via une requête HTTP HEAD (et jugera tout OK si elle reçoit un code de réponse de 200), mais vous pouvez fournir une chaîne de réponse que vous souhaitez que New Relic recherche, auquel cas une requête GET sera exécutée. examinez la réponse pour la chaîne que vous avez fournie. Cela peut être très pratique si vous souhaitez afficher une page personnalisée "Health Check"..
Vous pouvez également configurer une notification par courrier électronique en cas d’indisponibilité:
Maintenant que vous surveillez la disponibilité, vous aurez accès à un bon rapport qui vous indiquera visuellement toute interruption de service:
En fait, beaucoup de vos graphiques (par exemple, la vue d'ensemble de l'application) auront cette indication visuelle:
Vous devez admettre que c'est une fonctionnalité très agréable pour si peu d'effort.
Vous pouvez bien sûr désactiver et réactiver la surveillance (via l'API New Relic REST) lorsque vous effectuez des déploiements, pour vous assurer que vous ne recevez pas de faux événements indisponibles..
Un autre effet intéressant de ceci est que, si vous déployez votre projet animal sur Heroku sur un seul dyno, vous pouvez utiliser cette fonctionnalité de ping pour empêcher votre dyno de dormir, ce qui peut ralentir votre site si vous n'avez pas beaucoup de circulation.
Si des erreurs inattendues se produisent dans votre application, New Relic les enregistrera pour vous et vous donnera un beau graphique. Notre petite application 'Hello World' a fonctionné admirablement pour le moment, il n'y a donc rien à voir pour nous à cet égard. Mais nous pouvons délibérément casser notre application et voir ce que New Relic nous donne.
Modifions notre HelloController
pour générer une erreur au hasard environ 50% du temps:
classe HelloController < ApplicationController def index if rand(2) == 0 raise 'Random error' end end end
Nous allons maintenant passer quelques centaines d'appels à notre application et voir ce qui se passe:
ab -n 300 -c 10 http://127.0.0.1:3000/
Notre graphe d'erreur New Relic semble maintenant beaucoup plus intéressant:
Et nous pouvons approfondir pour obtenir quelques détails:
Comme vous pouvez le constater, nous pouvons trier nos erreurs, les filtrer et examiner séparément les erreurs issues des requêtes Web et des tâches en arrière-plan. Il s’agit là d’un outil extrêmement puissant pour vous aider à diagnostiquer et à résoudre les problèmes liés à votre application. Vous pouvez bien sûr aussi voir la trace de la pile pour chaque erreur:
Il existe des services spécifiquement dédiés à la capture des erreurs de votre application, parmi les plus connus, Airbrake et Bugsnag. Ce sont des services payants utilisés par de nombreuses applications, mais la fonctionnalité fournie par New Relic rend ces services redondants. En fait, si nous pouvions envoyer des erreurs personnalisées à New Relic (au lieu de les laisser capturer des erreurs que nous n’avions pas encore sauvées), nous pourrions plaider en notre faveur pour ne pas utiliser un service de collecte d’erreurs distinct gem dans le processus).
Bien que New Relic ne documente aucun moyen de le faire, nous pouvons toujours aller à la source pour voir si ce que nous voulons faire est difficile. Il me semble qu’il devrait être assez simple pour nous d’envoyer des erreurs personnalisées à New Relic, alors essayons. Nous modifierons à nouveau l'action de notre contrôleur pour récupérer toutes les erreurs et envoyer une erreur personnalisée à 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
Après avoir passé quelques appels supplémentaires et attendu que les données soient transmises, nous voyons ce qui suit:
Cela a fonctionné, notre erreur personnalisée arrive! New Relic peut certainement agir en tant que notre service de collecte des erreurs. Nous utilisons bien sûr ici une interface privée qui n’est pas très agréable, mais nous pouvons mettre le notice_error
appeler derrière une façade qui rendra les choses un peu plus faciles pour nous si l'interface change.
Une approche encore meilleure consiste peut-être à ne pas traiter les erreurs personnalisées comme des erreurs ordinaires, mais à créer une mesure personnalisée à suivre, puis à créer un tableau de bord personnalisé à visualiser. De cette façon, nous n’utilisons aucune fonctionnalité non documentée et obtiendrions tout de même tous les avantages - brillant!
New Relic suivra normalement vos transactions pour vous:
Vous pourrez voir où votre application passe le plus clair de son temps (par exemple, dans le contrôleur, le modèle, la base de données, etc.). Cependant, New Relic ne capturera pas de trace détaillée sauf si la transaction dure plus longtemps qu'Appdex * 4 secondes. Normalement, cela ne pose pas de problème, mais vous avez parfois des transactions beaucoup plus importantes pour votre application ou votre entreprise. Ces transactions représentent peut-être un volume extrêmement élevé ou concernent des événements importants tels que les paiements. Autant dire que vous devez vous assurer que ce type de transaction fonctionne toujours extrêmement bien.
Le problème, c’est que, quand une transaction est aussi importante, elle a probablement déjà reçu pas mal d’amour de votre part et peut-être se comporte assez bien. Supposons que vous ayez une transaction avec un débit extrêmement élevé (plusieurs fois par minute). Si cette transaction fonctionne de manière optimale, tout va bien, mais si les performances se dégradaient légèrement, en raison du volume du trafic, cela pourrait avoir un effet disproportionné sur votre application. Ce que vous voulez c'est quelque chose comme:
C’est exactement ce que vous apportent les transactions clés!
Avant de configurer une transaction clé pour notre application «Hello World», nous devons créer une transaction plus intéressante, qui fonctionnera généralement bien, mais qui fonctionnera parfois quelque peu mal. Nous développerons la capacité d'examiner les marques et les modèles de voitures et d'obtenir une marque particulière pour ralentir la transaction. Tout d'abord la route:
New RelicRails1 :: Application.routes.draw obtient 'random_car', vers: 'cars # show_random', 'root' hello # index 'end
Nous voulons pouvoir obtenir une voiture au hasard, cela va mapper à la CarsController
:
classe CarsController < ApplicationController def show_random @car = Car.offset(rand(Car.count)).first if @car.make == 'Ford' sleep(2) end end end
Nous obtenons une voiture au hasard dans la base de données et si la marque est "Ford", nous aurons une transaction lente sur nos mains. Bien sûr nous avons besoin d'un Voiture
modèle:
voiture de classe < ActiveRecord::Base end
Nous devrons configurer notre base de données pour utiliser MySql en développement (je l’ai fait, mais vous pouvez rester avec sqlite
):
base: & adaptateur de base: mysql2 encodage: utf8 hôte: "localhost" nom d'utilisateur: "root" max_connections: 10 timeout: 5000 development: & DEV <<: *BASE database: "New Relic_rails1_development" sql_log_level: debug
Nous avons besoin d’une migration pour créer un des voitures
table:
voitures de classe < ActiveRecord::Migration def change create_table :cars, force: true do |t| t.string :make t.string :model end end end
Et nous avons besoin de quelques données de base que nous allons mettre dans notre db / seeds.rb
fichier:
Car.create (marque: 'Ford', modèle: 'Mondeo') Car.create (marque: 'Honda', modèle: 'Accord') Car.create (marque: 'Audi', modèle: 'A4') Voiture. créer (marque: 'Lamborghini', modèle: 'Murcielago') voiture. créer (marque: 'Toyota', modèle: 'Prius')
Enfin, nous devrions probablement avoir une vue cars / show_random.html.erb
:
Faire: <%= @car.make %>
Modèle: <%= @car.model %>
Vous devrez également ajouter le mysql2
joyau au Gemfile
si vous êtes allé avec MySql. Après cela, nous avons juste besoin de créer et d’alimenter la base de données, de redémarrer notre serveur et nous sommes prêts à partir:
bundle rake db: créer && rake db: migrer && rake db: seed rails s
Vous devez cliquer sur l'URL pour vous assurer que New Relic reconnaît que cette transaction existe:
curl localhost: 3000 / random_car
Nous sommes maintenant prêts à surveiller cette transaction en tant que transaction clé. Tout d'abord, sautez dans l'onglet de transaction:
Cliquez sur le bouton "Suivre une transaction clé" et sélectionnez notre transaction nouvellement créée:
Nous pouvons donner un nom à notre nouvelle transaction de clé, choisir l'Apdex T qui nous convient et configurer des alertes. Lorsque notre transaction prend plus de temps que Apdex que nous avons choisi, New Relic capturera une trace détaillée que nous pourrons utiliser pour déterminer l'origine du problème de performance. Faisons quelques appels avec notre nouvelle URL et voyons quelles données nous avons:
ab -n 300 -c 20 http://127.0.0.1:3000/random_car
Hmm, il semble que certaines de nos transactions frustrent nos utilisateurs:
Voyons si New Relic a capturé des traces de transaction pour nous:
Regardons l'une de ces traces. Il a fallu environ 2 secondes pour répondre, mais seulement 10 millisecondes utilisaient le processeur:
Toutes nos instructions SQL étaient rapides, donc la base de données n'est pas le problème:
Il semble que la plupart du temps soit passé dans l'action du contrôleur:
Fouillons un peu dans la trace. Il semble que le SQL SELECT était rapide, un Car.find
était aussi rapide. Ensuite, nous perdons environ 2 secondes, suivies d’un rendu très rapide des modèles:
New Relic a gentiment souligné pour nous où nous avons perdu ces deux secondes. Nous devons regarder notre code de contrôleur après un Car.find
appel:
classe CarsController < ApplicationController def show_random @car = Car.offset(rand(Car.count)).first if @car.make == 'Ford' sleep(2) end end end
Hmm, le SELECT initial doit être le Nombre de voitures
appeler, et le Car.find
, doit être dû à la Car.offset
appel. Notre grand retard est juste après cela cependant. Ahh regarde ça, une personne idiote a mis un délai de 2 secondes dans notre code quand la marque de la voiture est "Ford". Cela expliquerait pourquoi notre délai de 2 secondes ne se produit que de temps en temps. Je ferais mieux de faire un blâmer
sur notre référentiel pour savoir qui a mis cet horrible code là! À bien y penser, je ferais mieux de ne pas le faire car on pourrait dire que c'était moi.
Chaque fois que vous appelez d'autres services depuis votre application (par exemple, une requête HTTP vers une API telle que Twitter), New Relic les surveillera en tant qu'appels externes. De nos jours, une application sérieuse peut s’intégrer à un certain nombre d’API externes. Ces services externes peuvent souvent dégrader de manière significative les performances de votre application, notamment si vous passez ces appels en cours de traitement. New Relic peut indiquer quels appels externes sont les plus lents, ceux que vous appelez le plus et ceux qui répondent le plus lentement en moyenne. Vous pouvez également examiner les performances de chacun des services externes que vous utilisez individuellement. Essayons.
Nous allons créer notre propre service externe en construisant une petite application Sinatra. Tout d'abord, nous installons la gemme:
bijou installer sinatra
Créez un nouveau fichier pour notre service:
touchez external_service.rb
Et mettez le code suivant ici:
Requiert 'sinatra' get '/ hello' do sleep_time = rand (2000) /1000.0 sleep (sleep_time) "Bonjour le monde externe # sleep_time!" fin
Ce service dormira pendant un temps aléatoire (entre 0 et 2 000 millisecondes), puis renverra une réponse "Bonjour" avec l'heure de veille. Il ne nous reste plus qu'à le démarrer:
ruby external_service.rb
De retour dans notre application Rails, nous construisons un nouveau contrôleur pour appeler notre service externe. Nous allons utiliser cette route:
Les nouveaux RelicRails1 :: Application.routes.draw font… obtiennent 'external_call', vers: 'external_calls # external_call'… fin
Notre contrôleur appellera notre service Sinatra via HTTP:
nécessite 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
Et nous avons besoin d'une vue pour afficher les résultats:
<%= @result %>
Il ne nous reste plus qu'à passer quelques appels à notre nouveau terminal:
ab -n 100 -c 10 http://127.0.0.1:3000/external_call
Voyons ce que New Relic a produit pour nous.
New Relic a effectivement pris notre nouvel appel externe. Nous avons le nombre total d'appels par minute vers le point d'extrémité externe. Et le total qui a été dépensé pour répondre par le service externe. Bien entendu, notre tableau semble un peu clair, car nous n’avons qu’un seul service externe, ce qui signifie que nous n’avons rien à comparer..
Nous pouvons également obtenir des données plus détaillées sur l'appel externe spécifique, ainsi que sur l'emplacement de l'appel dans notre application:
Nous pouvons voir quand les appels ont été passés, le débit et le temps de réponse moyen. Cela peut sembler simple, mais lorsque vous avez une application avec de nombreux services externes, cette fonctionnalité peut vous donner un très bon aperçu de la performance de ces services externes, ainsi que du moment et du lieu d'utilisation. Cela peut vous permettre de prendre des décisions en ce qui concerne la mise en cache de certaines réponses de services externes, voire de supprimer certains services externes si leurs performances ne sont pas à la hauteur. Et vous n'avez plus besoin d'argumenter ces choses en vous basant sur des mesures méticuleuses et gustatives, vous aurez des données fiables pour prouver votre argument..
Il n’ya rien de plus frustrant pour un développeur que de voir votre application basculer à cause d’un pic de trafic. Tout fonctionnait sans heurts jusqu'à l'arrivée de ces quelques centaines d'utilisateurs supplémentaires et l'explosion de votre application. Vous avez eu le sentiment que cela pourrait arriver, mais vous ne pouvez pas en être sûr - l'attente d'attendre semblait être l'approche la plus pragmatique. Avec les rapports de capacité et d’évolutivité de New Relic, vous n’avez plus à attendre et à voir. Vous pouvez dire immédiatement à quel point votre application évolue, vous pouvez effectuer des tests de charge et voir instantanément si votre application peut gérer la charge. Vous pouvez observer les tendances des temps de réponse de vos applications à mesure que votre base d'utilisateurs s'agrandit et prévoir à quel moment vous devrez ajouter de la capacité. Toutes ces choses sont vraiment merveilleuses.
Premièrement, regardons les rapports de capacité:
Hmm, celui-ci montre une grande pointe, mais sinon rien. Nous fonctionnons en mode développement, c'est donc compréhensible. Ce pic est pour quand nous avons fait un tas de demandes simultanément il y a un peu de temps. Comme vous pouvez le constater lorsque nous avons effectué ces demandes simultanées, nous avons limité au maximum notre mauvaise instance isolée Webrick. S'il s'agissait d'une production et que la charge était constante, notre instance serait toujours occupée à 100%, ce qui indiquerait probablement que nous avons besoin d'une autre instance..
Le rapport d'analyse d'instance est légèrement différent:
Dans notre cas, nous n'en tirons pas grand-chose, mais cela nous indique normalement le nombre d'instances en cours d'exécution et le nombre d'instances dont nous avons réellement besoin pour gérer la charge si toutes les instances étaient occupées à 100%. Ainsi, si nous exécutions 10 instances et que la charge d'instance simultanée était de 2, nous pourrions facilement diviser par deux (voire plus que par deux) le nombre d'instances en cours d'exécution et ne pas dégrader la performance du tout. Pour une petite application qui ne tourne que quelques instances, ce n'est pas grave, mais pour une grande application comptant des dizaines et des centaines d'instances, cela peut se traduire par des économies de coûts considérables..
Et puis il y a les rapports d'évolutivité. Le rapport de temps de réponse est probablement le plus intéressant / important:
Encore une fois, notre graphique est très déformé, car il s’agit d’une application de développement avec laquelle nous avons joué de manière aléatoire. L’idée de ce rapport est que, à mesure que le débit de votre application augmente (plus de demandes par minute), le temps de réponse doit rester presque constant (c’est-à-dire que les performances ne se dégradent pas lorsqu'il y a plus de trafic). Cela signifie que vous devriez toujours voir quelque chose qui ressemble à une ligne plate ici. Si votre ligne est fortement inclinée vers le haut, votre application a probablement du mal à gérer le trafic et vous devrez peut-être augmenter la capacité. La question de savoir où ajouter de la capacité est une autre question (capacité de la base de données, plus de serveurs, etc.). Les deux autres rapports d’évolutivité peuvent vous aider à y répondre. Il y a le rapport de base de données:
Vous ne pouvez pas vous attendre à ce que votre base de données ne soit pas affectée par une charge plus importante. Vous devez donc voir ici une ligne qui monte lentement à mesure que le débit de votre application augmente. C’est à vous de décider si le temps de réponse de la base de données est jugé inacceptable (c’est-à-dire que cela affecte trop la réponse de l’application), mais lorsque vous décidez que les réponses de la base de données sont trop lentes, vous savez qu’il est temps d’ajouter de la capacité. L'autre rapport est le CPU:
Une fois encore, vous ne pouvez pas vraiment vous attendre à ce que le débit plus élevé n'affecte pas la charge de votre processeur, vous devriez voir une ligne augmenter lentement avec le débit. Ceci, combiné aux rapports de capacité dont nous avons parlé précédemment, peut vous permettre de décider quand ajouter plus de processus / serveurs Rails pour vous assurer que vos performances restent correctes..
Si une ou plusieurs de ces fonctionnalités ont soulevé un sourcil (ou deux) pour vous, la bonne nouvelle est que nous n'avons fait qu'effleurer la surface. Chacune de ces caractéristiques mérite amplement un article en profondeur. Mais New Relic possède également un certain nombre d’autres fonctionnalités potentiellement encore plus puissantes, telles que la surveillance des utilisateurs réels, la nouvelle plate-forme Relic, le profileur de threads, les seuils d’alerte et les notifications, etc. Nous allons essayer de couvrir certains ou peut-être même tous ces éléments dans des tutoriels ultérieurs..
Pour le moment, essayez New Relic out, déployez un agent dans votre langue préférée et voyez si vous pouvez découvrir un moyen immédiat d’utiliser certaines des fonctionnalités fournies par New Relic. Et si vous avez des façons novatrices d'utiliser New Relic, assurez-vous de le faire savoir à tout le monde en laissant un commentaire..