diff --git a/sections/errorhandling/apmproducts.spanish.md b/sections/errorhandling/apmproducts.spanish.md index ffb1fd7c1..e85f7d9f9 100644 --- a/sections/errorhandling/apmproducts.spanish.md +++ b/sections/errorhandling/apmproducts.spanish.md @@ -1,9 +1,8 @@ -# Discover errors and downtime using APM products +# Detectar errores y tiempos de inactividad a través de productos APM +### Párrafo de explicación -### One Paragraph Explainer - -Exception != Error. Traditional error handling assumes the existence of Exception but application errors might come in the form of slow code paths, API downtime, lack of computational resources and more. This is where APM products come in handy as they allow to detect a wide variety of ‘burried’ issues proactively with a minimal setup. Among the common features of APM products are for example alerting when the HTTP API returns errors, detect when the API response time drops below some threshold, detection of ‘code smells’, features to monitor server resources, operational intelligence dashboard with IT metrics and many other useful features. Most vendors offer a free plan. +Exception != Error. La gestión tradicional de errores asume la existencia de Exception, pero los errores de la aplicación pueden manifestarse en forma de rutas de ejecución lentas, tiempos de inactividad de la API, falta de recursos computacionales y más. Es ahí donde los productos APM se tornan realmente útiles ya que permiten detectar una amplia variedad de problemas "enterrados", proactivamente y con una configuración mínima. Entre las características más comunes de productos APM están, por ejemplo, el alertar cuando se presentan errores HTTP API, detectar cuando el tiempo de respuesta de la API cae por debajo del umbral establecido, localizar ["code smells"](https://es.wikipedia.org/wiki/Hediondez_del_c%C3%B3digo), monitorizar recursos del servidor, proporcionar inteligencia operacional mediante paneles con métricas de IT y muchas otras funciones útiles. La mayoría de proveedores de este tipo de productos ofrecen algún plan gratuito. ### Wikipedia about APM diff --git a/sections/errorhandling/asyncerrorhandling.spanish.md b/sections/errorhandling/asyncerrorhandling.spanish.md index 06ca39532..eba481190 100644 --- a/sections/errorhandling/asyncerrorhandling.spanish.md +++ b/sections/errorhandling/asyncerrorhandling.spanish.md @@ -1,8 +1,8 @@ -# Use Async-Await or promises for async error handling +# Usar Async-Await o promises para capturar errores asíncronos -### One Paragraph Explainer +### Párrafo de explicación -Callbacks don’t scale well since most programmers are not familiar with them. They force to check errors all over, deal with nasty code nesting and make it difficult to reason about the code flow. Promise libraries like BlueBird, async, and Q pack a standard code style using RETURN and THROW to control the program flow. Specifically, they support the favorite try-catch error handling style which allows freeing the main code path from dealing with errors in every function +Los callbacks no escalan bien ya que muchos programadores no están familiarizados con ellos. Te obligan a estar pendiente de errores por todos lados y a lidiar con un anidamiento de código excesivo, lo cual dificulta la comprensión del flujo de código. Librerías prometedoras como BlueBird, async y Q empaquetan un estilo de código estándar utilizando RETURN y THROW para controlar el flujo del programa. Específicamente, soportan el estilo favorito de gestión de errores try-catch, liberando a la ruta principal de código de tratar con errores en cada función. ### Code Example – using promises to catch errors diff --git a/sections/errorhandling/catchunhandledpromiserejection.spanish.md b/sections/errorhandling/catchunhandledpromiserejection.spanish.md index e71f79cc3..b7461d57a 100644 --- a/sections/errorhandling/catchunhandledpromiserejection.spanish.md +++ b/sections/errorhandling/catchunhandledpromiserejection.spanish.md @@ -1,10 +1,10 @@ -# Catch unhandled promise rejections +# Capturar promises denegadas sin controlar

-### One Paragraph Explainer +### Párrafo de explicación -Typically, most of modern Node.js/Express application code runs within promises – whether within the .then handler, a function callback or in a catch block. Surprisingly, unless a developer remembered to add a .catch clause, errors thrown at these places are not handled by the uncaughtException event-handler and disappear. Recent versions of Node added a warning message when an unhandled rejection pops, though this might help to notice when things go wrong but it's obviously not a proper error handling method. The straightforward solution is to never forget adding .catch clauses within each promise chain call and redirect to a centralized error handler. However, building your error handling strategy only on developer’s discipline is somewhat fragile. Consequently, it’s highly recommended using a graceful fallback and subscribe to `process.on(‘unhandledRejection’, callback)` – this will ensure that any promise error, if not handled locally, will get its treatment. +Normalmente, la mayor parte de código en aplicaciones Node.js/Express modernas funciona encerrado en "promises", ya sea en el interior de un .then, como en una función callback o en un bloque catch. Sorprendentemente, a menos que el desarrollador no olvide añadir una cláusula .catch, los errores que lanzados en estos sitios no son controlados por uncaughtException y desaparecen. Las últimas versiones de Node incorporan un mensaje de warning ante estas situaciones y, a pesar de la ayuda que esto supone cuando las cosas van mal, resulta evidente que no es el método adecuado para dar por resuelto el tema. La solución más sencilla es nunca olvidar cláusulas .catch en cada cadena de promises y redirigir el error al gestor de errores centralizado. Sin embargo, centrar tu estrategia de gestión de errores puramente en la disciplina del desarrollador es ciertamente frágil. Por lo tanto, se recomienda muchísimo utilizar una alternativa elegante: suscribirse a `process.on('unhandledRejection', callback)` – esto asegurará que cualquier error provinente de una promise, de no gestionarse localmente, siempre reciba su correcta gestión.

