<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Israel Blancas</title>
    <description>The latest articles on DEV Community by Israel Blancas (@iblancasa).</description>
    <link>https://dev.to/iblancasa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23257%2F4f59cbfb-4cb2-4dbd-a03b-cec2d6bb6a35.jpg</url>
      <title>DEV Community: Israel Blancas</title>
      <link>https://dev.to/iblancasa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iblancasa"/>
    <language>en</language>
    <item>
      <title>Cómo los perfiles JSON me ayudaron a que la IA me entendiera</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Wed, 24 Sep 2025 22:39:54 +0000</pubDate>
      <link>https://dev.to/iblancasa/como-los-perfiles-json-me-ayudaron-a-que-la-ia-me-entendiera-12</link>
      <guid>https://dev.to/iblancasa/como-los-perfiles-json-me-ayudaron-a-que-la-ia-me-entendiera-12</guid>
      <description>&lt;p&gt;El otro día, hablando con &lt;a href="https://www.linkedin.com/in/carloscaballerogonzalez" rel="noopener noreferrer"&gt;Carlos Caballero&lt;/a&gt;, me comentaba el suplicio que a veces es generar miniaturas para sus vídeos de YouTube. No sé si sabéis, pero Carlos tiene &lt;a href="https://www.youtube.com/c/DotTechES" rel="noopener noreferrer"&gt;un canal sobre programación y tecnología&lt;/a&gt;, y el toque personal, la imagen, es crucial. Me explicaba que, por mucho que se esforzara con los &lt;em&gt;prompts&lt;/em&gt;, los resultados que le devolvía la IA a menudo eran genéricos, carentes de la chispa o del estilo visual que él buscaba. No es que las imágenes fueran feas, es que no eran &lt;em&gt;suyas&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Me reconozco en su problema. A menudo, cuando uso una IA generativa, le pido que me escriba un texto sobre algo muy concreto, como alguna documentación sobre OpenTelemetry, y lo que me devuelve es correcto, pero le falta contexto. No sabe que quiero que se enfoque en los problemas que soluciona, no en cómo está implementado. Le falta un mapa, una guía que le diga no solo &lt;em&gt;qué&lt;/em&gt; hacer, sino &lt;em&gt;cómo&lt;/em&gt; hacerlo para que el resultado sea coherente con lo que busco.&lt;/p&gt;

&lt;p&gt;Fue entonces cuando le hablé de la idea que había visto un tweet (si podemos seguir llamándolo así): usar &lt;strong&gt;perfiles de contexto JSON (JSON Context Profiles)&lt;/strong&gt;. Lo comenté también en el segundo episodio de “&lt;a href="https://www.youtube.com/watch?v=y_ReQycxh2U" rel="noopener noreferrer"&gt;Compila o revienta&lt;/a&gt;”. No es una varita mágica, sino una manera mucho más estructurada y eficiente de comunicarnos con la IA. En lugar de una simple instrucción, le damos un archivo de configuración, un pequeño &lt;em&gt;dossier&lt;/em&gt; con todas las reglas del juego.&lt;/p&gt;

&lt;p&gt;La clave está en ir más allá del &lt;em&gt;prompt&lt;/em&gt; simple y crear un perfil con información detallada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/30fb1ca7e4c7007a67c6af00482a8899/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/30fb1ca7e4c7007a67c6af00482a8899/href" rel="noopener noreferrer"&gt;https://medium.com/media/30fb1ca7e4c7007a67c6af00482a8899/href&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Un mapa de carretera para la IA
&lt;/h3&gt;

&lt;p&gt;La clave está en ir más allá del &lt;em&gt;prompt&lt;/em&gt; simple y crear un perfil con información detallada. Por ejemplo, imagina un archivo JSON que contenga:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"meta"&lt;/strong&gt; : Aquí defines los parámetros básicos: el idioma, el tono, la longitud del texto o, en el caso de Carlos, el estilo visual (minimalista, con colores vivos, etc.). Le dices a la IA a quién se dirige y cuál es el propósito de su trabajo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"restrictions"&lt;/strong&gt; : Aquí pones los límites. "No uses más de 1000 palabras", "no incluyas texto", "los colores principales deben ser el azul y el naranja". Esto evita que la IA se vaya por las ramas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"data"&lt;/strong&gt; : Esta es la parte más interesante. En lugar de un simple texto, le proporcionas una estructura de datos. Para las miniaturas de Carlos, por ejemplo, podría ser una lista de conceptos clave, un titular que debe destacar, o los elementos visuales que tienen que aparecer (un ordenador, un logo de Python, una taza de café). Esto obliga a la IA a seguir una estructura de salida específica.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto simplifica enormemente el proceso. En lugar de reescribir un &lt;em&gt;prompt&lt;/em&gt; larguísimo una y otra vez, solo tienes que cambiar los datos del archivo JSON.&lt;/p&gt;

&lt;h3&gt;
  
  
  Poniéndolo en práctica
&lt;/h3&gt;

&lt;p&gt;Por ejemplo, si doy a &lt;a href="https://gemini.google.com/" rel="noopener noreferrer"&gt;Gemini&lt;/a&gt; esta imagen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i5600u52x2gedn071zo.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i5600u52x2gedn071zo.jpeg" alt="Alhambra de Granada" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Alhambra de Granada&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Y le pido al modelo que me genere el JSON Context Profile, obtengo esto de vuelta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "image_description": "A dusk-time, wide-angle shot of the Alhambra complex in Granada, Spain, with a focus on its architectural details. The image is taken from a lower vantage point, looking up at the complex. The sky is a gradient of blue and purple, with clouds obscuring the tops of the mountains in the background. The Alhambra itself is a collection of various architectural styles. The most prominent feature is a large, rectangular, Renaissance-style palace building on the right, which is the Palace of Charles V. To its left and slightly forward is a large, older, and more fortified structure, likely the Alcazaba, with prominent crenellated walls and towers. In the center, a bell tower rises above the lower buildings, which are a mix of terracotta-colored structures with traditional Spanish tiling and arched windows. The foreground is filled with the dark green foliage of trees, which partially obscure the base of the fortress walls. The buildings are illuminated by warm, yellow-orange light, creating a strong contrast with the cooler tones of the sky and mountains. The lighting suggests that the photo was taken around sunset or just after.",
  "location": "Alhambra, Granada, Spain",
  "time_of_day": "Dusk/Sunset",
  "architectural_styles": [
    "Moorish/Nasrid",
    "Renaissance"
  ],
  "key_features": [
    "Alcazaba fortress",
    "Palace of Charles V",
    "Bell tower",
    "Forested hillside",
    "Mountain range in the background"
  ],
  "dominant_colors": [
    "Terracotta (buildings)",
    "Dark green (trees)",
    "Blue/Purple (sky and mountains)",
    "Yellow/Orange (lighting)"
  ],
  "mood": "Majestic, historic, serene",
  "possible_use_case": "Travel and tourism promotion, historical documentation, photography portfolio"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El modelo de IA, al recibir esta información estructurada, tiene una guía clara. Sabe que debe generar una imagen y que debe incluir los elementos visuales y el texto que le has pasado. La probabilidad de que el resultado se ajuste a tus expectativas se dispara.&lt;/p&gt;

&lt;p&gt;De hecho, si en una nueva conversación, pedimos que se genere una imagen basada en ese prompt, obtendremos esto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i5600u52x2gedn071zo.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i5600u52x2gedn071zo.jpeg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9vda7zwm2kengycp3c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9vda7zwm2kengycp3c5.png" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A la izquierda, la imagen original. A la derecha, la imagen generada desde el JSON Context Profile por Gemini&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A partir del JSON, podemos modificarlo y obtener imágenes similares pero con modificaciones. Por ejemplo, puedo cambiar el cielo de la fotografía:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fywnag3mk92uziaycpe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fywnag3mk92uziaycpe.png" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dependiendo del modelo, esto será más o menos acertado. Además, según la imagen, algunos parámetros aparecerán o desaparecerán: ángulo de la cámara, texto, edificios, número de personas…&lt;/p&gt;

&lt;p&gt;También podemos hacerlo utilizando varias fotografías, de forma que podemos pedir a nuestro modelo de confianza un JSON que extraiga el estilo de lo que queremos hacer y nos permita alcanzar los resultados deseados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/7c86c9eba896155bceafd48e65906615/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/7c86c9eba896155bceafd48e65906615/href" rel="noopener noreferrer"&gt;https://medium.com/media/7c86c9eba896155bceafd48e65906615/href&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al final, no se trata de convertir a la IA en una mente creativa, sino de usarla como la herramienta inteligente que es. Si le damos las instrucciones adecuadas, de forma precisa y estructurada, el trabajo se vuelve mucho más eficiente y los resultados, más satisfactorios. Y, con suerte, Carlos tendrá miniaturas que no solo sean correctas, sino que realmente le representen.&lt;/p&gt;




</description>
      <category>gemini</category>
      <category>generativeaitools</category>
      <category>inteligenciaartifici</category>
      <category>artificialintelligen</category>
    </item>
    <item>
      <title>Creando agentes con ADK</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Fri, 12 Sep 2025 08:38:40 +0000</pubDate>
      <link>https://dev.to/iblancasa/creando-agentes-con-adk-110h</link>
      <guid>https://dev.to/iblancasa/creando-agentes-con-adk-110h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgu6mea3krdgk1r6970g6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgu6mea3krdgk1r6970g6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Alguna vez te has detenido a pensar en el potencial que reside en programas de inteligencia artificial capaces no solo de responder, sino de &lt;em&gt;razonar&lt;/em&gt;, &lt;em&gt;planificar&lt;/em&gt; y &lt;em&gt;actuar&lt;/em&gt; para desentrañar tareas de una complejidad sorprendente? La respuesta, en esencia, se esconde tras la fascinante idea de los &lt;strong&gt;Agentes de IA&lt;/strong&gt;. Y es aquí donde Google, con su recién estrenado &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/agent-development-kit/quickstart?hl=es" rel="noopener noreferrer"&gt;&lt;strong&gt;Agent Development Kit (ADK)&lt;/strong&gt;&lt;/a&gt;, nos allana el camino de una manera notable.&lt;/p&gt;

&lt;p&gt;Imagina el ADK como una caja de herramientas indispensable, forjada en &lt;strong&gt;Python&lt;/strong&gt;  — sí, ese lenguaje que, con toda probabilidad, ya dominas — . Su propósito no es otro que el de facilitarte la construcción de estos asistentes inteligentes. Con él, serás capaz de insuflar vida a agentes dotados de la capacidad de razonar, de emplear &lt;strong&gt;herramientas externas&lt;/strong&gt; (como buscar información en la vasta red o interactuar con otras API) y de tomar &lt;strong&gt;decisiones dinámicas&lt;/strong&gt;. Todo ello, por supuesto, impulsado por la robustez de los &lt;strong&gt;Modelos de Lenguaje Grandes (LLMs)&lt;/strong&gt;, como Gemini.&lt;/p&gt;