diff --git a/sections/errorhandling/centralizedhandling.spanish.md b/sections/errorhandling/centralizedhandling.spanish.md index d153259d4..920970573 100644 --- a/sections/errorhandling/centralizedhandling.spanish.md +++ b/sections/errorhandling/centralizedhandling.spanish.md @@ -1,8 +1,8 @@ -# Handle errors centrally, through but not within a middleware +# Gestiona los errores de manera central, "a través de" pero no "en" un middleware -### One Paragraph Explainer +### Párrafo de explicación -Without one dedicated object for error handling, greater are the chances of important errors hiding under the radar due to improper handling. The error handler object is responsible for making the error visible, for example by writing to a well-formatted logger, sending events to some monitoring product or to an admin directly via email. A typical error handling flow might be: Some module throws an error -> API router catches the error -> it propagates the error to the middleware (e.g. Express, KOA) who is responsible for catching errors -> a centralized error handler is called -> the middleware is being told whether this error is an untrusted error (not operational) so it can restart the app gracefully. Note that it’s a common, yet wrong, practice to handle errors within Express middleware – doing so will not cover errors that are thrown in non-web interfaces +Sin un objeto dedicado a la gestión de errores, son más las posibilidades de que errores importantes se oculten bajo el radar debido a una gestión inapropiada de los mismos. El objeto que gestiona el error es responsable de hacerlo visible, por ejemplo, mediante un logger bien formateado, enviando eventos hacia algún producto de monitorización o directamente a un administrador vía email. Un flujo típico de gestión de errores puede ser: Algún módulo tira un error –> el router de la API captura el error -> se propaga al middleware (ej. Express, KOA) responsable de atrapar errores -> se llama al objeto gestor de errores central -> se le indica al middleware si el error no es de fiar (no operacional) para que pueda reiniciar la aplicación de forma controlada. Nota que es una práctica común y, aun así mala práctica, el gestionar los errores directamente en el middleware de Express, pues de esa manera los errores lanzados en interfaces "no web" no quedan cubiertos. ### Code Example – a typical error flow diff --git a/sections/errorhandling/documentingusingswagger.spanish.md b/sections/errorhandling/documentingusingswagger.spanish.md index e2f7a496c..f357dd780 100644 --- a/sections/errorhandling/documentingusingswagger.spanish.md +++ b/sections/errorhandling/documentingusingswagger.spanish.md @@ -1,8 +1,8 @@ -# Document API errors using Swagger +# Documentar errores API mediante Swagger -### One Paragraph Explainer +### Párrafo de explicación -REST APIs return results using HTTP status codes, it’s absolutely required for the API user to be aware not only about the API schema but also about potential errors – the caller may then catch an error and tactfully handle it. For example, your API documentation might state in advance that HTTP status 409 is returned when the customer name already exists (assuming the API register new users) so the caller can correspondingly render the best UX for the given situation. Swagger is a standard that defines the schema of API documentation offering an eco-system of tools that allow creating documentation easily online, see print screens below +Las APIs basadas en REST devuelven resultados utilizando códigos de estado HTTP. Es absolutamente necesario para el usuario de la API el ser consciente, no solo del esquema API, sino también de los errores potenciales. De ese modo puede atrapar el error y actuar en consecuencia. Por ejemplo, la documentación de tu API puede aclarar por adelantado que se devuelve el código HTTP 409 cuando el nombre del cliente ya existe (asumiendo que la API registre nuevos usuarios), por tanto la aplicación que consume la API puede proporcionar la mejor UX para la situación dada. Swagger es un estándar que define un esquema para generar documentación API, ofreciendo un ecosistema de herramientas que permiten crear fácilmente documentación online. Observa las siguientes capturas de pantalla. ### Blog Quote: "You have to tell your callers what errors can happen" diff --git a/sections/errorhandling/failfast.spanish.md b/sections/errorhandling/failfast.spanish.md index 8d56ebe76..d9d6f7813 100644 --- a/sections/errorhandling/failfast.spanish.md +++ b/sections/errorhandling/failfast.spanish.md @@ -1,8 +1,8 @@ -# Fail fast, validate arguments using a dedicated library +# Falla rápido, valida los argumentos mediante una librería dedicada -### One Paragraph Explainer +### Párrafo de explicación -We all know how checking arguments and failing fast is important to avoid hidden bugs (see anti-pattern code example below). If not, read about explicit programming and defensive programming. In reality, we tend to avoid it due to the annoyance of coding it (e.g. think of validating hierarchical JSON object with fields like email and dates) – libraries like Joi and Validator turn this tedious task into a breeze. +Todos sabemos que revisar argumentos y fallar cuanto antes es importante para evitar bugs ocultos (ver el código antipatrón de ejemplo a continuación). Si no, lee sobre programación explícita y defensiva. En realidad, tendemos a evitarlo por el fastidio que supone programarlo (por ej. piensa en validar un objeto JSON jerárquico con campos como email y fechas). Bibliotecas como Joi y Validator convierten esta tediosa tarea en calderilla. ### Wikipedia: Defensive Programming diff --git a/sections/errorhandling/operationalvsprogrammererror.spanish.md b/sections/errorhandling/operationalvsprogrammererror.spanish.md index d0750e7e9..9e501b4b4 100644 --- a/sections/errorhandling/operationalvsprogrammererror.spanish.md +++ b/sections/errorhandling/operationalvsprogrammererror.spanish.md @@ -1,8 +1,8 @@ -# Distinguish operational vs programmer errors +# Distinguir errores operacionales vs errores del programador -### One Paragraph Explainer +### Párrafo de explicación -Distinguishing the following two error types will minimize your app downtime and helps avoid crazy bugs: Operational errors refer to situations where you understand what happened and the impact of it – for example, a query to some HTTP service failed due to connection problem. On the other hand, programmer errors refer to cases where you have no idea why and sometimes where an error came from – it might be some code that tried to read an undefined value or DB connection pool that leaks memory. Operational errors are relatively easy to handle – usually logging the error is enough. Things become hairy when a programmer error pops up, the application might be in an inconsistent state and there’s nothing better you can do than to restart gracefully +Distinguir entre los siguientes dos tipos de error minimizará el downtime de la aplicación y ayudará a evitar comportamientos extraños: Los errores operacionales se refieren a situaciones en las que entendemos lo que ha pasado y su impacto, por ejemplo, una petición HTTP fallida por un problema de conexión. Por otro lado, los errores del programador se refieren a casos en los que no tienes ni idea de por qué ocurren (a veces ni de dónde vienen), puede tratarse de algún código que intenta leer un valor no definido o de una pool de conexión a base de datos que pierde memoria. Los errores operacionales son relativamente fáciles de gestionar –generalmente, con registrar el error es suficiente– pero las cosas se complican cuando salta un error del programador, ya que la aplicación puede quedar en un estado inconsistente y no hay nada mejor que puedas hacer que reiniciarla de forma controlada. ### Code Example – marking an error as operational (trusted) diff --git a/sections/errorhandling/shuttingtheprocess.spanish.md b/sections/errorhandling/shuttingtheprocess.spanish.md index 1065d3cf3..5b4c4f33f 100644 --- a/sections/errorhandling/shuttingtheprocess.spanish.md +++ b/sections/errorhandling/shuttingtheprocess.spanish.md @@ -1,8 +1,8 @@ -# Exit the process gracefully when a stranger comes to town +# Termina el proceso si llega un desconocido al pueblo -### One Paragraph Explainer +### Párrafo de explicación -Somewhere within your code, an error handler object is responsible for deciding how to proceed when an error is thrown – if the error is trusted (i.e. operational error, see further explanation within best practice #3) then writing to log file might be enough. Things get hairy if the error is not familiar – this means that some component might be in a faulty state and all future requests are subject to failure. For example, assuming a singleton, stateful token issuer service that threw an exception and lost its state – from now it might behave unexpectedly and cause all requests to fail. Under this scenario, kill the process and use a ‘Restarter tool’ (like Forever, PM2, etc) to start over with a clean slate. +En algún lugar del código, un objeto gestor de errores es responsable de decidir cómo se procede ante un error. Si ese error es confiable (ej. un error operacional, ver más información en mejores prácticas #3) con registrarlo en un log puede ser suficiente. Lo complicado viene cuando el error no es conocido, lo que implica que algún componente puede estar fallando y toda petición subsiguiente quedaría expuesta a fallar también. Por ejemplo, asumiendo una arquitectura singleton, un servicio proveedor de token con estado propio que lanza una excepción y pierde su estado podría, a partir de ese momento, comportarse de manera inesperada y provocar que todas las peticiones empiecen a fallar. Ante este escenario, termina el proceso y utiliza una "herramienta de reinicio" (como Forever, PM2, etc.) para empezar de cero limpiamente. ### Code example: deciding whether to crash diff --git a/sections/errorhandling/testingerrorflows.spanish.md b/sections/errorhandling/testingerrorflows.spanish.md index 3e2d3f887..bbab356ae 100644 --- a/sections/errorhandling/testingerrorflows.spanish.md +++ b/sections/errorhandling/testingerrorflows.spanish.md @@ -1,8 +1,8 @@ -# Test error flows using your favorite test framework +# Testear flujos de error mediante tu framework favorito de testing -### One Paragraph Explainer +### Párrafo de explicación -Testing ‘happy’ paths is no better than testing failures. Good testing code coverage demands to test exceptional paths. Otherwise, there is no trust that exceptions are indeed handled correctly. Every unit testing framework, like [Mocha](https://mochajs.org/) & [Chai](http://chaijs.com/), supports exception testing (code examples below). If you find it tedious to test every inner function and exception you may settle with testing only REST API HTTP errors. +Testear rutas de ejecución "felices" no es mejor que testear errores. Un buen coverage de código exige testear rutas de ejecución adversas. De lo contrario, no existe ninguna seguridad de que las excepciones se capturen y gestionen correctamente. Cada framework de testing unitario, como Mocha y Chai, admite testing de excepciones (códigos de ejemplo a continuación). Si te parece tedioso ir probando cada función y excepción internas, podrías quedarte solo con el testing de errores REST API HTTP. ### Code example: ensuring the right exception is thrown using Mocha & Chai diff --git a/sections/errorhandling/usematurelogger.spanish.md b/sections/errorhandling/usematurelogger.spanish.md index d735bda93..2f8b21600 100644 --- a/sections/errorhandling/usematurelogger.spanish.md +++ b/sections/errorhandling/usematurelogger.spanish.md @@ -1,9 +1,8 @@ -# Use a mature logger to increase errors visibility +# Utilizar un logger maduro para incrementar la visibilidad de errores -### One Paragraph Explainer +### Párrafo de explicación -We all love console.log but obviously, a reputable and persistent logger like [Winston][winston], [Bunyan][bunyan] (highly popular) or [Pino][pino] (the new kid in town which is focused on performance) is mandatory for serious projects. A set of practices and tools will help to reason about errors much quicker – (1) log frequently using different levels (debug, info, error), (2) when logging, provide contextual information as JSON objects, see example below. (3) watch and filter logs using a log querying API (built-in in most loggers) or a log viewer software -(4) Expose and curate log statement for the operation team using operational intelligence tools like Splunk +A todos nos encanta console.log, pero evidentemente un logger persistente y con buena reputación como [Winston][winston], [Bunyan][bunyan] (tremendamente popular) o [Pino][pino] (la última novedad, centrado en el performance) es algo obligatorio para proyectos serios. Un conjunto de prácticas y herramientas nos ayudarán a tratar con errores mucho más rápido: (1) Utilizar diferentes niveles de log (debug, info, error). (2) Cuando creamos logs, proporcionar información contextual mediante objetos JSON, ver el ejemplo de abajo. (3) Mirar y filtrar logs a través de una API de consulta de logs (incorporado en la mayoría de loggers) o de un software visor de logs. (4) Exponer y curar las entradas de log para el equipo de operaciones utilizando herramientas de inteligencia operacional como Splunk. [winston]: https://www.npmjs.com/package/winston [bunyan]: https://www.npmjs.com/package/bunyan diff --git a/sections/errorhandling/useonlythebuiltinerror.spanish.md b/sections/errorhandling/useonlythebuiltinerror.spanish.md index 7898f3318..f5206e25f 100644 --- a/sections/errorhandling/useonlythebuiltinerror.spanish.md +++ b/sections/errorhandling/useonlythebuiltinerror.spanish.md @@ -1,8 +1,8 @@ -# Use only the built-in Error object +# Utiliza solo el objeto nativo de Error -### One Paragraph Explainer +### Párrafo de explicación -The permissive nature of JS along with its variety code-flow options (e.g. EventEmitter, Callbacks, Promises, etc) pushes to great variance in how developers raise errors – some use strings, other define their own custom types. Using Node.js built-in Error object helps to keep uniformity within your code and with 3rd party libraries, it also preserves significant information like the StackTrace. When raising the exception, it’s usually a good practice to fill it with additional contextual properties like the error name and the associated HTTP error code. To achieve this uniformity and practices, consider extending the Error object with additional properties, see code example below +La naturaleza permisiva de JS junto con sus variadas opciones de flujo de código (ej. EventEmitter, Callbacks, Promises, etc) provocan la existencia de una gran variedad de maneras de lanzar errores. Algunos utilizan strings, otros definen sus propios tipos personalizados. Utilizar el objeto nativo de Error presente en Node.js ayuda a mantener la uniformidad dentro de tu código y de librerías de terceros, así como a mantener información significativa como el StackTrace. Al lanzar la excepción, normalmente es buena práctica el agregar propiedades adicionales que aporten contexto, como el nombre del error y el código de error HTTP asociado. Para lograr esta uniformidad y estas prácticas, considera extender el objeto Error con propiedades adicionales, observa el ejemplo a continuación. ### Code Example – doing it right diff --git a/sections/production/LTSrelease.spanish.md b/sections/production/LTSrelease.spanish.md index 1a3e0808a..fbedac0d6 100644 --- a/sections/production/LTSrelease.spanish.md +++ b/sections/production/LTSrelease.spanish.md @@ -1,10 +1,12 @@ -# Use an LTS release of Node.js in production +# Usa una versión LTS de Node.js en producción -### One Paragraph Explainer +