&lt;p&gt;Si el universo de los agentes de IA te ha atraído siempre, pero la incertidumbre sobre por dónde empezar te ha frenado, este es, sin duda, tu momento. Acompáñame en este recorrido y descubrirás lo asombrosamente sencillo que puede ser erigir tu primer agente.&lt;/p&gt;

&lt;h3&gt;
  
  
  La esencia de un Agente de IA: ¿Qué lo hace singular?
&lt;/h3&gt;

&lt;p&gt;Piensa en un asistente digital extraordinariamente inteligente. Esa es, en su sentido más puro, la definición de un Agente de IA. Pero, ¿qué elementos lo distinguen de cualquier otro programa? Un agente de IA utiliza un “cerebro” avanzado, como los Modelos de Lenguaje Grandes (LLM) de Google (por ejemplo, Gemini), para entender lo que le pides y encontrar la mejor manera de hacerlo. No se limita a lo que ya sabe, pues puede usar “Herramientas” externas para obtener la información que necesita, ya sea realizando una búsqueda en Google, consultando una base de datos o interactuando con otras aplicaciones. Basándose en su razonamiento y la información que recopila, puede tomar decisiones y ejecutar acciones para cumplir con su objetivo. Incluso para tareas muy complejas, puedes tener un Agente “padre” o principal que coordine a un equipo de &lt;strong&gt;sub-agentes&lt;/strong&gt; , cada uno especializado en una parte del trabajo, como un equipo de especialistas que trabajan juntos, por ejemplo, uno podría escribir un guion, otro buscar imágenes y un tercero unirlos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Development Kit (ADK) de Google: Desmitificando la creación de agentes
&lt;/h3&gt;

&lt;p&gt;Si la mera idea de construir estos agentes te parece una empresa titánica, respira tranquilo. Google, consciente de ello, ha concebido el &lt;strong&gt;Agent Development Kit (ADK)&lt;/strong&gt; con la clara intención de simplificarnos la existencia. El ADK es un &lt;em&gt;framework&lt;/em&gt; de &lt;strong&gt;código abierto y gratuito&lt;/strong&gt; de Google, un compendio de herramientas y librerías que te ayuda a construir, probar, desplegar y administrar tus agentes de IA de una manera más sencilla y organizada. Una de sus virtudes más destacadas reside en su filosofía &lt;strong&gt;“code-first”&lt;/strong&gt; , lo que implica que tus agentes cobran vida a través de la programación directa en Python, otorgándote un dominio total sobre su funcionamiento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72w3yw35wfenccq0sqmp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72w3yw35wfenccq0sqmp.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La flexibilidad es otra de sus grandes bazas; no estás constreñido a un único modelo, pues tienes la libertad de optar por Gemini, por otros modelos de Google, o incluso por soluciones de terceros. Una vez que tu agente está listo, puedes ubicarlo en la nube de tu preferencia o en tus propios servidores. Además, el ADK ha sido diseñado para ser &lt;strong&gt;interoperable&lt;/strong&gt; , lo que significa que puede convivir y colaborar sin fricciones con otros &lt;em&gt;frameworks&lt;/em&gt; y herramientas populares en el ámbito de la IA. Los agentes en ADK se pueden clasificar en: &lt;strong&gt;Agentes LLM&lt;/strong&gt; (los más adaptables), &lt;strong&gt;Agentes de Flujo de Trabajo&lt;/strong&gt; (para secuencias de tareas predefinidas) y &lt;strong&gt;Agentes Personalizados&lt;/strong&gt; (para un control aún más minucioso).&lt;/p&gt;

&lt;h3&gt;
  
  
  Los pilares del ADK: Componentes esenciales
&lt;/h3&gt;

&lt;p&gt;Para entender cómo funcionan estos agentes, es útil conocer sus componentes fundamentales. Los &lt;strong&gt;Agentes&lt;/strong&gt; son los ladrillos de la construcción: tenemos el LLMAgent, que es el agente "inteligente" que se apoya en el LLM para tomar decisiones, y los Workflow Agents (Agentes de Flujo de Trabajo), ideales para orquestar tareas paso a paso, de forma predefinida, sin que el LLM tenga que decidir la secuencia. Un buen ejemplo es el LoopAgent, perfecto para repetir pasos. Las &lt;strong&gt;Herramientas (Tools)&lt;/strong&gt; son, por decirlo de algún modo, las "manos" del agente, permitiéndole llevar a cabo acciones como buscar en la web o realizar cálculos. El &lt;strong&gt;Estado y&lt;/strong&gt;  &lt;strong&gt;output_key&lt;/strong&gt; definen cómo los agentes se "comunican" entre sí, transfiriéndose información. El &lt;strong&gt;Runner&lt;/strong&gt; es el "motor" que activa y supervisa todo el proceso del agente, mientras que los &lt;strong&gt;Servicios&lt;/strong&gt; se encargan de gestionar la memoria, la conversación (sesión) y los archivos que el agente pueda generar.&lt;/p&gt;

&lt;p&gt;Es fundamental que los agentes sigan un estándar, como el Protocolo de Contexto de Modelo (MCP) o el Protocolo de Agente a Agente (A2A), para asegurar su coherencia y facilidad de mantenimiento.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¡Manos a la obra! Nuestro primer agente: un ejemplo práctico
&lt;/h3&gt;

&lt;p&gt;Vamos a construir un agente sencillo para ilustrar el proceso. Nuestro objetivo es crear un agente que genere ideas para YouTube Shorts. Este ejemplo se inspira directamente en los &lt;a href="https://github.com/google/adk-docs/tree/main/examples/python/agent-samples/youtube-shorts-assistant" rel="noopener noreferrer"&gt;ADK-samples&lt;/a&gt;. La arquitectura se compone de un &lt;strong&gt;Agente Padre&lt;/strong&gt; (LoopAgent), encargado de asegurar la ejecución de todos los pasos, y de varios sub-agentes: uno para la escritura del guion (que incorpora una herramienta de búsqueda para enriquecer su contenido), otro para la visualización (que describe las imágenes pertinentes), y un tercero para formatear la información, reuniendo todo el material y presentándolo en formato Markdown.&lt;/p&gt;

&lt;p&gt;Para ponerlo en marcha, los primeros pasos son sencillos. Primero, &lt;strong&gt;instala el ADK&lt;/strong&gt; ejecutando pip install google-adk. Luego, &lt;strong&gt;configura tus claves de API&lt;/strong&gt; si vas a trabajar con Gemini, por ejemplo, asegurándote de tenerlas correctamente configuradas. Finalmente, familiarízate con la estructura básica del código en Python y del proyecto en general. Puedes explorar parte del código, como este fragmento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# --- Llm Agent Workflow ---
youtube_shorts_agent = LlmAgent(
    name="youtube_shorts_agent",
    model="gemini-2.0-flash-001",
    instruction=load_instruction_from_file("shorts_agent_instruction.txt"),
    description="You are an agent that can write scripts, visuals and format youtube short videos. You have subagents that can do this",
    sub_agents=[scriptwriter_agent, visualizer_agent, formatter_agent],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para interactuar con tu agente, tienes dos opciones principales. Para realizar pruebas rápidas directamente en la terminal, utiliza adk run youtube-shorts-assistant. Pero si quieres una visión más detallada, adk web es, sin duda, una herramienta esencial. Te permite lanzar una interfaz web para visualizar paso a paso (mediante eventos) el funcionamiento de tu agente y, si fuera necesario, depurarlo. Al ejecutar adk web, verás una respuesta en la terminal indicando la dirección web a la que debes acceder para interactuar con la interfaz.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/44C8u0CDtSo"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  En resumen…
&lt;/h3&gt;

&lt;p&gt;El ADK se perfila como una herramienta potente y maleable para construir agentes de IA utilizando Python. Su diseño te brinda un control significativo y simplifica el proceso de desarrollo. Mi consejo es que te animes a experimentar. Puedes encontrar más ejemplos y recursos valiosos en el &lt;a href="https://github.com/google/adk-samples" rel="noopener noreferrer"&gt;repositorio de ejemplos del ADK&lt;/a&gt;. Para profundizar aún más, no dudes en consultar la &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/agent-development-kit/quickstart?hl=es#%20__init__.py" rel="noopener noreferrer"&gt;documentación oficial&lt;/a&gt; y el &lt;a href="https://github.com/google/adk-samples/tree/main/python" rel="noopener noreferrer"&gt;repositorio principal&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>generativeaitools</category>
      <category>ai</category>
      <category>python</category>
      <category>artificialintelligen</category>
    </item>
    <item>
      <title>gemini-cli: el nuevo aliado para l@s devs</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Sun, 07 Sep 2025 22:46:17 +0000</pubDate>
      <link>https://dev.to/iblancasa/gemini-cli-el-nuevo-aliado-para-ls-devs-2hf4</link>
      <guid>https://dev.to/iblancasa/gemini-cli-el-nuevo-aliado-para-ls-devs-2hf4</guid>
      <description>&lt;p&gt;En un mundo donde la inteligencia artificial se ha colado hasta en la sopa –y bendita sea esa sopa, a veces–, es probable que ya te hayas familiarizado con la versión web de Gemini. Esa interfaz pulcra, intuitiva, donde uno teclea una pregunta y, casi por arte de magia, una respuesta aparece por pantalla. Es una maravilla, no cabe duda, para la creatividad, la búsqueda de información o, simplemente, para sacarnos de algún apuro conceptual. Pero, ¿y si te dijera que esa es solo una faceta de la historia? ¿Y si te dijera que el verdadero potencial de interacción con una IA como Gemini podría residir en un lugar mucho menos glamuroso, pero infinitamente más poderoso para quienes pasamos horas frente a un teclado programando o gestionando sistemas?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F429%2F0%2AVk-FO8o-wP2xwars" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F429%2F0%2AVk-FO8o-wP2xwars"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aquí es donde entra en juego &lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;&lt;strong&gt;gemini-cli&lt;/strong&gt;&lt;/a&gt;, una herramienta que, como su nombre indica, lleva el poder del modelo de Google directamente a tu terminal, a esa ventana negra (o del color que le hayas puesto) donde los comandos son el lenguaje universal. La primera pregunta que surge es obvia: ¿para qué querría uno prescindir de la comodidad de una interfaz gráfica para volver a las líneas de comando? Y la respuesta es tan sencilla como profunda: por la &lt;strong&gt;integración y la eficiencia&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5dym1s223nbwo2xftn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5dym1s223nbwo2xftn4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mientras la versión web es fantástica para consultas puntuales y flujos de trabajo aislados, la terminal es el corazón de la productividad para desarrolladores, ingenieros de sistemas y cualquier persona que trabaje con código o gestione infraestructuras. Gemini CLI no es solo una “conversación” con la IA; es una herramienta que se integra con tu entorno de trabajo, con tus archivos, con tu lógica de proyecto. Imagina poder pedirle a Gemini que genere un fragmento de código y que, acto seguido, ese código se escriba directamente en el archivo que tienes abierto, o que te ayude a refactorizar una función compleja y los cambios se reflejen al instante en tu base de código. Esta es la diferencia fundamental: la capacidad de &lt;strong&gt;operar directamente sobre tu proyecto, manipular archivos, ejecutar comandos y automatizar tareas&lt;/strong&gt; , todo ello sin salir del flujo de trabajo habitual de la terminal.&lt;/p&gt;

&lt;p&gt;No se trata de una mera duplicación de funcionalidades, sino de una extensión lógica. Es el salto de la consulta pasiva a la &lt;strong&gt;interacción activa y contextualizada&lt;/strong&gt;. La IA no solo te &lt;em&gt;dice&lt;/em&gt; cómo hacer algo, sino que te &lt;em&gt;ayuda a hacerlo&lt;/em&gt; en el mismo lugar donde trabajas. Y en un ámbito como el desarrollo de software, donde cada segundo cuenta y la fricción entre herramientas puede ralentizarlo todo, esta integración se convierte en un verdadero catalizador para la productividad. Es llevar la inteligencia artificial de un mero “consejero” a un “colaborador” directo en tu día a día, en ese espacio que ya dominas: la línea de comandos.&lt;/p&gt;

&lt;p&gt;Lo que verdaderamente lo hace atractivo, al menos en un primer contacto, es su accesibilidad. Google ha sido bastante generoso con su nivel gratuito, ofreciendo hasta mil solicitudes diarias, lo que lo convierte en una opción muy tentadora para experimentar sin que el bolsillo se resienta. Además, su naturaleza &lt;em&gt;open-source&lt;/em&gt; nos invita a bucear en sus entrañas, comprender cómo funciona y, quién sabe, quizás incluso a contribuir a su evolución. Imagina poder decirle a tu terminal: “Oye, créame un plan de proyecto para esto”, o “Depura esta función”, y que la IA, con un par de comandos, comience a trazar caminos y a sugerir soluciones. Es un paso más hacia esa promesa de un desarrollo asistido, casi simbiótico, con la máquina.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CqL5kB8pOfo"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Ahora bien, el ecosistema de herramientas de IA en la terminal no es, ni de lejos, un desierto. Aquí es donde la comparación se vuelve no solo necesaria, sino también reveladora.&lt;/p&gt;

&lt;p&gt;Por un lado, tenemos a &lt;strong&gt;OpenAI con su “Codex CLI”&lt;/strong&gt; , una herramienta que emerge como una respuesta directa a la necesidad de llevar los grandes modelos de lenguaje (LLMs) al entorno local. Codex CLI se jacta de ser un agente de codificación ligero, capaz de leer, modificar y ejecutar código en tu máquina. Su énfasis en la seguridad, con la ejecución en entornos aislados y sin acceso a la red por defecto, es un punto a favor que no podemos obviar. Si bien las capacidades son similares en cuanto a la manipulación de archivos y la ejecución de comandos, la filosofía de OpenAI parece centrarse en una interacción aún más agéntica, con la visión de un “ingeniero de software agéntico” que automatice progresivamente tareas complejas de programación. El hecho de que puedas usarlo para refactorizar código, depurar problemas o incluso escribir tests y ejecutarlos, suena a música celestial para cualquier desarrollador.&lt;/p&gt;

&lt;p&gt;Y por el otro, Anthropic nos trae sus propuestas con &lt;strong&gt;“Claude Code” y “Claude Engineer”&lt;/strong&gt;. Si bien Claude es conocido por su enfoque en la seguridad y la precisión, sus herramientas de interfaz de línea de comandos no se quedan atrás. “Claude Code” busca integrarse directamente en tu entorno de desarrollo, ofreciendo una serie de herramientas para operaciones de archivo, búsqueda de código y navegación web, todo ello sin la necesidad de servidores adicionales. Por su parte, “Claude Engineer” se presenta como un asistente de IA auto-mejorable, diseñado para crear y gestionar herramientas de IA con Claude 3.5. La promesa aquí es la capacidad de Claude para generar y gestionar sus propias herramientas, expandiendo continuamente sus capacidades a través de la conversación. Es una aproximación más modular, donde la IA no solo te asiste, sino que también construye sus propias extensiones para adaptarse mejor a tus necesidades.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoo9elz0m4u7ewohgmcx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoo9elz0m4u7ewohgmcx.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entonces, ¿cuál elegir?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La verdad es que cada herramienta tiene su matiz, su punto fuerte. Gemini CLI brilla por su integración con el ecosistema de Google y su modelo Gemini, además de una política de uso gratuito bastante generosa. Su capacidad para manejar grandes bases de código y la flexibilidad de las instrucciones personalizadas a través de gemini.md son características a tener en cuenta.&lt;/p&gt;

&lt;p&gt;Codex CLI de OpenAI, por su parte, se posiciona como un asistente robusto y seguro, con un enfoque más centrado en la automatización y la interacción directa con el repositorio. La posibilidad de que la IA no solo sugiera cambios, sino que los aplique automáticamente (si así lo configuras), es una muestra de la dirección hacia la que se dirige el desarrollo asistido por IA.&lt;/p&gt;

&lt;p&gt;Y las herramientas de Claude, con su énfasis en la creación y gestión de herramientas por parte de la propia IA, abren una puerta a una personalización y una evolución constante que podría ser revolucionaria para aquellos que buscan una IA que no solo resuelva problemas, sino que también se adapte y crezca con ellos.&lt;/p&gt;

&lt;p&gt;Y tú… ¿usas ya alguno?&lt;/p&gt;




</description>
      <category>generativeaitools</category>
      <category>artificialintelligen</category>
      <category>generativeaiusecases</category>
      <category>ai</category>
    </item>
    <item>
      <title>Recursos si estás empezando (o llevas poco)</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Fri, 08 Nov 2024 10:50:48 +0000</pubDate>
      <link>https://dev.to/iblancasa/recursos-si-estas-empezando-o-llevas-poco-pca</link>
      <guid>https://dev.to/iblancasa/recursos-si-estas-empezando-o-llevas-poco-pca</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03e89vfwlhzs9eyhs1dk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03e89vfwlhzs9eyhs1dk.png" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si estás comenzando en el mundo de la programación, probablemente te hayas dado cuenta de que hay una gran cantidad de recursos disponibles. Tantos, que saber por dónde empezar puede ser un desafío. En este post, quiero ayudarte a encontrar algunos de los mejores recursos gratuitos o de bajo costo para iniciar tu camino en el desarrollo de software.&lt;/p&gt;

&lt;p&gt;Antes de enlazarte ningún recurso, me gustaría darte algunos consejos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Entiende a dónde quieres llegar&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Define qué quieres lograr con la programación. ¿Te interesa el desarrollo web, aplicaciones móviles, ciencia de datos o inteligencia artificial? Tener un objetivo te ayudará a enfocar tus esfuerzos y elegir los recursos adecuados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Aprende los fundamentos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Antes de sumergirte en tecnologías avanzadas, asegúrate de comprender los conceptos básicos como variables, bucles, funciones y estructuras de datos. Una base sólida facilita el aprendizaje de lenguajes y herramientas más complejas. Además, te facilitará el salto de una tecnología a otra en caso de ser necesario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Elige un lenguaje y profundiza&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Es tentador intentar aprender varios lenguajes a la vez, pero es más efectivo dominar uno antes de pasar a otro. &lt;a href="https://www.python.org/doc/" rel="noopener noreferrer"&gt;Python&lt;/a&gt; y &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" rel="noopener noreferrer"&gt;JavaScript&lt;/a&gt; son excelentes opciones para principiantes debido a su amplia aplicación y comunidad de apoyo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Practica regularmente&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La programación es una habilidad que mejora con la práctica constante. Dedica tiempo diario o semanal para escribir código y resolver problemas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Lee y analiza código de otros&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Examinar el código escrito por programador@s experimentad@s puede brindarte nuevas perspectivas y técnicas que podrías no haber considerado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Resuelve problemas reales&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aplica tus conocimientos creando proyectos que te interesen o resuelvan problemas cotidianos. Esto no solo refuerza lo que has aprendido sino que también construye tu portafolio. Existen algunas páginas como &lt;a href="https://exercism.org/" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; o &lt;a href="https://www.codewars.com/" rel="noopener noreferrer"&gt;Codewars&lt;/a&gt; que te permiten practicar lenguajes de programación mediante retos. Esta no es forma favorita de aprender a programar… no estarás solucionando problemas como los que te puedes encontrar una vez estés trabajando y no estarás “engordando” tu portfolio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Utiliza Control de Versiones&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Familiarízate con herramientas como &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/a&gt; y plataformas como &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt; o &lt;a href="https://about.gitlab.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;GitLab&lt;/strong&gt;&lt;/a&gt;. El control de versiones es esencial en el desarrollo profesional y te ayudará a colaborar con otros.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. No temas pedir ayuda&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si te atascas, pide ayuda en foros, comunidades en línea o grupos de estudio. La comunidad de programación es generalmente muy abierta y dispuesta a ayudar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Mantente actualizad@&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El mundo de la tecnología evoluciona rápidamente. Sigue blogs, podcasts y canales de YouTube relacionados con programación para estar al día con las últimas tendencias y prácticas. Únete a grupos como GDG y ve a conferencias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. Desarrolla habilidades “blandas”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La comunicación, el trabajo en equipo y la resolución de problemas son habilidades igualmente importantes. Participa en grupos de estudio o proyectos colaborativos para desarrollarlas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. Cuida tu salud mental y física&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Programar puede ser desafiante. Estresante y frustrante, incluso. Tómate descansos, mantén una postura adecuada y no olvides equilibrar tu tiempo frente al ordenador con otras actividades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12. Explora Diferentes Áreas de la Programación&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Una vez que te sientas cómod@, experimenta con diferentes campos como el desarrollo de juegos, la inteligencia artificial o la ciberseguridad para encontrar tu verdadera pasión. No hace falta que seas un@ expert@ en el campo para empezar a “oler” lo que hay en otras áreas.&lt;/p&gt;

&lt;p&gt;Y, ahora sí, algunos recursos.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.freecodecamp.org/" rel="noopener noreferrer"&gt;freeCodeCamp&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F759%2F0%2AJhF5fqK3JZKugesJ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F759%2F0%2AJhF5fqK3JZKugesJ" width="759" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;freeCodeCamp es una organización sin fines de lucro dedicada a hacer que el aprendizaje de la programación sea accesible para todos. Ofrece una plataforma en línea gratuita que incluye un plan de estudios interactivo, una comunidad activa y recursos educativos diversos.&lt;/p&gt;

&lt;p&gt;El plan de estudios de freeCodeCamp abarca más de 3,000 horas de contenido, cubriendo áreas como desarrollo web, análisis de datos y aprendizaje automático. Los estudiantes pueden obtener certificaciones gratuitas en temas como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsive Web Design&lt;/li&gt;
&lt;li&gt;Algoritmos y estructuras de datos en JavaScript&lt;/li&gt;
&lt;li&gt;Bibliotecas de desarrollo front-end&lt;/li&gt;
&lt;li&gt;Visualización de datos&lt;/li&gt;
&lt;li&gt;Desarrollo Back-End y APIs&lt;/li&gt;
&lt;li&gt;Computación científica con Python&lt;/li&gt;
&lt;li&gt;Análisis de datos con Python&lt;/li&gt;
&lt;li&gt;Seguridad de la Información&lt;/li&gt;
&lt;li&gt;Machine Learning con Python&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/c/DotTechES" rel="noopener noreferrer"&gt;DotTech-ES&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AqisZ7TsLvybUPrUX" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AqisZ7TsLvybUPrUX" width="1024" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DotTech-ES es un canal de YouTube dedicado a la tecnología y la programación. Ofrece contenido educativo sobre patrones de diseño, código limpio, JavaScript, Angular y otros temas relacionados con el desarrollo de software. El canal cuenta con una lista de reproducción llamada “Lo mejor de DotTech” que recopila sus vídeos más destacados.&lt;/p&gt;

&lt;p&gt;Este canal es para gente que ya lleva programando un tiempo y quiere ir un pasito más allá. Para quienes buscan recursos en español sobre programación y desarrollo de software, DotTech-ES es una opción valiosa que combina teoría y práctica en sus contenidos.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.pythonweekly.com/" rel="noopener noreferrer"&gt;Python Weekly&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F883%2F0%2AMUN1orPAFJg0BXAi" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F883%2F0%2AMUN1orPAFJg0BXAi" width="883" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python Weekly es un boletín electrónico semanal que se enfoca en recopilar y compartir las últimas noticias, artículos, tutoriales, proyectos y eventos relacionados con el lenguaje de programación Python. Es una herramienta invaluable para desarrolladores de todos los niveles que desean mantenerse al día con las tendencias y avances en la comunidad de Python.&lt;/p&gt;

&lt;p&gt;Incorporar Python Weekly a tu rutina semanal es una excelente manera de complementar tu aprendizaje y mantenerte conectado con la vibrante comunidad de Python. Ya seas principiante o un experimentad@, este recurso te ofrecerá información valiosa para continuar creciendo en tu camino como programador.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.atlassian.com/es/git" rel="noopener noreferrer"&gt;Guía sobre Git de Atlassian&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F883%2F0%2A_w8ceEEjkleaR3IL" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F883%2F0%2A_w8ceEEjkleaR3IL" width="883" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¡Explora esta guía y lleva tus habilidades de programación al siguiente nivel! Aprender a utilizar Git de manera eficiente es esencial para colaborar en proyectos y mantener un flujo de trabajo organizado. La guía de Atlassian te acompaña paso a paso en este proceso de aprendizaje.&lt;/p&gt;

&lt;p&gt;Y tú… ¿qué otros recursos utilizas?&lt;/p&gt;




</description>
      <category>recursos</category>
      <category>software</category>
      <category>development</category>
      <category>git</category>
    </item>
    <item>
      <title>Talking about performance, profiling, testing and other stuff</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Tue, 18 Apr 2023 08:40:00 +0000</pubDate>
      <link>https://dev.to/iblancasa/talking-about-performance-profiling-testing-and-other-stuff-2l27</link>
      <guid>https://dev.to/iblancasa/talking-about-performance-profiling-testing-and-other-stuff-2l27</guid>
      <description>&lt;p&gt;&lt;strong&gt;Performance testing&lt;/strong&gt; is a type of software testing that measures how well an application performs under certain conditions. It is the process of determining the speed, responsiveness, stability, and scalability of a software application under a particular workload.&lt;/p&gt;

&lt;p&gt;It is significant for a number of reasons. First off, it aids in locating performance bottlenecks and other problems that might affect an application's performance. Second, it helps to guarantee that an application is scalable and can handle the anticipated traffic. Last but not least, it assists in ensuring that an application satisfies the performance standards established by the stakeholders.&lt;/p&gt;

&lt;p&gt;It is typically done during the testing phase of the software development life cycle (SDLC), after the functional testing has been completed. It can also be done before the application is released to production to ensure that it meets the performance requirements.&lt;/p&gt;

&lt;p&gt;Some of the variables that can be measured in performance testing include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Response Time - the time it takes for the application to respond to a user request.&lt;/li&gt;
&lt;li&gt;Throughput - the number of transactions that can be processed by the application in a given time period.&lt;/li&gt;
&lt;li&gt;Concurrency - the number of users that can access the application at the same time without impacting performance.&lt;/li&gt;
&lt;li&gt;CPU usage - the amount of CPU resources consumed by the application.&lt;/li&gt;
&lt;li&gt;Memory usage - the amount of memory resources consumed by the application.&lt;/li&gt;
&lt;li&gt;Network latency - the time it takes for data to travel between the client and server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Is it the same than load testing?
&lt;/h2&gt;

&lt;p&gt;Some people are not able to find differences between performance testing and load testing. They are related (somehow).&lt;/p&gt;

&lt;p&gt;Load testing is a type of software testing that measures how well an application can handle a specific load or level of demand. The goal of load testing is to determine the maximum capacity of an application and to identify any bottlenecks or issues that may impact its performance under high load. Load testing typically involves simulating a large number of users or transactions to see how the application responds. The focus is on measuring the response time, throughput, and resource utilization of the application under load.&lt;/p&gt;

&lt;p&gt;Performance testing, on the other hand, is a broader term that encompasses several types of testing. It can include load testing, stress testing, endurance testing, and other types of testing. The goal is to identify performance issues and bottlenecks that may impact the application's performance under different conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Write Performance Tests in Golang
&lt;/h2&gt;

&lt;p&gt;Why Write Performance Tests in Golang? Golang is a programming language that is well-suited for building high-performance applications. However, even the best-written code can suffer from performance issues when it is deployed in the real world. Performance testing helps identify these issues before they become major problems.&lt;/p&gt;

&lt;p&gt;In Golang, you can write performance tests using the built-in testing package. The package provides the Bench function, which allows you to write benchmark tests for your code.&lt;/p&gt;

&lt;p&gt;Here's an example of a performance test for a function that sorts an array of integers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create a random array of integers&lt;/span&gt;
    &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// Reset the timer&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Run the sort function b.N times&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a random array of integers and then reset the timer before running the &lt;code&gt;sort.Ints&lt;/code&gt; function &lt;code&gt;b.N&lt;/code&gt; times. The &lt;code&gt;b.N&lt;/code&gt; value is an integer that represents the number of times the &lt;code&gt;sort.Ints&lt;/code&gt; function should be run.&lt;/p&gt;

&lt;p&gt;Then, you can use the &lt;code&gt;go test&lt;/code&gt; command. To run the BenchmarkSort test from the previous example, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-bench&lt;/code&gt; flag specifies the pattern to match against benchmark test names. In this case, the . matches all benchmark tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I implement performance tests?
&lt;/h2&gt;

&lt;p&gt;As always: it depends. If the value of your application is to be a high performance communication system, it would make sense to integrate performance tests. If your application is a TODO-list, maybe is not as important. &lt;strong&gt;You need to implement the tests that bring more value to you&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Also, you have to take into account that, if your application depends on third-party services or in other web services, it can be difficult to detect bottlenecks during your performance testing. Also, some performance issues will appear only in your production environment. Why? Because they will take place only in those scenarios where the load is high and the users behavior is real and, maybe, less predictable. This is the usual scenario for cloud based applications.&lt;/p&gt;

&lt;p&gt;Performance testing can be interesting for certain parts of your code but you can be interested in &lt;strong&gt;continuous profiling&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous profiling
&lt;/h3&gt;

&lt;p&gt;Profiling involves analyzing an application's behavior, such as its CPU and memory usage, to identify performance bottlenecks and areas for optimization. It is typically done by running the application with a profiling tool that collects data about its performance, which can then be analyzed to identify areas for improvement. Performance testing, on the other hand, involves testing an application's performance under specific conditions. But those conditions could not reproduce the workflows from your users (you're not testing a real behavior or under the correct load).&lt;/p&gt;

&lt;p&gt;Continuous profiling is a technique used in software development to analyze and monitor the performance of an application in real-time. It involves the collection of data about the application's performance, such as CPU usage, memory usage, and other metrics, continuously and automatically.&lt;/p&gt;

&lt;p&gt;In contrast to traditional profiling, which is typically performed manually and only for short periods of time, continuous profiling is designed to provide ongoing insights into an application's performance. By monitoring the application's behavior over time, continuous profiling can identify trends and patterns that may indicate performance issues or opportunities for optimization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous profiling&lt;/strong&gt; is often used in conjunction with other techniques, such as continuous integration and continuous delivery, to ensure that an application is performing optimally throughout the development process. It can also be used in production environments to monitor the performance of an application in real-time and identify issues before they become critical.&lt;/p&gt;

&lt;p&gt;Overall, continuous profiling is a valuable tool for software developers and operations teams, as it allows them to identify and address performance issues quickly and efficiently, leading to faster and more reliable software delivery.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cncf.io/blog/2022/05/31/what-is-continuous-profiling/" rel="noopener noreferrer"&gt;You can learn more about continuous profiling in the CNCF website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>performance</category>
      <category>testing</category>
      <category>profiling</category>
      <category>go</category>
    </item>
    <item>
      <title>Golang. Yes or not?</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Mon, 10 Apr 2023 11:51:00 +0000</pubDate>
      <link>https://dev.to/iblancasa/golang-yes-or-not-3jmh</link>
      <guid>https://dev.to/iblancasa/golang-yes-or-not-3jmh</guid>
      <description>&lt;p&gt;I have been working with Golang for some years and some people ask me if Golang is a good language. The answer is always the same: "it depends on what you want to build". This post is not another one about why you should stop working with Python or Java and start with Golang. It is about when I consider Golang can (not must) be used and where can make you more productive.&lt;/p&gt;

&lt;p&gt;I can attest to the many advantages of using Golang, also known as Go, as a programming language. Developed by Google in 2007, Golang has become increasingly popular among developers due to its simplicity, concurrency support, and performance capabilities. In this article, I will explain why you should consider using Golang for your next project and compare it to other popular languages like Python and Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of Golang
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Simple and easy to learn
&lt;/h3&gt;

&lt;p&gt;Golang is known for its simplicity and ease of use. Its syntax is straightforward, and its standard library is well-documented, making it easy for developers to learn and start coding. Moreover, Golang has a smaller codebase compared to other languages, making it easier to maintain and debug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency support
&lt;/h3&gt;

&lt;p&gt;Golang is designed to handle concurrent programming. Its built-in goroutines, lightweight threads, and channels make it easy to write concurrent programs, improving the scalability and efficiency of your code. This is especially important for web applications that require handling multiple requests simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-performance capabilities
&lt;/h3&gt;

&lt;p&gt;Golang is known for its high-performance capabilities. Its compiled nature allows it to run faster than interpreted languages like Python. Additionally, Golang has efficient garbage collection, making it suitable for memory-intensive applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Great for building network applications
&lt;/h3&gt;

&lt;p&gt;Golang has excellent support for building network applications. Its standard library includes packages for working with HTTP, TCP, and UDP protocols, making it easy to develop web servers, APIs, and networking tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use Golang?
&lt;/h2&gt;

&lt;p&gt;Golang is a suitable choice for building a wide range of applications. Here are some situations where you should consider using Golang:&lt;/p&gt;

&lt;h3&gt;
  
  
  Developing microservices
&lt;/h3&gt;

&lt;p&gt;Golang is an excellent choice for developing microservices, which are small, independently deployable services that work together to form a larger application. Its concurrency support and high-performance capabilities make it ideal for building scalable microservices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building network applications
&lt;/h3&gt;

&lt;p&gt;Golang’s built-in support for networking protocols makes it a great choice for building network applications like web servers, APIs, and networking tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developing command-line tools
&lt;/h3&gt;

&lt;p&gt;Golang’s simple syntax and ease of use make it a great choice for developing command-line tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Golang vs. Python vs. Rust
&lt;/h2&gt;

&lt;p&gt;Golang is often compared to other popular programming languages like Python and Rust. Here are some key differences between the three languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax&lt;/strong&gt;: Golang’s syntax is simpler and easier to learn than Python and Rust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Golang is faster than Python but slower than Rust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency support&lt;/strong&gt;: Golang has better concurrency support than Python but worse than Rust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory safety&lt;/strong&gt;: Rust offers memory safety features that are not available in Golang or Python.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When not use Golang?
&lt;/h2&gt;

&lt;p&gt;While Golang is a powerful language for many applications, there are certain scenarios where it may not be the best choice. Here are some cases where Golang may not be the optimal language to use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GUI Applications&lt;/strong&gt;: Golang does not have strong support for building Graphical User Interface (GUI) applications. Although there are some libraries available for building GUIs, they are not as mature or well-supported as other languages like Java, C++, or Python. If you are building a GUI application, you may want to consider a language like Python or Java.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complex Mathematical Calculations&lt;/strong&gt;: Golang does not have built-in support for complex mathematical calculations. Although you can use external libraries for complex mathematical operations, Golang may not be the best choice for scientific computing or numerical analysis. If your application requires complex mathematical calculations, you may want to consider a language like Python or MATLAB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interoperability with Legacy Systems&lt;/strong&gt;: Golang does not have strong support for interoperability with legacy systems. If you need to integrate your application with legacy systems written in languages like COBOL or FORTRAN, you may want to consider a language like C or C++.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Machine Learning&lt;/strong&gt;: Although Golang has some libraries for machine learning, they are not as robust or widely used as Python's machine learning libraries. If your application requires extensive machine learning capabilities, you may want to consider using Python.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High-Level Abstractions&lt;/strong&gt;: Golang is a low-level language and does not have the high-level abstractions that other languages like Python or Ruby provide. If your application requires a lot of high-level abstractions, you may want to consider a language like Python or Ruby. For this reason, a lot of people says it is not good for business logic. Things like &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;reduce&lt;/code&gt; are not part of the standard library.&lt;/p&gt;

&lt;h3&gt;
  
  
  About writing business logic with Golang
&lt;/h3&gt;

&lt;p&gt;Golang is not the preferred language for writing business logic. Why? A lot of companies prefer to use Java for this kind of usage. These are some of the reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ecosystem Maturity: Java has been around for more than two decades and has a mature ecosystem that includes many libraries and frameworks for building business logic applications. On the other hand, Golang is a relatively new language, and although its ecosystem is growing, it is not as mature as Java’s.&lt;/li&gt;
&lt;li&gt;Strong Type System: Java’s strong type system helps developers catch errors at compile time, making it easier to build complex business logic applications. Golang has a weaker type system, which means that some errors may only be caught at runtime, making it more difficult to build complex business logic applications.&lt;/li&gt;
&lt;li&gt;Garbage Collection: Java has a robust garbage collection system that helps manage memory, which is essential for business logic applications that require a lot of memory. While Golang also has a garbage collection system, it is less efficient than Java’s. And we know efficiency affect to costs.&lt;/li&gt;
&lt;li&gt;Debugging and Profiling Tools: Java has a range of debugging and profiling tools, such as VisualVM and JProfiler, that make it easier to debug and optimize business logic applications. Golang also has some debugging and profiling tools, but they are not as mature as Java’s.&lt;/li&gt;
&lt;li&gt;Enterprise Support: Java has strong enterprise support from vendors like Oracle, making it a popular choice for building business logic applications. Golang is still a relatively new language, and while it is gaining popularity, it may not have the same level of enterprise support as Java.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In conclusion, Golang is an excellent choice for building scalable, high-performance applications, especially for network and microservices development. Its simplicity, concurrency support, and performance capabilities make it a top contender for many software engineering projects. However, the choice of programming language ultimately depends on the specific requirements of your project, and you should evaluate each language based on your needs before making a decision.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>language</category>
      <category>applications</category>
    </item>
    <item>
      <title>Use scratch images. Is it a good idea?</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Fri, 24 Mar 2023 16:51:28 +0000</pubDate>
      <link>https://dev.to/iblancasa/use-scratch-images-is-it-a-good-idea-32lp</link>
      <guid>https://dev.to/iblancasa/use-scratch-images-is-it-a-good-idea-32lp</guid>
      <description>&lt;p&gt;When you create the container image for your application, you need to set a base container image (indicated in the FROM statement from Dockerfiles/Containerfiles). Usually, we set Linux distributions as base images like Debian, CentOS, or Ubuntu. Later, we install all the libraries we need to build and/or run our application and generate the final container image. If we’re working with Java, we’ll install Gradle or use an image with Gradle installed. If we’re using Python, we’ll install the Python runtime or use an image with Python installed by default.&lt;/p&gt;

&lt;p&gt;One of the recommendations given as a good practice is to create minimal container images. What is a minimal container image? A container image with only your application, the configurations (XML files, environment variables), and the dependencies. Following this approach, we reduce the size of our container images. Why is this interesting? The images will be cheaper to store and to pull/push from/to container registries.&lt;/p&gt;

&lt;p&gt;Depending on the technologies your application relies on, you will depend more or less on the base image. For example, if you develop in NodeJS or Python, you only need a base image with the runtime installed: you don’t care about the base OS. If you develop in C, you probably need to care about it because you may need to depend on a specific LIBC implementation (GLIBC or MUSL, for instance). So, to productize your application, you should choose a base container image that meets your requirements but minimal footprint. For instance, if we need  to use a NodeJS Carbon container image as a base for ours, carbon-alpine is the best choice.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repository&lt;/th&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Image ID&lt;/th&gt;
&lt;th&gt;Size (MB)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon-alpine&lt;/td&gt;
&lt;td&gt;b9e61ad789af&lt;/td&gt;
&lt;td&gt;67,4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon-slim&lt;/td&gt;
&lt;td&gt;6fded0f27b5f&lt;/td&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon-buster-slim&lt;/td&gt;
&lt;td&gt;06ad6f44bf28&lt;/td&gt;
&lt;td&gt;148&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon-jessie-slim&lt;/td&gt;
&lt;td&gt;ad0fdfc38d06&lt;/td&gt;
&lt;td&gt;183&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon-jessie&lt;/td&gt;
&lt;td&gt;e866fe9eab07&lt;/td&gt;
&lt;td&gt;675&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon-buster&lt;/td&gt;
&lt;td&gt;39eb5db21f68&lt;/td&gt;
&lt;td&gt;862&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;node&lt;/td&gt;
&lt;td&gt;carbon&lt;/td&gt;
&lt;td&gt;7a9afc16a57f&lt;/td&gt;
&lt;td&gt;894&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;But, if we’re using something as Golang, were you can &lt;a href="https://mt165.co.uk/blog/static-link-go/" rel="noopener noreferrer"&gt;do static link of everything into your application&lt;/a&gt;, you can reduce the size even more. Why? Because you don’t need a runtime and you can, even, not need a base operating system. For that reason, is pretty common to see Dockerfiles from Golang applications as simple as (supposing the application was built locally or &lt;a href="https://docs.docker.com/build/building/multi-stage/" rel="noopener noreferrer"&gt;you can use multi-stage container builds&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; scratch&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; myapp .&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; [“./myapp”]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Is using scratch images a good idea?
&lt;/h2&gt;

&lt;p&gt;Using scratch images as the base for containers can be a good idea because they provide a minimal and clean starting point for building images. The scratch image is completely empty and does not include any pre-installed packages or libraries, which means that you have complete control over the dependencies and software that are included in the image. It is the 0 image. The “Object” container image. The minimal container image. The nothing.&lt;/p&gt;

&lt;p&gt;Using scratch images as the base for our containers can be beneficial in situations where you need to build a small, lightweight image that only includes the exact packages and libraries that are necessary for your application. Following this approach can help you to ensure that your images are more secure since there are no pre-installed packages or libraries that could be vulnerable to security exploits.&lt;/p&gt;

&lt;p&gt;Some developers prefer not to use scratch images as a base for their container images. They can be “safer” because they don’t have applications the hackers can take advantage of to break into your system but they do not provide any security or patching mechanisms. This is usually a concern for developers. Instead, many developers prefer to use base images that include a minimal set of commonly-used packages and libraries, which can save time and reduce the risk of errors, even when the base images are not totally minimal. A good approach for this can be to use the &lt;a href="https://github.com/GoogleContainerTools/distroless" rel="noopener noreferrer"&gt;distroless container base images&lt;/a&gt;, where you have base images but not with a lot of components.&lt;/p&gt;

&lt;p&gt;And you? What do you prefer to use?&lt;/p&gt;

</description>
      <category>container</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Kubernetes: why yes and why not</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Thu, 02 Feb 2023 10:20:25 +0000</pubDate>
      <link>https://dev.to/iblancasa/kubernetes-why-yes-and-why-not-54no</link>
      <guid>https://dev.to/iblancasa/kubernetes-why-yes-and-why-not-54no</guid>
      <description>&lt;p&gt;For sure you have heard about Kubernetes. Kubernetes is an open-source container orchestration system that has taken the world of containerization by storm. This powerful platform has become a go-to choice for organizations of all sizes looking to manage and deploy containerized applications at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why yes
&lt;/h2&gt;

&lt;p&gt;One of the main reasons why Kubernetes is so amazing is its ability to automate the deployment, scaling, and management of containerized applications. This means that organizations can focus on developing and deploying new features and functionality, rather than worrying about the underlying infrastructure.&lt;/p&gt;

&lt;p&gt;In addition to its automation capabilities, Kubernetes also offers a high degree of flexibility. The platform can be easily customized to meet the unique needs of different organizations, and it can be deployed on a wide range of infrastructure, including on-premises, in the cloud, or in a hybrid environment.&lt;/p&gt;

&lt;p&gt;Another key advantage of Kubernetes is its ability to handle high availability and disaster recovery. The platform supports automatic failover and self-healing, which helps to ensure that applications remain up and running even in the event of a failure. This helps to minimize downtime and ensure that users always have access to the services they need.&lt;/p&gt;

&lt;p&gt;Finally, Kubernetes is an open-source project, which means that it is constantly being improved and updated by a large and active community of developers. This ensures that the platform remains cutting-edge and up-to-date with the latest technologies and trends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not
&lt;/h2&gt;

&lt;p&gt;Despite all the advantages, it's not always the perfect solution for every organization. In this blog post, we'll explore some of the reasons why Kubernetes can be a horrible fit for certain organizations.&lt;/p&gt;

&lt;p&gt;One of the main issues with Kubernetes is its steep learning curve. The platform is highly complex and can be difficult to set up, configure, and manage. This can be a significant barrier for organizations that do not have a dedicated team of experts with the necessary skills and experience to work with Kubernetes.&lt;/p&gt;

&lt;p&gt;Another issue with Kubernetes is its high resource requirements. The platform requires a lot of memory, CPU, and storage to run, which can be a significant burden for organizations that have limited resources. Furthermore, Kubernetes requires a lot of management and maintenance which can be a real headache for organizations that are struggling to keep up with the day-to-day operations.&lt;/p&gt;

&lt;p&gt;Another downside of Kubernetes is its scalability limitations. While the platform is designed to handle large numbers of containerized applications, it can struggle to meet the needs of organizations that are dealing with massive traffic or large-scale deployments. This can lead to increased downtime, slow performance, and other issues that can negatively impact the user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What alternatives do I have to run my own Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Depending on your application needs, it could be OK to &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_atomic_host/7/html/managing_containers/running_containers_as_systemd_services_with_podman" rel="noopener noreferrer"&gt;use systemd to run your containers&lt;/a&gt; or deploy a virtual machine as host. Other alternatives are using a Platform as a Service or a Backend as a Service (like &lt;a href="https://firebase.google.com/?hl=es" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you still feel you need Kubernetes but you cannot manage to create your own Kubernetes cluster, there are some alternatives like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Managed Kubernetes Services: Many cloud providers such as Amazon Web Services (AWS), Google Cloud Platform (GCP), and Microsoft Azure offer managed Kubernetes services. These services handle the deployment, scaling, and management of Kubernetes clusters, leaving you to focus on developing and deploying your applications.&lt;/li&gt;
&lt;li&gt;Kubernetes-as-a-Service: This is a fully managed Kubernetes service offered by a third-party provider. It allows you to easily create and manage Kubernetes clusters on a variety of cloud providers, without having to worry about the underlying infrastructure.
3.Serverless Containers: Serverless container platforms such as AWS Fargate, Azure Container Instances, and Google Cloud Run allow you to run your containerized applications without having to worry about managing the underlying infrastructure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, while Kubernetes is a powerful platform that has a lot to offer, it's not always the best fit for every organization. The platform is highly complex, requires a lot of resources and maintenance, and has scalability limitations. Organizations that are struggling to meet these requirements may be better off looking for alternative solutions that are better suited to their specific needs.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>openshift</category>
      <category>containers</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Development principles you should know</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Sat, 28 Jan 2023 16:03:45 +0000</pubDate>
      <link>https://dev.to/iblancasa/development-principles-you-should-know-n1f</link>
      <guid>https://dev.to/iblancasa/development-principles-you-should-know-n1f</guid>
      <description>&lt;p&gt;In our industry, principles are rules and recommendations to follow during software development to make it easy to maintain and evolve. Developers can apply these principles at various stages of the software development process, from planning and design to implementation and testing. These principles can look not so valuable when somebody is at the beginning of their career. On the other hand, they make sense when you start working on more professional applications.&lt;/p&gt;

&lt;p&gt;During this post, I'll try to give you a quick view of some well-known software principles you should know!&lt;/p&gt;

&lt;h2&gt;
  
  
  You Ain't Gonna Need It
&lt;/h2&gt;

&lt;p&gt;YAGNI is a principle that advises developers not to add unnecessary features or code to a software system. The idea is to keep the system as simple as possible. Adding new features happens later only if they are needed. So: rather than trying to anticipate future needs and adding them in advance, we only spend resources on creating something to satisfy our requirements.&lt;/p&gt;

&lt;p&gt;Why is YAGNI important? Keep the product as much simple as possible, not adding stuff that will not bring value to the final customer, is a good practice: you don't waste resources and ensure your technical debt will not increase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Repeat Yourself
&lt;/h2&gt;

&lt;p&gt;DRY is a principle that advises developers to avoid writing redundant code. The idea is to ensure that there is only one source of truth for any given piece of information within a system. This makes it easier to maintain the system, as you only have to update a single piece of code rather than searching for and updating multiple copies of the same code. You can reuse logic you wrote before: write once, use thousands of times.&lt;/p&gt;

&lt;p&gt;Why is DRY important? Because you don't need to solve the same problem multiple times. If, for instance, you wrote a method to calculate the price of something... why do you need to write the same again in another place of your code? Also: if you fix a bug in one of the methods, you might forget about propagating the change to the other implementations of the same agorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep It Simple, Stupid
&lt;/h2&gt;

&lt;p&gt;KISS is a principle that advises developers to keep their code and design as simple as possible. The idea is that simple systems are easier to understand, maintain, and modify than complex ones.&lt;br&gt;
It is a similar principle than Ockham's razor. Ockham's razor is a principle of parsimony which states that, when presented with multiple explanations for a phenomenon, one should select the explanation that makes the fewest number of assumptions. So: if you have multiple posibilities to implement something... what is the correct? The simplest.&lt;/p&gt;

&lt;p&gt;Why is KISS important? Remember you will not be working alone when developing software. Keeping stuff simple, will help new contributors to understand your methods/architectures/systems easier... Find (and fix) bugs will be a piece of cake!&lt;/p&gt;

&lt;h2&gt;
  
  
  Law of Demeter
&lt;/h2&gt;

&lt;p&gt;LOD is a principle that advises developers to reduce the number of dependencies between objects in a system. The idea is to minimize the amount of knowledge that an object has about other objects, as this can make the system more modular and easier to maintain.&lt;/p&gt;

&lt;p&gt;Why is LOD important? It will help the KISS and DRY pinciples. Also... it will help you for testing purposes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Separation of Concerns
&lt;/h2&gt;

&lt;p&gt;SOC is a principle that advises developers to divide a software system into distinct parts, each of which addresses a separate concern. The idea is to make it easier to understand and modify the system, as each part can be developed and tested independently of the others.&lt;/p&gt;

&lt;p&gt;Why is SOC important? Imagine, for instance, you integrated an application with a database. After some time, for cost reasons, you need to switch to another system. If the application is really coupled to the database (you have calls to the  database API across all your code), the costs of using a new database will raise. But, if your code calls an intermediate piece of code thata acts as an interface for the database, you only need to change the implementation of its methods!&lt;/p&gt;

&lt;h2&gt;
  
  
  SOLID
&lt;/h2&gt;

&lt;p&gt;SOLID is an acronym for five design principles for writing maintainable and scalable software. They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Single Responsibility Principle&lt;/em&gt;: A class should have one and only one reason to change.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Open-Closed Principle&lt;/em&gt;: A class should be open for extension but closed for modification.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Liskov Substitution Principle&lt;/em&gt;: Subtypes should be able to substitute for their base types.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Interface Segregation Principle&lt;/em&gt;: A class should not be forced to implement interfaces it doesn't use.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Dependency Inversion Principle&lt;/em&gt;: High-level modules should not depend on low-level modules, but both should depend on abstractions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why are SOLID principles important? They mainly resume the others!&lt;/p&gt;

&lt;p&gt;These are just a few examples of software development principles that can help developers create high-quality, maintainable software. By following these principles, developers can help ensure that their systems are flexible, scalable, and easy to modify over time. Which others do you know?&lt;/p&gt;

</description>
      <category>development</category>
      <category>principles</category>
      <category>craftsmanship</category>
    </item>
    <item>
      <title>Access the Jaeger REST API programatically in OpenShift</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Thu, 05 May 2022 14:22:59 +0000</pubDate>
      <link>https://dev.to/iblancasa/access-the-jaeger-rest-api-programatically-in-openshift-ebk</link>
      <guid>https://dev.to/iblancasa/access-the-jaeger-rest-api-programatically-in-openshift-ebk</guid>
      <description>&lt;p&gt;Have you ever tried to access &lt;a href="https://www.jaegertracing.io/" rel="noopener noreferrer"&gt;Jaeger&lt;/a&gt; programmatically in &lt;a href="https://www.redhat.com/technologies/cloud-computing/openshift" rel="noopener noreferrer"&gt;OpenShift&lt;/a&gt;? It can be a little bit difficult. Sometimes, it is needed because you want, for instance, access to the REST API &lt;a href="https://www.jaegertracing.io/docs/1.33/apis/#http-json-internal" rel="noopener noreferrer"&gt;which is not documented because it is for internal usage&lt;/a&gt;. Or you want (as it is my case) to test something from the UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfq8kxdv9gtyq0ws1rsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfq8kxdv9gtyq0ws1rsl.png" alt="OpenShift Oauth Proxy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Before reading this article
&lt;/h2&gt;

&lt;p&gt;This article is about how to get access to the Jaeger query service when using the “production” deployment strategy and deploying via the &lt;a href="https://www.jaegertracing.io/docs/1.33/operator/" rel="noopener noreferrer"&gt;Jaeger Operator&lt;/a&gt;. Some steps can be the same if you are using other deployment methods. Even, these steps can be not needed if you disabled the security:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaegertracing.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Jaeger&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disable-oauth-proxy&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, take into account this is for OpenShift. So, if you are using Kubernetes without any security proxy or something, you’ll not need to follow these steps to access the Jaeger query endpoints. Or (if you are using another proxy) you’ll need to configure your credentials to access the API. I’ll assume you’re using the &lt;a href="https://github.com/openshift/oauth-proxy" rel="noopener noreferrer"&gt;OpenShift Oauth Proxy&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting access to the Jaeger query service
&lt;/h2&gt;

&lt;p&gt;Let’s imagine I deployed the following CRD (&lt;code&gt;kubectl create -f simple-prod.yaml&lt;/code&gt;) in the &lt;code&gt;israel&lt;/code&gt; namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaegertracing.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Jaeger&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;simple-prod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elasticsearch&lt;/span&gt;
    &lt;span class="na"&gt;elasticsearch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;nodeCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;200m&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of running &lt;code&gt;curl&lt;/code&gt; against the created OpenShift route will be a 403 error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get route simple-prod &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;
HTTP/1.1 403 Forbidden
Set-Cookie: &lt;span class="nv"&gt;_oauth_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;simple-prod-israel.apps.mycluster.iblancasa.com&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Expires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Thu, 05 May 2022 11:09:34 GMT&lt;span class="p"&gt;;&lt;/span&gt; HttpOnly&lt;span class="p"&gt;;&lt;/span&gt; Secure&lt;span class="p"&gt;;&lt;/span&gt; SameSite
Date: Thu, 05 May 2022 12:09:34 GMT
Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
Set-Cookie: &lt;span class="nv"&gt;3f978cf9c2d3ee8d70cad1d11aef9dcd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8d2f11be8db90157d1e73d19b515f187&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; HttpOnly&lt;span class="p"&gt;;&lt;/span&gt; Secure&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;SameSite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you didn’t specify the &lt;code&gt;-I&lt;/code&gt; option to receive just the headers, you will receive the full HTML code from the logging webpage. Let’s see how to get the “correct” answer from the server.&lt;/p&gt;

&lt;p&gt;The first step is to create a &lt;a href="https://docs.openshift.com/container-platform/4.10/authentication/understanding-and-creating-service-accounts.html" rel="noopener noreferrer"&gt;Service Account&lt;/a&gt;. From the OpenShift documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A service account is an OpenShift Container Platform account that allows a component to directly access the API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ll name my Service Account as “automation-access”. So, my file &lt;code&gt;sa.yaml&lt;/code&gt; contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;automation-access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create it in OpenShift using &lt;code&gt;kubectl create -f sa.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; sa.yaml
serviceaccount/automation-access created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to create a Cluster Role Binding. From the &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" rel="noopener noreferrer"&gt;Kubernetes documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A role binding grants the permissions defined in a role to a user or set of users. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. A RoleBinding grants permissions within a specific namespace whereas a ClusterRoleBinding grants that access cluster-wide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a simplification, we can use Cluster Role Bindings to establish relationships between, for instance, a Service Account and Cluster Role. In our case, it would be enough with &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/#other-component-roles" rel="noopener noreferrer"&gt;system:auth-delegator&lt;/a&gt; for the &lt;code&gt;jaeger-operator&lt;/code&gt; Service Account from the &lt;code&gt;observability&lt;/code&gt; namespace and &lt;a href="https://docs.openshift.com/container-platform/4.10/authentication/using-rbac.html#default-roles_using-rbac" rel="noopener noreferrer"&gt;cluster-reader&lt;/a&gt; for the Service Account we created before. Our &lt;code&gt;crb.yaml&lt;/code&gt; file will be similar to this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRoleBinding&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaeger-operator-with-auth-delegator&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;observability&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaeger-operator&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;observability&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRole&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;system:auth-delegator&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRoleBinding&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;automation-access-bind&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;automation-access&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;israel&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRole&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-reader&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And apply it to our OpenShift cluster using: &lt;code&gt;kubectl create -f crb.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; crb.yaml
clusterrolebinding.rbac.authorization.k8s.io/jaeger-operator-with-auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/automation-access-bind created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to set some extra options to our Jaeger deployment (&lt;code&gt;jaeger-sar.yaml&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jaegertracing.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Jaeger&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;simple-prod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;query.bearer-token-propagation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;openshift&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;sar&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"namespace":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"israel",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"resource":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"pods",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"verb":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"get"}'&lt;/span&gt;
      &lt;span class="na"&gt;delegateUrls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"/":{"namespace":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"israel",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"resource":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"pods",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"verb":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"get"}}'&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pass-access-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;pass-user-bearer-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user:info&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;user:check-access"&lt;/span&gt;
      &lt;span class="na"&gt;pass-basic-auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we apply it with &lt;code&gt;kubectl apply -f jaeger-sa.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; jaeger-sar.yaml
Warning: resource jaegers/simple-prod is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create &lt;span class="nt"&gt;--save-config&lt;/span&gt; or kubectl apply. The missing annotation will be patched automatically.
jaeger.jaegertracing.io/simple-prod configured
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok! We’re almost there. The next step is to get the token that will allow us to access the Jaeger query service programmatically. To get the token, we need to get the name of the &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;Kubernetes secret&lt;/a&gt; to use. We can get that information from the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get sa automation-access &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.secrets}'&lt;/span&gt;
&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"automation-access-token-q2p2x"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"automation-access-dockercfg-xvzsq"&lt;/span&gt;&lt;span class="o"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is the name of 2 secrets. We’ll use the one called &lt;code&gt;auomation-access-token-&amp;lt;ID&amp;gt;&lt;/code&gt;. If you use &lt;a href="https://mikefarah.gitbook.io/yq/" rel="noopener noreferrer"&gt;yq&lt;/a&gt;, the command can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get sa automation-access &lt;span class="nt"&gt;-o&lt;/span&gt; yaml | yq &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s1"&gt;'.secrets[] | select( .name == "*-token-*")'&lt;/span&gt;.name 
automation-access-token-q2p2x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, finally, we extract the token from the secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get secret automation-access-token-q2p2x &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.data.token}'&lt;/span&gt; |  &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
eyJhbGciOiJSUzI1NiIsImtpZCI6Iks3TXcwUWhyb3BVdUVJblhkQmVQT25Fek1KVVlfa2RPV3dDZWpJVXpmekUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJpc3JhZWwiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoiYXV0b21hdGlvbi1hY2Nlc3MtdG9rZW4tcTJwMngiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYXV0b21hdGlvbi1hY2Nlc3MiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI1NGY1ZDE0MC1lMDEwLTQ5NWYtYWE4Yy0wNmQ3ZjIwNjg3OGIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6aXNyYWVsOmF1dG9tYXRpb24tYWNjZXNzIn0.J5USv-olD1vU0A5tL8TT1SDoH-jf5f58hSIEPnkkiZzTiOjHHx2Vj2v1p0bm26epfTQwLV3TfIsgcsV7tnpC0cR64MmDQe9EuBtNonJqV45nTkSoboWuBfeSxXqjk7Tuj_bcZcutcA0vsVHzAglb-Z0wavx9ETfQJueDWTzF6Cry5HxVxYn6ytogHfbaEgiLN9HNeZBWW4xi7JAzY-2viECrFq1yEIJKzWDihZScFkyX2fu1UDpFLH2ewA8N6bdqSd5FTEna0JS0e8yxQcGo-oXykDW2G_YcLDBSrCpQaji390FgMp_6dEl1yHSazGgCaKwulwOU4Rr6usf807mdBQ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command gets the token from the secret and decodes it. We need to provide this token in the &lt;code&gt;Authorization&lt;/code&gt; header when doing a &lt;code&gt;curl&lt;/code&gt; call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get secret automation-access-token-q2p2x &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.data.token}'&lt;/span&gt; |  &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get route simple-prod &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.host}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
HTTP/1.1 200 OK
Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
Date: Thu, 05 May 2022 12:44:06 GMT
Gap-Auth: system:serviceaccount:israel:automation-sa@cluster.local
Gap-Upstream-Address: localhost:16686
Vary: Accept-Encoding
Set-Cookie: &lt;span class="nv"&gt;3f978cf9c2d3ee8d70cad1d11aef9dcd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2e6b6fcf2050268c74e1aabcf71e9bab&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; HttpOnly&lt;span class="p"&gt;;&lt;/span&gt; Secure&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;SameSite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;None
Cache-control: private
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading! I hope this article helped you! :)&lt;/p&gt;