+ +### Párrafo de explicación -Ensure you are using an LTS(Long Term Support) version of Node.js in production to receive critical bug fixes, security updates and performance improvements. +Asegúrate de usar una versión LTS —soporte a largo plazo, del inglés "Long Term Support"— de Node.js en producción para recibir correcciones críticas, actualizaciones de seguridad y mejoras de rendimiento. -LTS versions of Node.js are supported for at least 18 months and are indicated by even version numbers (e.g. 4, 6, 8). They're best for production since the LTS release line is focussed on stability and security, whereas the 'Current' release line has a shorter lifespan and more frequent updates to the code. Changes to LTS versions are limited to bug fixes for stability, security updates, possible npm updates, documentation updates and certain performance improvements that can be demonstrated to not break existing applications. +Las versiones LTS de Node.js reciben soporte durante al menos 18 meses y vienen indicadas por números pares de versión (por ejemplo, 4, 6, 8). Son las mejores para su uso en producción ya que sus actualizaciones se centran en la estabilidad y seguridad, mientras que las actualizaciones de 'Current' (la versión más reciente de Node) tienen una vida útil más corta y se lanzan con mucha frecuencia. Los cambios en las versiones de LTS están limitados a la corrección de errores de estabilidad, actualizaciones de seguridad, posibles actualizaciones de npm, actualizaciones de documentación y ciertas mejoras de rendimiento con prueba demostrable de que no rompen aplicaciones existentes.

diff --git a/sections/production/apmproducts.spanish.md b/sections/production/apmproducts.spanish.md index 71c51794c..a10ff30a6 100644 --- a/sections/production/apmproducts.spanish.md +++ b/sections/production/apmproducts.spanish.md @@ -1,10 +1,10 @@ -# Sure user experience with APM products +# Asegura la experiencia de usuario con productos APM

-### One Paragraph Explainer +### Párrafo de explicación -APM (application performance monitoring) refers to a family of products that aims to monitor application performance from end to end, also from the customer perspective. While traditional monitoring solutions focus on Exceptions and standalone technical metrics (e.g. error tracking, slow server endpoints, etc), in the real world our app might create disappointed users without any code exceptions, for example, if some middleware service performed real slow. APM products measure the user experience from end to end, for example, given a system that encompasses frontend UI and multiple distributed services – some APM products can tell how fast a transaction that spans multiple tiers last. It can tell whether the user experience is solid and point to the problem. This attractive offering comes with a relatively high price tag hence it’s recommended for large-scale and complex products that require going beyond straightforward monitoring. +APM (application performance monitoring) se refiere a una familia de productos que tiene como objetivo monitorizar el rendimiento de la aplicación de principio a fin, también desde la perspectiva del cliente. Mientras las soluciones de monitorización tradicionales se centran en Excepciones y métricas técnicas independientes (por ejemplo, seguimiento de errores, endpoints lentos de servidor, etc.), en el mundo real nuestra app podría tener a usuarios descontentos sin excepciones de código, por ejemplo, si algún servicio middleware funcionase muy lento. Los productos APM miden la experiencia de usuario de punto a punto, por ejemplo, dado un sistema que abarca la interfaz de usuario frontend y múltiples servicios distribuidos: algunos productos APM pueden indicar lo rápido que dura una transacción que abarca varios niveles. Puede revelar, de hecho, si la experiencia de usuario es sólida y señalar el problema. Esta atractiva solución viene con un precio relativamente alto y se recomienda para productos complejos a gran escala que requieren ir más allá de la monitorización básica.

diff --git a/sections/production/assigntransactionid.spanish.md b/sections/production/assigntransactionid.spanish.md index d8de3580a..d6418fd69 100644 --- a/sections/production/assigntransactionid.spanish.md +++ b/sections/production/assigntransactionid.spanish.md @@ -1,10 +1,10 @@ -# Assign ‘TransactionId’ to each log statement +# Asigna "TransactionId" a cada entrada de log

-### One Paragraph Explainer +### Párrafo de explicación -A typical log is a warehouse of entries from all components and requests. Upon detection of some suspicious line or error, it becomes hairy to match other lines that belong to the same specific flow (e.g. the user “John” tried to buy something). This becomes even more critical and challenging in a microservice environment when a request/transaction might span across multiple computers. Address this by assigning a unique transaction identifier value to all the entries from the same request so when detecting one line one can copy the id and search for every line that has similar transaction Id. However, achieving this In Node is not straightforward as a single thread is used to serve all requests –consider using a library that that can group data on the request level – see code example on the next slide. When calling other microservice, pass the transaction Id using an HTTP header like “x-transaction-id” to keep the same context. +El típico log es un almacén de entradas de todos los componentes y peticiones. Ante la detección de una línea sospechosa o error, se vuelve un lío cruzar dicha línea con otras líneas que pertenezcan a la misma cadena de sucesos (por ejemplo, el usuario "John" intentó comprar algo). Esto se vuelve aún más crítico y desafiante en un entorno de microservicios en el que para una petición/transacción pueden intervenir múltiples máquinas. Esto se soluciona asignando un valor único a modo de identificador de "la transacción" a todas las entradas de la misma petición, así cuando se detecta una línea de log puedes copiar dicho ID y buscar todas las líneas con la misma ID de transacción. Sin embargo, lograr esto en Node no es sencillo ya que se usa un solo thread para atender a todas las peticiones —considera el uso de una librería que agrupe datos a nivel de petición—. Observa el ejemplo de código en siguiente la imagen. Cuando llames a otro microservicio, pasa el ID de transacción en una cabecera HTTP como "x-transaction-id" para mantener el mismo contexto.

diff --git a/sections/production/bestateless.spanish.md b/sections/production/bestateless.spanish.md index cea84dec9..5e1e6465f 100644 --- a/sections/production/bestateless.spanish.md +++ b/sections/production/bestateless.spanish.md @@ -1,14 +1,13 @@ -# Be stateless, kill your Servers almost every day +# Sin estado: reinicia tus servidores casi cada día

-### One Paragraph Explainer +### Párrafo de explicación -Have you ever encountered a severe production issue where one server was missing some piece of configuration or data? That is probably due to some unnecessary dependency on some local asset that is not part of the deployment. Many successful products treat servers like a phoenix bird – it dies and is reborn periodically without any damage. In other words, a server is just a piece of hardware that executes your code for some time and is replaced after that. -This approach +¿Te has encontrado alguna vez un grave problema en producción en el que a un servidor le faltaba algo de configuración o información? Probablemente se deba a alguna dependencia innecesaria en algún recurso local que no es parte del deploy. Muchos productos de éxito tratan a los servidores como a un pájaro fénix: muere y renace periódicamente sin sufrir daños. En otras palabras, un servidor es solo una pieza de hardware que ejecuta tu código durante un tiempo y que después se reemplaza. De esta manera: -- allows scaling by adding and removing servers dynamically without any side-effects. -- simplifies the maintenance as it frees our mind from evaluating each server state. +- Se puede escalar añadiendo y quitando servidores dinámicamente, sin efectos secundarios. +- Se simplifica el mantenimiento ya que libera nuestra mente de tener que evaluar el estado de cada servidor.