</description>
      <category>openshift</category>
      <category>jaeger</category>
      <category>automation</category>
    </item>
    <item>
      <title>Observability: the basics</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Tue, 15 Feb 2022 22:25:39 +0000</pubDate>
      <link>https://dev.to/iblancasa/observability-the-basics-4njh</link>
      <guid>https://dev.to/iblancasa/observability-the-basics-4njh</guid>
      <description>&lt;p&gt;Probably you have heard about observability, but.. do you really understand it? In this post, I’ll explain it in an easy way. If this is the first time you read something about observability: I hope you learn a lot. Else, if you know a lot about observability, I hope you learn something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is observability?
&lt;/h2&gt;

&lt;p&gt;A system is observable when you can infer its internal state just from its outputs. That’s it. Sounds easy, right? Not exactly. The systems are more and more complex each day  and deciding what outputs provide the tools to use to manage that data and being able to convert those data into information can be a big challenge.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh29cckqh8px00k6v024k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh29cckqh8px00k6v024k.png" alt="Observability"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A 101 example
&lt;/h2&gt;

&lt;p&gt;Let’s imagine you created a calculator command line application. At some point, you try to multiply 3 by 3 and the result is 9 but, if you multiply 3 by 4, the result is 150. How would you debug that issue? Probably you will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the output of the program for different inputs&lt;/li&gt;
&lt;li&gt;Read the source code of the tool to detect what can go wrong&lt;/li&gt;
&lt;li&gt;Use a debugging tool (or add a lot of temporary print statements, right? 😛)
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F746wk6foixui5er6b8rj.png" alt="Example"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, after some time, you’ll find the issue, fix the problem, rebuild your application and, hopefully, run the tests to verify nothing was broken. This is so slow. And our example is a small application running in a single node: imagine when your codebase has thousands of lines of code, is running on a multi-cloud environment with hundreds of nodes and interacting with other applications. Problems can be difficult to find, aren't they? Systems are complex with complex failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is observability needed?
&lt;/h2&gt;