diff --git a/sections/production/createmaintenanceendpoint.spanish.md b/sections/production/createmaintenanceendpoint.spanish.md index 4dfa86f8f..54b32e4bd 100644 --- a/sections/production/createmaintenanceendpoint.spanish.md +++ b/sections/production/createmaintenanceendpoint.spanish.md @@ -1,10 +1,10 @@ -# Create a maintenance endpoint +# Crea un endpoint de mantenimiento

-### One Paragraph Explainer +### Párrafo de explicación -A maintenance endpoint is a plain secured HTTP API that is part of the app code and its purpose is to be used by the ops/production team to monitor and expose maintenance functionality. For example, it can return a head dump (memory snapshot) of the process, report whether there are some memory leaks and even allow to execute REPL commands directly. This endpoint is needed where the conventional DevOps tools (monitoring products, logs, etc) fails to gather some specific type of information or you choose not to buy/install such tools. The golden rule is using professional and external tools for monitoring and maintaining the production, these are usually more robust and accurate. That said, there are likely to be cases where the generic tools will fail to extract information that is specific to Node or to your app – for example, should you wish to generate a memory snapshot at the moment GC completed a cycle – few NPM libraries will be glad to perform this for you but popular monitoring tools will be likely to miss this functionality +Un endpoint de mantenimiento es una API HTTP plana y securizada que es parte del código de la aplicación y su propósito es ser usado por el equipo de ops/producción para monitorizar y exponer funcionalidades de mantenimiento. Por ejemplo, puede devolver un "Heap Dump" (snapshot de memoria) del proceso, reportar si hay fugas de memoria e incluso permitir la ejecución de comandos REPL directamente. El endpoint se necesita donde las herramientas convencionales de devops (productos de monitorización, logs, etc) fallan en recoger algún tipo específico de información o si simplemente eliges no comprar/instalar dichas herramientas. La regla de oro es utilizar herramientas externas y profesionales para monitorizar y mantener la aplicación en producción, ya que normalmente éstas son más robustas y precisas. Dicho eso, puede haber casos en los que las herramientas genéricas fallen en extraer información específica de Node o de tu aplicación —por ejemplo, si deseas generar una snapshot de memoria en el instante en el que GC completa un ciclo— algo que unas cuantas librerías NPM estarán encantadas de hacer por ti, pero que probablemente falte en herramientas de monitorización populares.

diff --git a/sections/production/delegatetoproxy.spanish.md b/sections/production/delegatetoproxy.spanish.md index c7ed98d78..752aaff27 100644 --- a/sections/production/delegatetoproxy.spanish.md +++ b/sections/production/delegatetoproxy.spanish.md @@ -1,10 +1,10 @@ -# Delegate anything possible (e.g. static content, gzip) to a reverse proxy +# Delega todo lo posible (ej. contenido estático, gzip) a un proxy inverso

-### One Paragraph Explainer +### Párrafo de explicación -It’s very tempting to cargo-cult Express and use its rich middleware offering for networking related tasks like serving static files, gzip encoding, throttling requests, SSL termination, etc. This is a performance kill due to its single threaded model which will keep the CPU busy for long periods (Remember, Node’s execution model is optimized for short tasks or async IO related tasks). A better approach is to use a tool that expertise in networking tasks – the most popular are nginx and HAproxy which are also used by the biggest cloud vendors to lighten the incoming load on node.js processes. +Es muy tentador caer en el culto a Express y usar su rico sistema de middlewares para tareas relacionadas con la red, como servir archivos estáticos, encoding de gzip, peticiones de throttling, terminación SSL, etc. Esto mata el rendimiento ya que su modelo "single thread" mantendrá la CPU ocupada durante largos periodos de tiempo (recuerda, el modelo de ejecución de Node está optimizado para tareas cortas o asíncronas relacionadas con entrada/salida). Una mejor solución es utilizar una herramienta especializada en tareas de red; las más populares son nginx y HAproxy, usadas también por los mayores proveedores cloud para aligerar la carga entrante en procesos de node.js.

diff --git a/sections/production/detectvulnerabilities.spanish.md b/sections/production/detectvulnerabilities.spanish.md index e8dd22e30..6193227fe 100644 --- a/sections/production/detectvulnerabilities.spanish.md +++ b/sections/production/detectvulnerabilities.spanish.md @@ -1,15 +1,13 @@ -# Use tools that automatically detect vulnerable dependencies +# Usa herramientas de detección automática de vulnerabilidades

-### One Paragraph Explainer +### Párrafo de explicación -Modern Node applications have tens and sometimes hundreds of dependencies. If any of the dependencies -you use has a known security vulnerability your app is vulnerable as well. -The following tools automatically check for known security vulnerabilities in your dependencies: +Las aplicaciones modernas de Node tienen decenas y a veces cientos de dependencias. Si alguna de las dependencias que utilizas tiene una vulnerabilidad de seguridad, tu aplicación también es vulnerable. Las siguientes herramientas detectan automáticamente si hay vulnerabilidades de seguridad conocidas en tus dependencias: - [nsp](https://www.npmjs.com/package/nsp) - Node Security Project -- [snyk](https://snyk.io/) - Continuously find & fix vulnerabilities in your dependencies +- [snyk](https://snyk.io/) - Encuentra y corrige continuamente vulnerabilidades en tus dependencias

diff --git a/sections/production/frontendout.spanish.md b/sections/production/frontendout.spanish.md index 180bee4b2..df88b5ad0 100644 --- a/sections/production/frontendout.spanish.md +++ b/sections/production/frontendout.spanish.md @@ -1,16 +1,16 @@ -# Get your frontend assets out of Node +# Saca tus recursos frontend fuera de Node

-### One Paragraph Explainer +### Párrafo de explicación -In a classic web app the backend serves the frontend/graphics to the browser, a very common approach in the Node’s world is to use Express static middleware for streamlining static files to the client. BUT – Node is not a typical webapp as it utilizes a single thread that is not optimized to serve many files at once. Instead, consider using a reverse proxy (e.g. nginx, HAProxy), cloud storage or CDN (e.g. AWS S3, Azure Blob Storage, etc) that utilizes many optimizations for this task and gain much better throughput. For example, specialized middleware like nginx embodies direct hooks between the file system and the network card and uses a multi-threaded approach to minimize intervention among multiple requests. +En una aplicación web clásica, el backend sirve tanto frontend como gráficos al navegador. Una práctica muy común en el mundo de Node es utilizar el middleware estático de Express para mandar los archivos estáticos al cliente. PERO, Node no es una aplicación web típica, ya que utiliza un único thread que no está diseñado para servir muchos archivos a la vez. Así que, en vez de eso, considera utilizar un proxy inverso (como nginx o HAProxy), almacenamiento cloud, o un CDN (como AWS S3, Azure Blob Storage, etc.) que se vale de muchas optimizaciones para esta tarea y ganas un rendimiento mucho mayor. Por ejemplo, un middleware especializado como nginx incorpora enlaces directos entre el sistema de archivos y la tarjeta de red, y funciona bajo un proceso multi-threaded para minimizar las afectaciones entre múltiples peticiones. -Your optimal solution might wear one of the following forms: +Tu solución óptima podría seguir uno de los siguientes modelos: -1. Using a reverse proxy – your static files will be located right next to your Node application, only requests to the static files folder will be served by a proxy that sits in front of your Node app such as nginx. Using this approach, your Node app is responsible deploying the static files but not to serve them. Your frontend’s colleague will love this approach as it prevents cross-origin-requests from the frontend. +1. Usar un proxy inverso: tus archivos estáticos se ubicarán justo al lado de tu aplicación Node y solo las peticiones a la carpeta de archivos estáticos serán servidas mediante el proxy que se encuentra frente a tu aplicación Node, como nginx. Mediante esta técnica, tu aplicación Node es la responsable de publicar los archivos estáticos pero no de servirlos. Al colega de tu frontend le encantará este enfoque, ya que también evita peticiones cross-origin desde el frontend. -2. Cloud storage – your static files will NOT be part of your Node app content, they will be uploaded to services like AWS S3, Azure BlobStorage, or other similar services that were born for this mission. Using this approach, your Node app is not responsible deploying the static files neither to serve them, hence a complete decoupling is drawn between Node and the Frontend which is anyway handled by different teams. +2. Usar almacenamiento cloud: tus archivos estáticos NO serán parte del contenido de tu aplicación Node, sino que se subirán a servicios como AWS S3, Azure BlobStorage o similares que nacieron para este cometido. Mediante esta técnica, tu aplicación Node no es responsable ni de publicar los archivos estáticos ni de servirlos, por tanto se desenlaza por completo el backend del frontend, que de todos modos lo gestionan equipos diferentes.