&lt;p&gt;The dependency of business on technology has increased over the years. And the architecture of those software systems too. And, as a consequence, the architecture of the systems where this software runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  From monolith to microservices
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf6dtakuji26bekfvxnu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf6dtakuji26bekfvxnu.png" alt="From monolith to microservices"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of articles about how a lot of companies have evolved the software architecture of their systems from a single application to a lot of them. "Splitting" your application into microservices has some advantages, like better scalability, faster time to market, greater agility or better fault tolerance.&lt;br&gt;
But it also has some disadvantages, like the need for more collaboration between teams or poorer performance (because the information needs to be sent through the network). And you need to maintain more systems. So, when something needs investigation (like an error or a performance degradation), instead of reviewing a single element, we need to inspect our microservices to detect which one is causing the issue and where.&lt;/p&gt;

&lt;h3&gt;
  
  
  From one machine to containers
&lt;/h3&gt;

&lt;p&gt;Another big change was in the infrastructure. Before, the applications were deployed on a single machine. The dependencies as databases were installed in the same machine. If the system needed more resources, the solution was to buy new hardware and migrate everything to the new machine. This is called vertical scaling. But this solution has limitations in the number of resources you can have in a machine and the price of hardware with a lot of resources is expensive. And you have to throw away your old hardware! What is the solution? Horizontal scaling.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xo4szxutwybla0fx1nu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xo4szxutwybla0fx1nu.png" alt="Horizontal scaling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can simplify and say that horizontal scaling is using small interconnected machines to work as a single unit. For example, you can have 10 machines running a web application and another one running a load balancer software to distribute the load between the different nodes.&lt;/p&gt;