diff --git a/sections/production/guardprocess.spanish.md b/sections/production/guardprocess.spanish.md index 5d3eeaa71..7288148fd 100644 --- a/sections/production/guardprocess.spanish.md +++ b/sections/production/guardprocess.spanish.md @@ -1,10 +1,10 @@ -# Guard and restart your process upon failure (using the right tool) +# Proteje y reinicia tu proceso ante fallos (mediante la herramienta adecuada)

-### One Paragraph Explainer +### Párrafo de explicación -At the base level, Node processes must be guarded and restarted upon failures. Simply put, for small apps and those who don’t use containers – tools like [PM2](https://www.npmjs.com/package/pm2-docker) are perfect as they bring simplicity, restarting capabilities and also rich integration with Node. Others with strong Linux skills might use systemd and run Node as a service. Things get more interesting for apps that use Docker or any container technology since those are usually accompanied by cluster management and orchestration tools (e.g. [AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html), [Kubernetes](https://kubernetes.io/), etc) that deploy, monitor and heal containers. Having all those rich cluster management features including container restart, why mess up with other tools like PM2? There’s no bulletproof answer. There are good reasons to keep PM2 within containers (mostly its containers specific version [pm2-docker](https://www.npmjs.com/package/pm2-docker)) as the first guarding tier – it’s much faster to restart a process and provide Node-specific features like flagging to the code when the hosting container asks to gracefully restart. Other might choose to avoid unnecessary layers. To conclude this write-up, no solution suits them all and getting to know the options is the important thing +Desde un nivel base, los procesos de Node deben protegerse reiniciándose en caso de fallo. En pocas palabras, para aplicaciones pequeñas y para aquellos que no usan contenedores: herramientas como [PM2](https://www.npmjs.com/package/pm2-docker) son perfectas, ya que brindan simplicidad, capacidad de reinicio y una gran integración con Node. Otros con sólidas habilidades en Linux podrían usar systemd y ejecutar Node como servicio. Las cosas se vuelven más interesantes para aplicaciones que usan Docker o cualquier tecnología de contenedores, ya que suelen ir acompañadas de herramientas de orquestación y gestión de clúster (por ejemplo, [AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html), [Kubernetes](https://kubernetes.io/), etc.) que despliegan, supervisan y reparan contenedores. Con toda esa abundancia en funciones de administración de clústeres, incluyendo reinicio de contenedores, ¿por qué ir a otras herramientas como PM2? No hay respuesta a prueba de balas. Hay buenas razones para mantener PM2 en el interior de contenedores (principalmente su versión específica para contenedores [pm2-docker](https://www.npmjs.com/package/pm2-docker)). Como primer nivel de protección, es mucho más rápido reiniciar un proceso y proporcionar características específicas de Node como marcar el código cuando el contenedor solicita un reinicio correctamente. Otros quizá elijan evitar capas innecesarias. Para concluir este artículo, ninguna solución es siempre la más conveniente, lo importante es conocer las opciones.

diff --git a/sections/production/lockdependencies.spanish.md b/sections/production/lockdependencies.spanish.md new file mode 100644 index 000000000..12019be2f --- /dev/null +++ b/sections/production/lockdependencies.spanish.md @@ -0,0 +1,69 @@ +# Bloquea dependencias + +

+ +### Párrafo de explicación + +Tu código depende de muchos paquetes externos. Digamos que 'requiere' y usa momentjs-2.1.4, entonces, por defecto, al deployear a producción NPM quizá baje momentjs 2.1.5, lo que por desgracia arroja nuevos bugs a la sopa. Utilizando archivos de configuración de NPM y el argumento ```–save-exact=true``` se le ordena a NPM hacer uso de la versión exacta que se instaló para que la próxima vez que ejecutes ```npm install``` (en producción o en un contenedor Docker que vas a mandar para testing) se instale la misma versión del paquete. Una solución alternativa y popular es usar un archivo `.shrinkwrap` (generado fácilmente con NPM) que declara con exactitud qué paquetes y versiones deben instalarse de modo que ningún entorno pueda verse tentado a buscar versiones más recientes. + +* **Actualización:** a partir de NPM 5, las dependencias se bloquean automáticamente mediante .shrinkwrap. Yarn, un gestor de paquetes en auge, también bloquea las dependencias por defecto. + +

+ +### Code example: .npmrc file that instructs NPM to use exact versions + +```npmrc +// save this as .npmrc file on the project directory +save-exact:true +``` + +

+ +### Code example: shrinkwrap.json file that distills the exact dependency tree + +```json +{ + "name": "A", + "dependencies": { + "B": { + "version": "0.0.1", + "dependencies": { + "C": { + "version": "0.1.0" + } + } + } + } +} +``` + +

+ +### Code example: NPM 5 dependencies lock file – package.json + +```json +{ + "name": "package-name", + "version": "1.0.0", + "lockfileVersion": 1, + "dependencies": { + "cacache": { + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz", + "integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg==" + }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=" + } + } + } + } +} +``` diff --git a/sections/production/measurememory.spanish.md b/sections/production/measurememory.spanish.md index 5d3d95cb3..c434b8197 100644 --- a/sections/production/measurememory.spanish.md +++ b/sections/production/measurememory.spanish.md @@ -1,10 +1,10 @@ -# Measure and guard the memory usage +# Mide y protege el uso de la memoria

-### One Paragraph Explainer +### Párrafo de explicación -In a perfect world, a web developer shouldn’t deal with memory leaks. In reality, memory issues are a known Node’s gotcha one must be aware of. Above all, memory usage must be monitored constantly. In the development and small production sites, you may gauge manually using Linux commands or NPM tools and libraries like node-inspector and memwatch. The main drawback of this manual activities is that they require a human being actively monitoring – for serious production sites, it’s absolutely vital to use robust monitoring tools e.g. (AWS CloudWatch, DataDog or any similar proactive system) that alerts when a leak happens. There are also few development guidelines to prevent leaks: avoid storing data on the global level, use streams for data with dynamic size, limit variables scope using let and const. +En un mundo perfecto, un desarrollador web no debería lidiar con fugas de memoria. En la realidad, los problemas de memoria son un asunto conocido de Node del que uno debe ser consciente. El uso de la memoria se debe monitorizar constantemente. En sites de desarrollo o pequeños sites en producción, quizá puedas medir la memoria manualmente mediante comandos Linux o herramientas NPM como node-inspector y memwatch. El principal inconveniente de estas actividades manuales es que requieren de una persona que las realice activamente. Para sites serios en producción, es absolutamente indispensable el uso de herramientas de monitorización robustas —por ej. AWS CloudWatch, DataDog o cualquier sistema proactivo similar— que alerten cuando ocurra una fuga de memoria. También existen algunas pautas para evitar estas fugas: evita almacenar datos a nivel global, utiliza streams de datos con tamaño dinámico, limita el scope de las variables mediante el uso de let y const.

diff --git a/sections/production/monitoring.spanish.md b/sections/production/monitoring.spanish.md index 68f42cbd9..1932e4e10 100644 --- a/sections/production/monitoring.spanish.md +++ b/sections/production/monitoring.spanish.md @@ -1,12 +1,12 @@ -# Monitoring! +# ¡Monitorizar!