&lt;p&gt;But using physical machines has a big inconvenience: when you don’t need all the computing power your system has, you are wasting resources. Virtual machines to rescue! Using virtual machines, you can benefit more from your resources. If you need more computing power, you create copies of the VM running your application. If you need less, you can scale down your system easily. And… What do you do with the spare resources? You rented them to other companies with the same problems (oh wait! We just invented Cloud Computing).&lt;/p&gt;

&lt;p&gt;This new scenario has other benefits: since you can create and destroy instances of your applications easily, if one of them starts to fail, you can remove it and spawn a new one. Another one: if you are running microservices, you can scale up or down one of them without affecting the others.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f6ji4px3miap3ad81oy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f6ji4px3miap3ad81oy.png" alt="Virtual machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using a cloud as infrastructure for your virtual machines avoids the need for maintaining physical hardware. And, depending on the cloud you are using, you can deploy your application in different regions, reducing the response delay of your customers.&lt;/p&gt;

&lt;p&gt;When we use physical resources, we could run one instance of our application machine. Now, we can run multiple instances per machine. But our infrastructure can be more efficient: for each VM, there is an installation of the full operating system, libraries and other stuff that is not really important for our application. How about a way to isolate the instances of our applications but share those resources? That’s the idea behind containers.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fam8ofz6rywgv9dn5pngw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fam8ofz6rywgv9dn5pngw.png" alt="VMs vs containers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With containers, we don’t need a hypervisor. Instead, we run a container engine in the host operating system and share OS resources across the different containers. As a consequence, each container includes the application and its dependencies. This leads to a lower resource usage per application instance. So, we can run more instances of our application in the same machine.&lt;/p&gt;