-### One Paragraph Explainer +### Párrafo de explicación -At the very basic level, monitoring means you can *easily* identify when bad things happen at production. For example, by getting notified by email or Slack. The challenge is to choose the right set of tools that will satisfy your requirements without breaking your bank. May I suggest, start with defining the core set of metrics that must be watched to ensure a healthy state – CPU, server RAM, Node process RAM (less than 1.4GB), the number of errors in the last minute, number of process restarts, average response time. Then go over some advanced features you might fancy and add to your wish list. Some examples of a luxury monitoring feature: DB profiling, cross-service measuring (i.e. measure business transaction), front-end integration, expose raw data to custom BI clients, Slack notifications and many others. +En el nivel más básico, monitorizar significa que puedes identificar *fácilmente* cuándo ocurren cosas malas en producción. Por ejemplo, recibiendo notificaciones por email o por Slack. El desafío es elegir el conjunto adecuado de herramientas que satisfaga tus requisitos sin dejarte en quiebra. Puedo sugerir, comenzar con la definición del conjunto básico de métricas que se deben vigilar para garantizar un estado saludable: CPU, RAM del servidor, RAM del proceso de Node (menos de 1.4 GB), número de errores durante el último minuto, número de reinicios del proceso y tiempo medio de respuesta. Y a continuación, revisar otras métricas más avanzadas para añadirlas a tu lista de deseos. Algunos ejemplos de monitorización de lujo son: DB profiling, medición de servicios cruzados (es decir, medición de transacciones de negocio), integración front-end, exposición de datos sin procesar a clientes de BI personalizados, notificaciones Slack y muchas otras. -Achieving the advanced features demands lengthy setup or buying a commercial product such as Datadog, NewRelic and alike. Unfortunately, achieving even the basics is not a walk in the park as some metrics are hardware-related (CPU) and others live within the node process (internal errors) thus all the straightforward tools require some additional setup. For example, cloud vendor monitoring solutions (e.g. [AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/)) will tell you immediately about the hardware metrics but not about the internal app behavior. On the other end, Log-based solutions such as ElasticSearch lack the hardware view by default. The solution is to augment your choice with missing metrics, for example, a popular choice is sending application logs to [Elastic stack](https://www.elastic.co/products) and configure some additional agent (e.g. [Beat](https://www.elastic.co/products)) to share hardware-related information to get the full picture. +Implementar tales funciones avanzadas requiere de una instalación más bien larga, o bien comprar un producto comercial como Datadog, NewRelic y similares. Desafortunadamente, incluso implementar lo básico no es una caminata por el parque, ya que algunas métricas están relacionadas con el hardware (CPU) y otras residen en el interior del proceso de Node (errores internos). Por lo tanto, todas las herramientas "simples" requieren configuración adicional. Por ejemplo, las soluciones de monitorización de proveedores cloud (ej. [AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/)) te informarán de inmediato sobre las métricas del hardware, pero no sobre el comportamiento de la aplicación interna. Por otro lado, las soluciones basadas en logging como ElasticSearch carecen de la vista hardware por defecto. La solución es aumentar tu elección con las métricas ausentes. Por ejemplo, una opción popular es enviar logs de la aplicación a [Elastic stack](https://www.elastic.co/products) y configurar algún agente adicional (por ejemplo, [Beat](https://www.elastic.co/products)) para compartir información relacionada con el hardware y así obtener el cuadro completo.

diff --git a/sections/production/productoncode.spanish.md b/sections/production/productoncode.spanish.md index 4871ad396..ea29f60c9 100644 --- a/sections/production/productoncode.spanish.md +++ b/sections/production/productoncode.spanish.md @@ -1,16 +1,16 @@ -# Make your code production-ready +# Desarrolla código listo para producción

-### One Paragraph Explainer +### Párrafo de explicación -Following is a list of development tips that greatly affect the production maintenance and stability: +La siguiente lista contiene consejos de desarrollo que afectan en gran medida al mantenimiento y estabilidad de producción: -* The twelve-factor guide – Get familiar with the [Twelve factors](https://12factor.net/) guide -* Be stateless – Save no data locally on a specific web server (see separate bullet – ‘Be Stateless’) -* Cache – Utilize cache heavily, yet never fail because of cache mismatch -* Test memory – gauge memory usage and leaks as part your development flow, tools such as ‘memwatch’ can greatly facilitate this task -* Name functions – Minimize the usage of anonymous functions (i.e. inline callback) as a typical memory profiler will provide memory usage per method name -* Use CI tools – Use CI tool to detect failures before sending to production. For example, use ESLint to detect reference errors and undefined variables. Use –trace-sync-io to identify code that uses synchronous APIs (instead of the async version) -* Log wisely – Include in each log statement contextual information, hopefully in JSON format so log aggregators tools such as Elastic can search upon those properties (see separate bullet – ‘Increase visibility using smart logs’). Also, include transaction-id that identifies each request and allows to correlate lines that describe the same transaction (see separate bullet – ‘Include Transaction-ID’) -* Error management – Error handling is the Achilles’ heel of Node.js production sites – many Node processes are crashing because of minor errors while others hang on alive in a faulty state instead of crashing. Setting your error handling strategy is absolutely critical, read here my [error handling best practices](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) +* La guía de los doce factores: familiarízate con la guía de [Los doce factores](https://12factor.net/). +* Sin estado: no guardes datos localmente en un servidor web específico (consulta el apartado separado: "Sin estado"). +* Caché: utiliza mucho caché, pero evita problemas de matching. +* Test de memoria: vigila el uso de la memoria y las fugas como parte del flujo de desarrollo —herramientas como "memwatch" pueden facilitar enormemente esta tarea—. +* Funciones nombradas: minimiza el uso de funciones anónimas (es decir, inline callbacks) ya que el típico profiler de memoria relacionará cada uso de memoria con su función respectiva. +* Herramientas de CI: usa la herramienta de CI para detectar fallos antes de mandar el código a producción. Por ejemplo, usa ESLint para detectar errores de referencia y variables no definidas. Utiliza --trace-sync-io para identificar código que ejecute APIs síncronas en vez de su versión asincrónica. +* Logs inteligentes: incluye en cada entrada de log información contextual, si puede ser en formato JSON, para que las herramientas de agregadores de log como Elastic puedan buscar en esas propiedades (consulta la sección separada: "Aumentar la visibilidad mediante logs inteligentes"). Además, incluye la ID de transacción que identifica cada petición y permite correlacionar líneas que describen la misma transacción (vea sección aparte: "Incluir ID de transacción"). +* Gestión de errores: la gestión de errores es el talón de Aquiles de los sites en producción de Node.js: muchos procesos de Node se bloquean debido a errores menores, mientras que otros se cuelgan en un estado defectuoso en vez de fallar. Establecer una estrategia de gestión de errores es absolutamente crítico, lee aquí mis [mejores prácticas para la gestión de errores](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/). diff --git a/sections/production/setnodeenv.spanish.md b/sections/production/setnodeenv.spanish.md index 6fdff71f7..5eee12c7b 100644 --- a/sections/production/setnodeenv.spanish.md +++ b/sections/production/setnodeenv.spanish.md @@ -1,10 +1,10 @@ -# Set NODE_ENV = production +# Asigna NODE_ENV = production

-### One Paragraph Explainer +### Párrafo de explicación -Process environment variables is a set of key-value pairs made available to any running program, usually for configuration purposes. Though any variables can be used, Node encourages the convention of using a variable called NODE_ENV to flag whether we’re in production right now. This determination allows components to provide better diagnostics during development, for example by disabling caching or emitting verbose log statements. Any modern deployment tool – Chef, Puppet, CloudFormation, others – support setting environment variables during deployment +Las variables de entorno de proceso son un conjunto de pares clave-valor que se hacen disponibles para un programa en ejecución, generalmente con fines de configuración. Aunque se puede usar cualquier variable, Node fomenta la convención de usar una variable llamada NODE_ENV para marcar si estamos en producción en este momento. Esta información permite a los componentes proporcionar mejores diagnósticos durante el desarrollo, por ejemplo, deshabilitando el caché o registrando logs más detallados. Cualquier herramienta moderna de deploy —Chef, Puppet, CloudFormation y otros— soporta la asignación de variables de entorno durante el deploy.

diff --git a/sections/production/smartlogging.spanish.md b/sections/production/smartlogging.spanish.md index 5aab52d1f..8c1f30f9f 100644 --- a/sections/production/smartlogging.spanish.md +++ b/sections/production/smartlogging.spanish.md @@ -1,16 +1,16 @@ -# Make your app transparent using smart logs +# Haz transparente tu app mediante logs inteligentes

-### One Paragraph Explainer +### Párrafo de explicación -Since you print out log statements anyway and you're obviously in a need of some interface that wraps up production information where you can trace errors and core metrics (e.g. how many errors happen every hour and which is your slowest API end-point) why not invest some moderate effort in a robust logging framework that will tick all boxes? Achieving that requires a thoughtful decision on three steps: +Ya que vas a printar logs igual y obviamente necesitas una interfaz que resuma información de producción donde puedas rastrear errores y métricas core (por ejemplo, cuántos errores ocurren cada hora y cuál es el endpoint más lento de la API), ¿por qué no invertir un esfuerzo moderado en un framework de logging robusto que lo haga todo? Conseguir esto requiere una decisión reflexiva en tres pasos: -**1. smart logging** – at the bare minimum you need to use a reputable logging library like [Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan) and write meaningful information at each transaction start and end. Consider to also format log statements as JSON and provide all the contextual properties (e.g. user id, operation type, etc) so that the operations team can act on those fields. Include also a unique transaction ID at each log line, for more information refer to the bullet below “Write transaction-id to log”. One last point to consider is also including an agent that logs the system resource like memory and CPU like Elastic Beat. +**1. Logging inteligente** – como mínimo, deberías utilizar una librería de logging conocida, como [Winston](https://github.com/winstonjs/winston) o [Bunyan](https://github.com/trentm/node-bunyan), y guardar información significativa en cada inicio y fin de transacción. Considera también guardar logs en formato JSON y añadir información contextual mediante propiedades (por ejemplo, la id de usuario, el tipo de operación, etc.) para que el equipo de operaciones pueda actuar en esos aspectos. Incluye también una ID de transacción única en cada línea de log (para más información consulta el punto "Escribir ID de transacción en el log"). Un último punto a considerar también incluye un agente que registre el uso de recursos del sistema, como la memoria y la CPU, como Elastic Beat. -**2. smart aggregation** – once you have comprehensive information on your servers file system, it’s time to periodically push these to a system that aggregates, facilities and visualizes this data. The Elastic stack, for example, is a popular and free choice that offers all the components to aggregate and visualize data. Many commercial products provide similar functionality only they greatly cut down the setup time and require no hosting. +**2. Agregación inteligente** – una vez tengas información exhaustiva en el sistema de archivos del server, es hora de enviarla periódicamente a un sistema que agregue, configure y visualice estos datos. Elastick stack, por ejemplo, es una opción popular y gratuita que ofrece todos los componentes para agregar y visualizar datos. Muchos productos comerciales ofrecen una funcionalidad similar reduciendo enormemente el tiempo de configuración y evitando el requisito de hosting. -**3. smart visualization** – now the information is aggregated and searchable, one can be satisfied only with the power of easily searching the logs but this can go much further without coding or spending much effort. We can now show important operational metrics like error rate, average CPU throughout the day, how many new users opted-in in the last hour and any other metric that helps to govern and improve our app +**3. Visualización inteligente** – ahora que la información se ha agregado y se puede buscar, uno puede quedar satisfecho solo con poder buscar fácilmente entre los logs, pero esto puede ir mucho más allá sin necesidad de codificar ni invertir mucho esfuerzo. Ahora podemos mostrar importantes métricas operacionales como la tasa de error, uso promedio de la CPU durante el día, cuántos usuarios nuevos se unieron en la última hora y cualquier otra métrica que ayude a regular y mejorar nuestra app.

diff --git a/sections/production/utilizecpu.spanish.md b/sections/production/utilizecpu.spanish.md index c99a081b0..13d925d38 100644 --- a/sections/production/utilizecpu.spanish.md +++ b/sections/production/utilizecpu.spanish.md @@ -1,10 +1,10 @@ -# Utilize all CPU cores +# Utiliza todos los núcleos de la CPU

-### One Paragraph Explainer +### Párrafo de explicación -It might not come as a surprise that in its basic form, Node runs over a single thread=single process=single CPU. Paying for beefy hardware with 4 or 8 CPU and utilizing only one sounds crazy, right? The quickest solution which fits medium sized apps is using Node’s Cluster module which in 10 lines of code spawns a process for each logical core and route requests between the processes in a round-robin style. Even better, use PM2 which sugarcoats the clustering module with a simple interface and cool monitoring UI. While this solution works well for traditional applications, it might fall short for applications that require top-notch performance and robust DevOps flow. For those advanced use cases, consider replicating the NODE process using custom deployment script and balancing using a specialized tool such as nginx or use a container engine such as AWS ECS or Kubernetees that have advanced features for deployment and replication of processes. +Quizá no sea una sorpresa que, en su forma básica, Node se ejecute en un solo subproceso = proceso único = una sola CPU. Pagar por hardware pesado con 4 u 8 CPUs y usar solo una suena absurdo, ¿verdad? La solución más rápida que se adapta a aplicaciones de tamaño medio es utilizar el módulo Node's Cluster, que en 10 líneas de código genera un proceso para cada núcleo lógico y redirige las peticiones entre los procesos al estilo round-robin. Mejor aún, PM2 endulza Node's Cluster con una interfaz de monitorización simple y genial. Si bien esta solución funciona bien para aplicaciones tradicionales, se puede quedar corta para aplicaciones que requieren de un rendimiento de primer nivel y de un flujo DevOps robusto. Para esos casos más avanzados, considera la posibilidad de replicar el proceso NODE mediante un script personalizado de deploy, y balancear la carga a través de herramientas especializadas como nginx, o a través de un motor de contenedores como AWS ECS o Kubernetees, que tienen funciones avanzadas para deployment y replicación de procesos.

diff --git a/sections/projectstructre/breakintcomponents.spanish.md b/sections/projectstructre/breakintcomponents.spanish.md index 1da60edcc..083399e21 100644 --- a/sections/projectstructre/breakintcomponents.spanish.md +++ b/sections/projectstructre/breakintcomponents.spanish.md @@ -1,36 +1,37 @@ -# 组件式构建你的解决方案 +# Estructura tu solución en componentes

+### Párrafo de explicación -### 一段解释 +Para aplicaciones de tamaño medio o superior, los monolitos son bastante malos. Un enorme software con muchas dependencias se torna complicado de manejar y por lo general termina en código espagueti. Incluso arquitectos inteligentes –aquellos con suficiente habilidad como para domar a la bestia y "modularizarla"– invierten gran esfuerzo mental en el diseño, y cada cambio requiere una evaluación cuidadosa del impacto en dependencias. La solución definitiva es desarrollar software pequeño: dividir el total en componentes autocontenidos, que no compartan archivos con otros, cada uno de los cuales constituye un pequeño conjunto de archivos (ej. API, servicio, acceso de datos, pruebas, etc), lo que aporta una estructura muy fácil de digerir. Algunos lo llaman arquitectura de "microservicios". Es importante entender que los microservicios no son ninguna especificación que debas seguir, sino un conjunto de principios. Puedes optar por atenerte a muchos principios en una arquitectura de microservicios completa, o simplemente adoptar unos pocos. Ambas opciones son buenas siempre y cuando mantengas baja la complejidad del software. Al final, lo que deberías hacer es crear límites básicos entre componentes, asignar una carpeta en la raíz de tu proyecto para cada entidad de negocio (componente) y hacer que sea autocontenido. A otros componentes solo se les permite consumir su funcionalidad a través de su interfaz pública o API. Esta es la base para mantener tus componentes simples, evitar el infierno de las dependencias y abrir el camino a microservicios completos en el futuro una vez tu aplicación crezca. -对于中等规模的应用程序及以上,一个代码库是非常糟糕的 - 一个包含很多依赖的大型软件很难理解,往往导致代码混乱。即使是那些擅长解决负责问题和 "模块化" 的聪明架构师 - 在设计上花费了很大的脑力, 每一个变化都需要仔细评估对其他依赖对象的影响。最终的解决方案是开发小型软件:将整个堆栈划分为独立的组件,这些组件不与其他组件共享文件,每个组件由很少的文件构成(例如API、服务、数据访问、测试等),因此很容易理解它。有些人可能称之为 "microservices" 架构 - 重要的是要理解 microservices 不是一个你必须遵循的规范,而是一套原则。您可以将许多原则引入到成熟的 microservices 体系结构中, 或者只采用少数几个。只要您保持软件的复杂性低, 两者都是好的。最起码应该做的是在组件之间创建一个基本边界, 为每个业务组件在项目根目录中分配一个文件夹, 并使其自包含-其他组件只能通过其公共接口或 API 使用其功能。这是保持您的组件简单的基础,在未来, 一旦您的应用程序增长,避免依赖性地狱,为全面的 microservices 架构铺平了道路. +

+ +### Blog Quote: "Scaling requires scaling of the entire application" + + From the blog MartinFowler.com + +> Monolithic applications can be successful, but increasingly people are feeling frustrations with them - especially as more applications are being deployed to the cloud. Change cycles are tied together - a change made to a small part of the application requires the entire monolith to be rebuilt and deployed. Over time it's often hard to keep a good modular structure, making it harder to keep changes that ought to only affect one module within that module. Scaling requires scaling of the entire application rather than parts of it that require greater resource.

+### Blog Quote: "So what does the architecture of your application scream?" -### 博客引用: "伸缩需要对整个应用程序进行伸缩设计" - 摘自博客 MartinFowler.com - - > 单个应用程序可以成功, 但越来越多的人对它们感到失望 - 尤其是随着更多的应用程序被部署到云中。更改周期被捆绑在一起 - 对应用程序的一小部分进行更改, 需要重建和部署整个整体。随着时间的推移, 通常很难保持一个良好的模块化结构, 这使得更改哪怕只会影响该模块中的一个模块变得更加困难。伸缩设计需要扩展整个应用程序, 而不是它的部分,这往往需要更多资源。 + From the blog [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) -

- - ### 博客引用: "那么, 你的应用程序的架构声明了什么?" - 摘自博客 [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) - -> ...如果你正在寻找一个图书馆的建筑架构, 你可能会看到一个盛大的入口, 一个 check-in-out 的文员, 阅读区, 小会议室, 画廊, 画廊后面容纳了装载所有图书馆书籍的书架。建筑会声明: 图书馆.
-那么, 应用程序的体系架构会声明什么呢? 当您查看顶级目录结构和最高级别包中的源文件时; 他们声明: 医疗保健系统, 或会计系统, 或库存管理系统? 或者他们声明: Rails, 或Spring/Hibernate, 或 ASP?. +> ...if you were looking at the architecture of a library, you’d likely see a grand entrance, an area for check-in-out clerks, reading areas, small conference rooms, and gallery after gallery capable of holding bookshelves for all the books in the library. That architecture would scream: Library.
+So what does the architecture of your application scream? When you look at the top level directory structure, and the source files in the highest level package; do they scream: Health Care System, or Accounting System, or Inventory Management System? Or do they scream: Rails, or Spring/Hibernate, or ASP?.