&lt;p&gt;The less resources we use, the more money we save.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is this related to observability?
&lt;/h3&gt;

&lt;p&gt;With one single instance of our application, observability was important to reduce the time to identify possible issues in our system. Imagine how important it is now, since we have hundreds of containers running instances of our microservices in different clouds with thousands of users accessing them. Systems are complex. And complexity increases the probabilities of creating a catastrophe.&lt;/p&gt;

&lt;p&gt;There is something you need to take into account: disaster can not be avoided. There will always be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Human error&lt;/li&gt;
&lt;li&gt;Network issues: latency, bandwidth, reliability…&lt;/li&gt;
&lt;li&gt;Outages&lt;/li&gt;
&lt;li&gt;Untested code paths&lt;/li&gt;
&lt;li&gt;Corner cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to be ready for issues to avoid them or, at least, recover from them as fast as possible. Each minute our system is not working, is money our company is losing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The free pillars of observability
&lt;/h2&gt;

&lt;p&gt;If your application is observable, you should be able to detect where the problem originated by checking the outputs. What outputs?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traces: contextual data about how a request or operation went through a system&lt;/li&gt;
&lt;li&gt;Metrics: quantitative information about the system&lt;/li&gt;
&lt;li&gt;Logs: specific messages emitted by a process or service
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F87fh6sku5lubspdfzy31.png" alt="Pillars of observability"&gt;
As I said, once your system is generating that data, you need to convert it into information. Usually, send everything to a central place where you can correlate everything. For instance: if you start seeing crashes in your applications, you can query your system to detect what queries are producing those crashes. After that, using tracing and logging, you can go directly to the source of the problem. Observability is about the integration of multiple sources of telemetry data together that can help you to better understand how your software is operating. To get context to solve a problem before it happens or as soon as possible after the failure is produced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Something that is pretty clear is that the concept of monitoring is complementary to observability. Monitoring tells you when something is wrong and observability why. Monitoring provides information about how the system is performing about connectivity, downtime or bottlenecks and observability what piece is failing and the reasons. Monitoring is part of observability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traces
&lt;/h3&gt;

&lt;p&gt;A trace is a visualization of the events in your system showing the calling relationship between the events. This visualization includes information like the timing data for each event. The individual events are called "spans".&lt;/p&gt;

&lt;p&gt;Using them, you can get what functions were called in your code or when one microservice connected a database to retrieve some information. And something really important: you can get how much time is spent in the different operations. Distributed tracing helps to do profiling of your system in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metrics
&lt;/h3&gt;

&lt;p&gt;They consist of a single numeric value tracked over time. We have used them in monitoring systems for years: CPU usage, memory, disk performance… But all this information gives us an incomplete view of what is happening in our system.&lt;/p&gt;

&lt;p&gt;Observable systems include the concept of "application performance monitoring". This new concept proposes to track application level metrics like average load times, error rates, requests per second, time to perform operations against third party services… providing a real picture of what the user experiences.&lt;/p&gt;

&lt;p&gt;Each metric tracks only one variable, which makes them more efficient to send and store.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logs
&lt;/h3&gt;

&lt;p&gt;Logs are text strings written to the terminal or to a file. You can generate these logs directly by printing information on the screen. But there are libraries that can help you to structurate that data to print information depending on the importance level (it is not the same as a debug message than an error message, for instance).&lt;/p&gt;

&lt;p&gt;Los aggregation services allow you to send these messages to a central place to store them. Later, you can retrieve that data and extract information about what is happening in your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;I hope you found this article useful. I'll create more posts about more observability topics soon!&lt;/p&gt;

</description>
      <category>observability</category>
      <category>tracing</category>
      <category>logging</category>
      <category>metrics</category>
    </item>
    <item>
      <title>Use VS Code online for your workshops!</title>
      <dc:creator>Israel Blancas</dc:creator>
      <pubDate>Wed, 20 Oct 2021 20:05:02 +0000</pubDate>
      <link>https://dev.to/iblancasa/use-vs-code-online-for-your-workshops-4p83</link>
      <guid>https://dev.to/iblancasa/use-vs-code-online-for-your-workshops-4p83</guid>
      <description>&lt;p&gt;How many times did your workshops turn into a copy-code-from-slides session? When you run a workshop, it is easy your attendees get lost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They can not see your slides to copy the examples&lt;/li&gt;
&lt;li&gt;The code is long and is easy to mistype something&lt;/li&gt;
&lt;li&gt;They spend more time copying code than actually attending what you are saying&lt;/li&gt;
&lt;li&gt;If they distract, they can be lost the rest of the session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It would be amazing if you could send the code ahead to their laptops while you are explaining. Right? You would reduce the copy/paste time. The audience engagement would be higher. Everybody would learn more with less effort. I was thinking a lot about this problem two days ago.&lt;/p&gt;

&lt;p&gt;One alternative could be to use something like &lt;a href="https://www.google.com/intl/es_es/drive/" rel="noopener noreferrer"&gt;Google Drive&lt;/a&gt;. But those tools are not good when you share code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No syntax highlighting&lt;/li&gt;
&lt;li&gt;Copy/paste operations can be a problem&lt;/li&gt;
&lt;li&gt;You cannot handle more than one file at the same time in a single session&lt;/li&gt;
&lt;li&gt;No code suggestions/autocompletion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other tools like &lt;a href="https://codeanywhere.com/" rel="noopener noreferrer"&gt;Code Anywhere&lt;/a&gt; that allow you to share code on real time with different people. Even, they allow you to enter in a “classroom” mode -where the invitees to the session cannot modify the code you are sharing-. But they also have their problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not easy to find one free&lt;/li&gt;
&lt;li&gt;Usually, the users need to register in the tool platform&lt;/li&gt;
&lt;li&gt;Poor language support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some code editors have plugins to allow the developers to create collaboration sessions. &lt;a href="https://docs.microsoft.com/es-es/visualstudio/liveshare/use/vscode" rel="noopener noreferrer"&gt;Visual Studio has Live Share&lt;/a&gt; and &lt;a href="https://teletype.atom.io/" rel="noopener noreferrer"&gt;Atom has Teletype&lt;/a&gt;. But the invitees need to install the editor to be able to join the session. Until today.&lt;/p&gt;

&lt;p&gt;Today I saw this tweet:&lt;br&gt;
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Wanna see something cool? 😎 Go to "&lt;a href="https://t.co/k0d9MtptVW" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://t.co/k0d9MtptVW" rel="noopener noreferrer"&gt;https://t.co/k0d9MtptVW&lt;/a&gt;" and start coding with Visual Studio Code entirely in your browser. Anywhere, anytime, on any device and tablet, with no install required 🧑‍💻🪄&lt;br&gt;Read the announcement 👉 &lt;a href="https://t.co/XpTxjfVENL" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://t.co/XpTxjfVENL" rel="noopener noreferrer"&gt;https://t.co/XpTxjfVENL&lt;/a&gt; &lt;a href="https://t.co/eOxK5gSoiE" rel="noopener noreferrer"&gt;pic.twitter.com/eOxK5gSoiE&lt;/a&gt;&lt;/p&gt;— Visual Studio Code (@code) &lt;a href="https://twitter.com/code/status/1450853494949244929?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;October 20, 2021&lt;/a&gt;
&lt;/blockquote&gt; 

&lt;p&gt;Now when you visit the &lt;a href="https://vscode.dev/" rel="noopener noreferrer"&gt;vscode.dev&lt;/a&gt;, you'll go to a website with a lightweight version of VS Code running fully in the browser. Open a folder on your local machine and start coding. There are some limitations like you can't access a debugger or a terminal… but it is better than what we currently have. And... &lt;strong&gt;it's free&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04xfdrybsd7eot4x8iyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04xfdrybsd7eot4x8iyz.png" alt="vscode.dev" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does this mean?&lt;/strong&gt; You can ask the assistants to your workshop to open &lt;a href="https://vscode.dev/" rel="noopener noreferrer"&gt;vscode.dev&lt;/a&gt;, &lt;a href="https://code.visualstudio.com/learn/collaboration/live-share#_get-started-with-live-share" rel="noopener noreferrer"&gt;install the Live Share extension&lt;/a&gt; and… share the code easily! &lt;strong&gt;They will not need to sign up on a new service or something similar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm looking forward to schedule a workshop session to test Visual Studio online, and you?&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>workshop</category>
      <category>conference</category>
      <category>editor</category>
    </item>
  </channel>
</rss>