- ### 推荐: 通过独立组件构建解决方案 +### Good: Structure your solution by self-contained components + ![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +

-

+### Bad: Group your files by technical role -### 避免: 按技术角色对文件进行分组 ![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/configguide.spanish.md b/sections/projectstructre/configguide.spanish.md index 0aa6bbd82..8f7067734 100644 --- a/sections/projectstructre/configguide.spanish.md +++ b/sections/projectstructre/configguide.spanish.md @@ -1,20 +1,20 @@ -# Use environment aware, secure and hierarchical config +# Utiliza configuración consciente del entorno, segura y jerárquica

-### One Paragraph Explainer +### Párrafo de explicación -When dealing with configuration data, many things can just annoy and slow down: +Cuando se trata de datos de configuración, hay muchas molestias que pueden suponer un retraso: -1. setting all the keys using process environment variables becomes very tedious when in need to inject 100 keys (instead of just committing those in a config file), however when dealing with files only the DevOps admins cannot alter the behavior without changing the code. A reliable config solution must combine both configuration files + overrides from the process variables +1. Setear todas las claves utilizando variables de entorno se vuelve muy tedioso cuando hay que inyectar 100 claves (en vez de simplemente commitearlas en un archivo de configuración). Sin embargo, tratar solo con archivos provoca que los administradores DevOps no puedan alterar el comportamiento sin cambiar el código. Una solución confiable para la configuración debe combinar archivos de configuración + la sobreescritura desde variables de entorno. -2. when specifying all keys in a flat JSON, it becomes frustrating to find and modify entries when the list grows bigger. A hierarchical JSON file that is grouped into sections can overcome this issue + few config libraries allow to store the configuration in multiple files and take care to union all at runtime. See example below +2. Al especificar todas las claves en JSON plano, se vuelve frustrante encontrar y modificar las entradas cuando la lista crece. Un archivo JSON jerárquico y agrupado en secciones puede superar este problema + pocas librerías de configuración permiten almacenar la configuración en múltiples archivos encargándose también de su unión en tiempo de ejecución. Mira el ejemplo de abajo. -3. storing sensitive information like DB password is obviously not recommended but no quick and handy solution exists for this challenge. Some configuration libraries allow to encrypt files, others encrypt those entries during GIT commits or simply don't store real values for those entries and specify the actual value during deployment via environment variables. +3. Evidentemente, no es recomendable almacenar información sensible como la contraseña de la base de datos, pero no existen soluciones rápidas y cómodas para este desafío. Algunas librerías de configuración permiten encriptar archivos, otros encriptan esas entradas durante los commits de GIT o simplemente no almacenan valores reales para esas entradas y especifican el valor verdadero durante el deploy a través de variables de entorno. -4. some advanced configuration scenarios demand to inject configuration values via command line (vargs) or sync configuration info via a centralized cache like Redis so multiple servers will use the same configuration data. +4. Algunos escenarios de configuración avanzada exigen inyectar los valores de configuración a través de línea de comandos (vargs) o que se sincronicen a través de un caché centralizado como Redis para que múltiples servidores puedan usar los mismos datos de configuración. -Some configuration libraries can provide most of these features for free, have a look at NPM libraries like [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf) and [config](https://www.npmjs.com/package/config) which tick many of these requirements. +Algunas librerías de configuración pueden proporcionar muchas de estas características sin coste, echa un vistazo a paquetes NPM como [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf) y [config](https://www.npmjs.com/package/config) los cuales cumplen con muchos de estos requisitos.

diff --git a/sections/projectstructre/separateexpress.spanish.md b/sections/projectstructre/separateexpress.spanish.md index c60ea4b57..cc396641a 100644 --- a/sections/projectstructre/separateexpress.spanish.md +++ b/sections/projectstructre/separateexpress.spanish.md @@ -1,10 +1,10 @@ -# Separate Express 'app' and 'server' +# Separa la 'app' de Express y el 'server'

-### One Paragraph Explainer +### Párrafo de explicación -The latest Express generator comes with a great practice that is worth to keep - the API declaration is separated from the network related configuration (port, protocol, etc). This allows testing the API in-process, without performing network calls, with all the benefits that it brings to the table: fast testing execution and getting coverage metrics of the code. It also allows deploying the same API under flexible and different network conditions. Bonus: better separation of concerns and cleaner code +El último generador de Express viene con una gran práctica que vale la pena mantener. La declaración API separada de la configuración relacionada con la red (puerto, protocolo, etc). Esto permite testear la API sin realizar llamadas de red, con todos los beneficios que ello conlleva: una ejecución rápida de los tests y la obtención de métricas de coverage. También permite desplegar la misma API bajo diferentes condiciones de red. Y otro plus: una mejor división de responsabilidades y un código más limpio.

diff --git a/sections/projectstructre/wraputilities.spanish.md b/sections/projectstructre/wraputilities.spanish.md index 23cca38ca..1e366cb52 100644 --- a/sections/projectstructre/wraputilities.spanish.md +++ b/sections/projectstructre/wraputilities.spanish.md @@ -1,10 +1,10 @@ -# Wrap common utilities as npm packages +# Encierra utilidades comunes en paquetes npm

-### One Paragraph Explainer +### Párrafo de explicación -Once you start growing and have different components on different servers which consumes similar utilities, you should start managing the dependencies - how can you keep 1 copy of your utility code and let multiple consumer components use and deploy it? well, there is a tool for that, it's called npm... Start by wrapping 3rd party utility packages with your own code to make it easily replaceable in the future and publish your own code as private npm package. Now, all your code base can import that code and benefit free dependency management tool. It's possible to publish npm packages for your own private use without sharing it publicly using [private modules](https://docs.npmjs.com/private-modules/intro), [private registry](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) or [local npm packages](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) +Al empezar a crecer y tener diferentes componentes en diferentes servidores que consumen utilidades similares, deberías empezar a gestionar las dependencias. ¿Cómo puedes mantener una sola copia de tu código de útiles mientras permites que múltiples componentes lo usen y lo desplieguen? Bueno, hay una herramienta para eso llamada npm... Empieza por encerrar paquetes de terceros con tu propio código para hacerlo fácilmente reemplazable en un futuro y publica tu propio código como un paquete privado npm. Ahora, todo tu código base puede importar ese código y beneficiarse gratuitamente de la herramienta de gestión de paquetes. Es posible publicar paquetes npm para tu propio uso privado sin compartirlo públicamente mediante el uso de [módulos privados](https://docs.npmjs.com/private-modules/intro), [registro privado](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) o [paquetes npm locales](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc).

diff --git a/sections/testingandquality/citools.spanish.md b/sections/testingandquality/citools.spanish.md index e26bd66d5..037ac662d 100644 --- a/sections/testingandquality/citools.spanish.md +++ b/sections/testingandquality/citools.spanish.md @@ -1,10 +1,10 @@ -# Carefully choose your CI platform +# Elige tu plataforma de CI con cuidado

-### One Paragraph Explainer +### Párrafo de explicación -The CI world used to be the flexibility of [Jenkins](https://jenkins.io/) vs the simplicity of SaaS vendors. The game is now changing as SaaS providers like [CircleCI](https://circleci.com/) and [Travis](https://travis-ci.org/) offer robust solutions including Docker containers with minimum setup time while Jenkins tries to compete on 'simplicity' segment as well. Though one can setup rich CI solution in the cloud, should it required to control the finest details Jenkins is still the platform of choice. The choice eventually boils down to which extent the CI process should be customized: free and setup free cloud vendors allow to run custom shell commands, custom docker images, adjust the workflow, run matrix builds and other rich features. However, if controlling the infrastructure or programming the CI logic using a formal programming language like Java is desired - Jenkins might still be the choice. Otherwise, consider opting for the simple and setup free cloud option +El mundo de la CI solía ser la flexibilidad de Jenkins vs la simplicidad de proveedores SaaS. El juego ahora cambia ya que proveedores SaaS como CircleCI y Travis ofrecen soluciones robustas, incluyendo contenedores Docker con instalación y configuración mínimas, mientras Jenkins también intenta competir en el segmento de la "simplicidad". Aunque uno puede instalar una solución de CI completa en cloud, si fuera necesario controlar hasta el más mínimo detalle, Jekins sigue siendo la plataforma recomendada. Llega un momento en el que la elección se reduce lo siguiente: ¿hasta qué punto tengo que personalizar mi CI? Los proveedores cloud permiten ejecutar comandos de shell personalizados, imágenes Docker personalizadas, ajustar el flujo de trabajo, ejecutar compilaciones en clúster y otras funciones avanzadas. Sin embargo, si se desea controlar la infraestructura o programar la lógica de CI utilizando un lenguaje formal de programación como Java, Jenkins aún podría ser la opción. De lo contrario, considera optar por la opción de cloud simple y libre de instalación.