<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Development Archives - Blog IT</title>
	<atom:link href="https://blogit.create.pt/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogit.create.pt/category/development/</link>
	<description>Create IT blogger community</description>
	<lastBuildDate>Fri, 20 Jun 2025 15:21:53 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>Learning: Observability</title>
		<link>https://blogit.create.pt/davidpereira/2025/06/20/learning-observability/</link>
					<comments>https://blogit.create.pt/davidpereira/2025/06/20/learning-observability/#respond</comments>
		
		<dc:creator><![CDATA[David Pereira]]></dc:creator>
		<pubDate>Fri, 20 Jun 2025 13:08:49 +0000</pubDate>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[observability]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=13517</guid>

					<description><![CDATA[<p>Table of Contents Introduction In this small post, I&#8217;ll share some resources, notes I&#8217;ve taken while learning, and best practices for making our systems observable. I&#8217;ve always had a knowledge gap regarding observability, and recently I&#8217;ve truly enjoyed learning more about this area in our software industry. Quick note: In this post I&#8217;ll only share [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/davidpereira/2025/06/20/learning-observability/">Learning: Observability</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Table of Contents</h2>



<ul style="max-width:1005px" class="wp-block-list">
<li>Introduction</li>



<li>Get Started</li>



<li>Logs
<ul style="max-width:960px" class="wp-block-list">
<li>Canonical logs</li>
</ul>
</li>



<li>Traces</li>



<li>Metrics</li>



<li>General Best Practices</li>



<li>Resources
<ul style="max-width:960px" class="wp-block-list">
<li>GitHub demo repo</li>
</ul>
</li>



<li>Conclusion</li>
</ul>



<h2 class="wp-block-heading">Introduction</h2>



<p>In this small post, I&#8217;ll share some resources, notes I&#8217;ve taken while learning, and best practices for making our systems observable. I&#8217;ve always had a knowledge gap regarding observability, and recently I&#8217;ve truly enjoyed learning more about this area in our software industry.</p>



<p><strong>Quick note</strong>: In this post I&#8217;ll only share about 3 telemetry&nbsp;<a href="https://opentelemetry.io/docs/concepts/signals/" target="_blank" rel="noreferrer noopener">signals</a>.&nbsp;<strong>Profile</strong>&nbsp;is another signal that I will research in the future.</p>



<p></p>



<h2 class="wp-block-heading">Get Started</h2>



<p>Follow these steps to get started with auto-instrumentation in your application using OpenTelemetry:&nbsp;<a href="https://opentelemetry.io/docs/languages/net/getting-started/#instrumentation" target="_blank" rel="noreferrer noopener">https://opentelemetry.io/docs/languages/net/getting-started/#instrumentation</a></p>



<p>For OpenTelemetry in a front-end app you can check these useful resources:</p>



<ul style="max-width:1005px" class="wp-block-list">
<li><a href="https://grafana.com/oss/faro/" target="_blank" rel="noreferrer noopener">Grafana faro</a></li>



<li><a href="https://nextjs.org/docs/app/building-your-application/optimizing/open-telemetry#using-vercelotel" target="_blank" rel="noreferrer noopener">Next.js</a></li>



<li><a href="https://www.checklyhq.com/blog/in-depth-guide-to-monitoring-next-js-apps-with-opentelemetry/" target="_blank" rel="noreferrer noopener">Guide for OpenTelemetry in Next.js</a></li>



<li><a href="https://opentelemetry.io/docs/languages/js/getting-started/browser/" target="_blank" rel="noreferrer noopener">Browser OpenTelemetry getting started</a></li>
</ul>



<p></p>



<p>Client-side instrumentation in OpenTelemetry is part of&nbsp;<a href="https://opentelemetry.io/community/roadmap/#p2-client-instrumentation-rum" target="_blank" rel="noreferrer noopener">their roadmap</a>&nbsp;which is great to see, since I&#8217;ve only seen vendor-specific solutions and products for front-end apps (e.g. New Relic, Datadog). For browser instrumentation otel doesn&#8217;t seem to be super mature yet, but a lot of effort is being put into this area by the OpenTelemetry team.</p>



<h2 class="wp-block-heading">Logs</h2>



<p>We all know about logs 😄. It&#8217;s data that we all need in order to troubleshoot and know what is happening in our applications. We shouldn&#8217;t overdo it, creating tons and tons of logs since that will probably create noise and make it harder to troubleshoot problems.</p>



<p>For logs, we can use&nbsp;<a href="https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/docs/logs/README.md#best-practices" target="_blank" rel="noreferrer noopener">these best practices</a>. From this list, these are an absolute must to follow:</p>



<ul style="max-width:1005px" class="wp-block-list">
<li>Avoid string interpolation</li>



<li>Use structured logging</li>



<li>Log redaction for sensitive information</li>
</ul>



<p>In addition to the list above, we should also include the&nbsp;<code>TraceId</code>&nbsp;and&nbsp;<code>SpanId</code>&nbsp;in our log records, to correlate logs with traces. If you are using the Serilog console sink,&nbsp;<a href="https://github.com/serilog/serilog-sinks-console/blob/4c9a7b6946dfd2d7f07a792c40bb3d46af835ee9/src/Serilog.Sinks.Console/ConsoleLoggerConfigurationExtensions.cs#L32" target="_blank" rel="noreferrer noopener">by default the message template</a>&nbsp;won&#8217;t have those fields so if you want them, consider using&nbsp;<a href="https://github.com/serilog/serilog/wiki/Formatting-Output#formatting-json" target="_blank" rel="noreferrer noopener">JsonFormatter</a>&nbsp;or&nbsp;<code>CompactJsonFormatter</code>. Here is an example Serilog configuration in&nbsp;<code>appsettings.json</code>&nbsp;(setup to remove unnecessary/noisy logs):</p>



<pre class="wp-block-code"><code>"Serilog": {
    "Using": &#091;
      "Serilog.Sinks.Console"
    ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft.AspNetCore": "Warning",
        "Microsoft.Extensions.Diagnostics.HealthChecks": "Warning"
      }
    },
    "WriteTo": &#091;
      {
        "Name": "Console",
        "Args": {
          "formatter": {
            "type": "Serilog.Formatting.Json.JsonFormatter, Serilog",
            "renderMessage": true
          }
        }
      }
    ],
    "Enrich": &#091;
      "FromLogContext",
      "WithMachineName",
      "WithThreadId",
      "WithProcessId",
      "WithProcessName",
      "WithExceptionDetails",
      "WithExceptionStackTraceHash",
      "WithEnvironmentName"
    ],
    "Properties": {
      "Application": "GrafanaDemoOtelApp"
    }
  }</code></pre>



<p>Below are some documentation links for logging in .NET. The&nbsp;<code>ILogger</code>&nbsp;extension methods are not always the best choice (e.g.&nbsp;<code>logger.LogInformation</code>), especially in high-performance scenarios or if your logs are in a hot path:</p>



<ul style="max-width:1005px" class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/high-performance-logging" target="_blank" rel="noreferrer noopener">High-performance logging in .NET</a></li>



<li><a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator" target="_blank" rel="noreferrer noopener">Compile-time logging source generation</a></li>
</ul>



<h3 class="wp-block-heading">Canonical logs</h3>



<p>There is also a different way of logging, based on having more attributes in one single log line. I&#8217;ve seen this in Stripe where they call it <a href="https://stripe.com/blog/canonical-log-lines" target="_blank" rel="noreferrer noopener">canonical log lines</a>. Charity Majors also references this <strong>canonical logs</strong> term in her blog post about Observability 2.0 (that I reference in the Resources section).</p>



<p>This idea is very interesting, but might lack awareness. At least in .NET land, I didn&#8217;t find many references to this style of logging or example code that we could follow when there are many&nbsp;<code>ILogger</code>&nbsp;instances involved.</p>



<p></p>



<h2 class="wp-block-heading">Traces</h2>



<p>For traces in .NET we have <a href="https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#best-practices-1">these best practices</a>. So far I&#8217;ve seen four common solutions for adding <a href="https://microsoft.github.io/code-with-engineering-playbook/observability/correlation-id/" target="_blank" rel="noreferrer noopener">correlation ids</a> in traces (not all are standards):</p>



<ul style="max-width:1005px" class="wp-block-list">
<li><a href="https://www.w3.org/TR/trace-context/" target="_blank" rel="noreferrer noopener">W3C trace context</a>&nbsp;&#8211; current standard in the HTTP protocol for tracing</li>



<li><a href="https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Common_non-standard_request_fields" target="_blank" rel="noreferrer noopener">X-Correlation-Id</a>&nbsp;&#8211; a non-standard HTTP header for RESTful APIs (also known as&nbsp;<a href="https://http.dev/x-request-id" target="_blank" rel="noreferrer noopener">X-Request-Id</a>). I thought this was a standard since it&#8217;s widely used, but I didn&#8217;t find a RFC from IETF or any other organization.</li>



<li><a href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Diagnostics.DiagnosticSource/src/HttpCorrelationProtocol.md" target="_blank" rel="noreferrer noopener">Request-Id</a>&nbsp;&#8211; this is a known header in the .NET ecosystem</li>



<li><a href="https://github.com/openzipkin/b3-propagation" target="_blank" rel="noreferrer noopener">B3 Zipkin propagation</a>&nbsp;&#8211; Zipkin format standard</li>



<li><a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader" target="_blank" rel="noreferrer noopener">AWS X-Ray Trace Id</a>&nbsp;&#8211; proprietary solution for AWS that adds headers for tracing</li>
</ul>



<p>Not every company/project uses W3C trace context, you have some options above to pick from. I prefer the standard W3C trace context 😄 (maybe the industry will widely adopt this in the future) and using OpenTelemetry to manage these headers (HTTP, AMQP, etc) and correlation with logs automatically. The code you don&#8217;t write can&#8217;t have bugs 😆.</p>



<p>With that said, in some situations, you might have integrations with 3rd party software and need to use their custom headers or project limitations and need to use a particular format. At the end of the day what&#8217;s important is that you have distributed tracing working E2E.</p>



<p>There is also a relevant spec for distributed tracing called&nbsp;<a href="https://www.w3.org/TR/baggage/" target="_blank" rel="noreferrer noopener">Baggage</a>&nbsp;which OpenTelemetry implements and we can use in our apps. The most important part here is trace propagation to get the full trace from the publisher to the consumer.</p>



<p></p>



<h2 class="wp-block-heading">Metrics</h2>



<p>For metrics, it&#8217;s important to follow naming conventions for custom metrics. Especially if your organization has a platform team, setting conventions helps everyone. I do know some otel semantic conventions aren&#8217;t stable, and that also leads to some nuget packages being pre-release.</p>



<p>But anyhow, set conventions for your team or read and follow&nbsp;<a href="https://opentelemetry.io/docs/specs/semconv/general/metrics/" target="_blank" rel="noreferrer noopener">OpenTelemetry semantic conventions</a>.<br>An important resource I found is the comments on&nbsp;<a href="https://prometheus.io/docs/practices/instrumentation/#do-not-overuse-labels" target="_blank" rel="noreferrer noopener">Prometheus best practices</a>&nbsp;related to high cardinality metrics.</p>



<p>When I started trying out custom metrics instrumentation I discovered that OpenTelemetry is not always used (the SDK + OTLP). We have the Prometheus SDK which is mature and widely used. Then for Java there are other solutions like Micrometer and others that integrate very well with Spring. In regards to the Java ecosystem, I read&nbsp;<a href="https://opentelemetry.io/blog/2024/java-metric-systems-compared/#benchmark-opentelemetry-java-vs-micrometer-vs-prometheus-java" target="_blank" rel="noreferrer noopener">this otel Java benchmarks</a>&nbsp;and&nbsp;<a href="https://spring.io/blog/2024/10/28/lets-use-opentelemetry-with-spring" target="_blank" rel="noreferrer noopener">this Spring post</a>&nbsp;just because I was interested in knowing what the industry is adopting and why.</p>



<p></p>



<h2 class="wp-block-heading">General Best Practices</h2>



<p>There is a ton to be learned with SRE principles and practices. But one in particular was very useful for me and my team:&nbsp;<strong>always categorize our custom metrics according to the 4 Golden Signals</strong>. Any metric we can&#8217;t categorize is probably not useful for us.</p>



<figure class="wp-block-image is-resized td-caption-align-center"><img fetchpriority="high" decoding="async" width="800" height="800" src="https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring.webp" alt="" class="wp-image-13523" style="width:808px;height:auto" srcset="https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring.webp 800w, https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring-300x300.webp 300w, https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring-150x150.webp 150w, https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring-768x768.webp 768w, https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring-420x420.webp 420w, https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring-696x696.webp 696w, https://blogit.create.pt/wp-content/uploads/2025/05/deniseyu_art_monitoring-70x70.webp 70w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption"><em>Image Credit to &#8211; Denise Yu</em></figcaption></figure>



<p><a href="https://deniseyu.io/art/" target="_blank" rel="noreferrer noopener">Source of Denise Yu&#8217;s art</a>.</p>



<p><a href="https://sre.google/sre-book/monitoring-distributed-systems/" target="_blank" rel="noreferrer noopener">Google&#8217;s SRE book</a>&nbsp;is amazing to learn more about the 4 Golden signals and creating SLO-based alerts. All our alerts should be actionable (or the support team will not be happy), so it helps if they are based on SLOs that are defined as a team.</p>



<p>They also have&nbsp;<a href="https://sre.google/sre-book/service-best-practices/" target="_blank" rel="noreferrer noopener">some best practices for production services</a>.</p>



<p></p>



<h2 class="wp-block-heading">Resources</h2>



<ul style="max-width:1005px" class="wp-block-list">
<li>Glossary of many observability terms in case you’re not familiar with them:&nbsp;<a href="https://github.com/prathamesh-sonpatki/o11y-wiki" target="_blank" rel="noreferrer noopener">https://github.com/prathamesh-sonpatki/o11y-wiki</a></li>



<li><a href="https://github.com/magsther/awesome-opentelemetry" target="_blank" rel="noreferrer noopener">Awesome Observability GitHub repo</a></li>



<li>If dashboards make you happy&nbsp;<a href="https://play.grafana.org/d/feg4yc4qw3wn4b/third-annual-observability-survey?pg=survey-2025&amp;plcmt=toc-cta-2&amp;orgId=1&amp;from=2025-03-13T02:49:20.476Z&amp;to=2025-03-14T02:49:20.476Z&amp;timezone=utc&amp;var-region=$__all&amp;var-role=$__all&amp;var-size=$__all&amp;var-industry=$__all&amp;var-filters=%60Region%60%20in%20%28%27Europe%27,%27Asia%27,%27North%20America%27,%27Africa%27,%27South%20America%27,%27Oceania%27,%27Middle%20East%27%29%20AND%20%60Role%60%20IN%20%28%27Platform%20team%27,%27SRE%27,%27CTO%27,%27Engineering%20manager%27,%27Developer%27,%27Director%20of%20engineering%27,%27Other%27%29%20AND%20%60Size_of_organization%60%20IN%20%28%2710%20or%20fewer%20employees%27,%2711%20-%20100%20employees%27,%27101%20-%20500%20employees%27,%27501%20-%201,000%20employees%27,%271,001%20-%202,500%20employees%27,%272,501%20-%205,000%20employees%27,%275,001%2B%20employees%27%29%20AND%20%60Industry%60%20IN%20%28%27Telecommunications%27,%27Healthcare%27,%27IoT%27,%27Financial%20services%27,%27Education%27,%27Government%27,%27Applied%20Sciences%27,%27Software%20%26%20Technology%27,%27Media%20%26%20Entertainment%27,%27Travel%20%26%20Transportation%27,%27Retail%2FE-commerce%27,%27Energy%20%26%20Utilities%27,%27Automotive%20%26%20Manufacturing%27,%27Other%27%29" target="_blank" rel="noreferrer noopener">check the Grafana observability report dashboard</a></li>



<li><a href="https://aws-observability.github.io/observability-best-practices/guides/" target="_blank" rel="noreferrer noopener">AWS observability best practices guide</a></li>



<li><a href="https://grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services/" target="_blank" rel="noreferrer noopener">About RED and USE method</a></li>



<li><a href="https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#best-practices-1" target="_blank" rel="noreferrer noopener">Traces Instrumentation best practices in .NET</a></li>



<li><a href="https://signoz.io/guides/what-are-the-limitations-of-prometheus-labels/#what-are-the-limitations-of-prometheus-labels" target="_blank" rel="noreferrer noopener">What are the Limitations of Prometheus Labels?</a></li>



<li><a href="https://www.cncf.io/training/certification/otca/" target="_blank" rel="noreferrer noopener">CNCF OpenTelemetry certification</a></li>



<li><a href="https://github.com/cncf/tag-observability/blob/main/whitepaper.md" target="_blank" rel="noreferrer noopener">TAG Observability whitepaper</a>&nbsp;&#8211; this is an amazing resource with tons of information! I also recommend checking out the other resources they have in the tag-observability repo and community</li>



<li>Resources specifically about&nbsp;<strong>Observability 2.0</strong>:
<ul style="max-width:970px" class="wp-block-list">
<li><a href="https://charity.wtf/tag/observability-2-0/" target="_blank" rel="noreferrer noopener">Observability 2.0 by Charity Majors</a></li>



<li><a href="https://www.aparker.io/post/3leq2g72z7r2t" target="_blank" rel="noreferrer noopener">Re-Redefining Observability</a></li>



<li><a href="https://www.youtube.com/watch?v=ag2ykPO805M" target="_blank" rel="noreferrer noopener">Is It Time To Version Observability? (Signs Point To Yes) &#8211; Charity Majors</a></li>
</ul>
</li>



<li>Talks
<ul style="max-width:970px" class="wp-block-list">
<li><a href="https://www.youtube.com/watch?v=hhZrOHKIxLw" target="_blank" rel="noreferrer noopener">How Prometheus Revolutionized Monitoring at SoundCloud &#8211; Björn Rabenstein</a></li>



<li><a href="https://www.youtube.com/watch?v=X99X-VDzxnw" target="_blank" rel="noreferrer noopener">How to Include Latency in SLO-based Alerting &#8211; Björn Rabenstein, Grafana Labs</a></li>



<li><a href="https://www.youtube.com/watch?v=pLPMAAOSxSE" target="_blank" rel="noreferrer noopener">Myths and Historical Accidents: OpenTelemetry and the Future of Observability Part 1</a></li>



<li><a href="https://youtu.be/3tBj3ZCPGJY?t=687" target="_blank" rel="noreferrer noopener">Modern Platform Engineering: 9 Secrets of Generative Teams &#8211; Liz Fong-Jones</a></li>



<li><a href="https://www.youtube.com/watch?v=gviWKCXwyvY" target="_blank" rel="noreferrer noopener">Context Propagation makes OpenTelemetry awesome</a></li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading">GitHub demo repo</h3>



<p>I&#8217;ve been developing a demo app (it has fewer features than the&nbsp;<a href="https://github.com/open-telemetry/opentelemetry-demo" target="_blank" rel="noreferrer noopener">otel demo</a>) to demonstrate how to build an app with OpenTelemetry, Grafana and Prometheus. It&#8217;s primarily focused on a small app I can showcase in my talks.</p>



<p>If you&#8217;re interested take a look: <a href="https://github.com/BOLT04/grafana-observability-demo">https://github.com/BOLT04/grafana-observability-demo</a></p>



<p></p>



<h2 class="wp-block-heading">Conclusion</h2>



<img decoding="async" src="https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExeGh0em9taDR0N2hodXIycnh4a3RqbXk2cWRoeDFjODU2Mmd0MDJqdSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/tkApIfibjeWt1ufWwj/giphy.gif" alt="happy gif" loading="lazy">



<p>Hopefully, some of these resources I&#8217;ve shared are useful to you 😄. I still have a ton to learn and explore, but I&#8217;m happy with the knowledge I&#8217;ve acquired so far.</p>



<p>There are some specific standards + projects that I&#8217;ll dive in and explore more, like: eBPF; OpenMetrics. OpenMetrics is something I&#8217;d like to spend some quality time reading about, but I know&nbsp;<a href="https://www.cncf.io/blog/2024/09/18/openmetrics-is-archived-merged-into-prometheus/" target="_blank" rel="noreferrer noopener">it&#8217;s archived</a>&nbsp;and&nbsp;<a href="https://www.reddit.com/r/devops/comments/1f5ttdx/openmetrics_is_archived_merged_into_prometheus/?rdt=47070" target="_blank" rel="noreferrer noopener">reddit says the same</a>. Just want to read and watch some talks about it to feed my curiosity 😃.</p>



<p>Last but not least, I want to follow the work that some industry leaders are doing like&nbsp;<a href="https://charity.wtf/" target="_blank" rel="noreferrer noopener">Charity Majors</a>, specifically about Observability 2.0 😄. I discovered this term in the&nbsp;<a href="https://www.thoughtworks.com/radar/techniques/summary/observability-2-0" target="_blank" rel="noreferrer noopener">Thouthworks tech radar</a>, and the part &#8220;high-cardinality event data in a single data store&#8221; caught my interest.<br>I&#8217;m still learning, researching, and listening to the opinions of industry leaders about this term to then develop my own opinions. Maybe I&#8217;ll make a blog post about this in the future 😁.</p>



<p>If you&#8217;re interested, check out my other blog posts:</p>



<ul style="max-width:1005px" class="wp-block-list">
<li><a href="https://blogit.create.pt/davidpereira/2024/02/05/dreamforce-2023-highlights/">Dreamforce 2023 Highlights</a></li>



<li><a href="https://blogit.create.pt/davidpereira/2021/09/16/getting-started-with-cloudevents-and-asyncapi/">Getting Started with CloudEvents and AsyncAPI</a></li>
</ul>



<p></p>
<p>The post <a href="https://blogit.create.pt/davidpereira/2025/06/20/learning-observability/">Learning: Observability</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/davidpereira/2025/06/20/learning-observability/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Integration Tests in .NET WebApi</title>
		<link>https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/</link>
					<comments>https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/#respond</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 01 Apr 2024 12:47:41 +0000</pubDate>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Automatic Testing]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[inmemorydatabase]]></category>
		<category><![CDATA[integrated]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=13472</guid>

					<description><![CDATA[<p>In software development, testing is an essential aspect that ensures the stability and reliability of applications. Three primary types of tests are commonly used: unit tests, integration tests, and end-to-end tests. In this blog post, we will discuss these testing types in the context of a .NET WebAPI project and provide an example implementation of integration testing using an in-memory database.</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/">Integration Tests in .NET WebApi</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In software development, testing is an essential aspect that ensures the stability and reliability of applications. Three primary types of tests are commonly used: unit tests, integration tests, and end-to-end tests. In this blog post, we will discuss these testing types in the context of a .NET WebAPI project and provide an example implementation of integration testing using an in-memory database.</p>



<hr class="wp-block-separator has-alpha-channel-opacity" />



<h2 class="wp-block-heading">Unit Tests, Integration Tests, and End-to-End Tests: What&#8217;s the Difference?</h2>



<ul class="wp-block-list">
<li><strong>Unit tests</strong> focus on testing individual units or components of your application in isolation. This type of test verifies whether the unit/component works correctly and adheres to its business logic.</li>



<li><strong>Integration tests</strong> aim to test multiple units or components together, ensuring that they interact properly. Integration tests can uncover issues related to data flow, communication between components, and external dependencies like databases.</li>



<li><strong>End-to-end (E2E)</strong> tests simulate a complete user scenario by testing the entire application from start to finish. E2E tests can help identify issues related to multiple components, external APIs, and user interfaces.</li>
</ul>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">Example Implementation in .NET</h2>



<p>To perform integration tests, we will use an in-memory database and the <em>WebApplicationFactory </em>feature of ASP.NET Core. This approach allows us to test our WebAPI application with a real web server in memory, simulating how the components interact with each other when making requests.</p>



<p>First, let&#8217;s create an InMemoryDbAppFactory that sets up our in-memory web server and database:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
public class InMemoryDbAppFactory : WebApplicationFactory&lt;Program&gt;
{
    private readonly string _environment;

    public InMemoryDbAppFactory()
    {
        _environment = &quot;IntegrationTests&quot;;
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        Environment.SetEnvironmentVariable(&quot;ASPNETCORE_ENVIRONMENT&quot;, _environment);
        builder.UseEnvironment(_environment);
        builder.UseSetting(&quot;https_port&quot;, &quot;8080&quot;);

        builder.ConfigureTestServices(services =&gt;
        {
            services.RemoveAll&lt;ITestRepository&gt;();
            services.TryAddTransient&lt;ITestRepository, TestRepositoryTest&gt;();

            // Anonymous authentication
            services
                .AddAuthentication(&quot;Test&quot;)
                .AddScheme&lt;AuthenticationSchemeOptions, TestAuthenticationHandler&gt;(&quot;Test&quot;, options =&gt; { });
        });
    }
}
</pre></div>


<p>In order to use an in-memory database, we will override the connection string injection in our <em>ServiceCollectionExtensions</em>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
public static partial class ServiceCollectionExtensions
{
    public static IServiceCollection AddDbContexts(
        this IServiceCollection services,
        IConfiguration configuration,
        IWebHostEnvironment environment
    )
    {
        if (environment.IsEnvironment(&quot;IntegrationTests&quot;))
        {
            var connDb = new SqliteConnection(&quot;DataSource=db;mode=memory;cache=shared&quot;);
            connDb.Open();
            services.AddDbContext&lt;dbContext&gt;(options =&gt; options.UseSqlite(connDb));
        }
        else
        {
            services.AddDbContext&lt;dbContext&gt;(
                options =&gt; options.UseSqlServer(configuration.GetConnectionString(&quot;ConnectionString&quot;)).UseExceptionProcessor(),
                ServiceLifetime.Scoped
            );
        }

        return services;
    }
}
</pre></div>


<p>Finally, this is how a test looks like:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
&#x5B;Collection(&quot;MemoryDbIntegrationTests&quot;)]
public class ApiTests : IClassFixture&lt;InMemoryDbAppFactory&gt;
{
    private readonly InMemoryDbAppFactory _factory;
    private readonly HttpClient _client;

    public ApiTests(InMemoryDbAppFactory factory)
    {
        _factory = factory;
        _client = factory.CreateClient();

        // Ensures a clean database before each test
        factory.ResetDb();
    }

    &#x5B;Fact]
    public async Task GetList_Should_Return_List()
    {
        // Arrange

        // Act
        var response = await _client.GetAsync(&quot;/api/list&quot;);
        var content = await response.Content.ReadFromJsonAsync&lt;IEnumerable&lt;Dto&gt;&gt;();

        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        content.Should().NotBeNull();
        content.Should().HaveCount(2);
    }
}

</pre></div></div>
</div>



<hr class="wp-block-separator has-alpha-channel-opacity" />



<h2 class="wp-block-heading">Using an in-memory database for integration tests has both advantages and disadvantages:</h2>



<h3 class="wp-block-heading">Advantages:</h3>



<ul class="wp-block-list">
<li><strong>Faster test execution</strong>: In-memory databases provide quicker test execution times since the data is stored in memory instead of on disk. This can significantly improve your overall testing performance and help you find issues faster.</li>



<li><strong>Easy to set up and tear down</strong>: In-memory databases are easy to create, modify, and delete without the need for external dependencies or configuration changes. This makes it easier to write, run, and maintain your tests.</li>



<li><strong>Consistent test data</strong>: In-memory databases allow you to create a known set of data for your tests, ensuring that each test starts with the same initial conditions. This can help reduce the likelihood of inconsistent test results and make it easier to identify issues related to data flow or dependencies between tests.</li>
</ul>



<h3 class="wp-block-heading">Disadvantages:</h3>



<ul class="wp-block-list">
<li><strong>Limited scalability</strong>: In-memory databases have limited capacity and may not be suitable for testing large datasets or complex scenarios that require high levels of concurrency.</li>



<li><strong>Lack of realism</strong>: In-memory databases may not accurately represent the behavior or performance of a production database, especially when dealing with complex queries or data modification operations. This can make it difficult to identify issues related to database schema, indexing, and query optimization.</li>



<li><strong>Limited support for advanced features</strong>: using SQLite as our in memory database we don&#8217;t have support for multiple schemas and some advanced query features.</li>



<li><strong>Seed data</strong>: the need to create seed data can be tedious and time consuming.</li>
</ul>



<p>When deciding whether to use an in-memory database, mock data, or a real web server in memory for your integration tests, consider the specific requirements of your project and weigh the advantages and disadvantages of each approach. In many cases, using a combination of testing types and approaches can help you ensure the stability, reliability, and performance of your .NET WebAPI application.</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/">Integration Tests in .NET WebApi</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Performing broker migrations on your Kafka consumers</title>
		<link>https://blogit.create.pt/joaorafael/2023/03/15/kafka-consumer-broker-migration-aws-msk/</link>
					<comments>https://blogit.create.pt/joaorafael/2023/03/15/kafka-consumer-broker-migration-aws-msk/#respond</comments>
		
		<dc:creator><![CDATA[João Rafael]]></dc:creator>
		<pubDate>Wed, 15 Mar 2023 12:44:45 +0000</pubDate>
				<category><![CDATA[Deployment]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Kafka]]></category>
		<category><![CDATA[migrations]]></category>
		<category><![CDATA[MSK]]></category>
		<category><![CDATA[Streaming]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12805</guid>

					<description><![CDATA[<p>When using Kafka for communication between systems, you may find yourself having to change your consumer configuration. This may happen due to the publisher changing topic, or a new message broker being created and a company-wide mandate that everyone switch until a set date. Doing this sort of migration isn&#8217;t very complicated, but any errors [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/joaorafael/2023/03/15/kafka-consumer-broker-migration-aws-msk/">Performing broker migrations on your Kafka consumers</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When using Kafka for communication between systems, you may find yourself having to change your consumer configuration. This may happen due to the publisher changing topic, or a new message broker being created and a company-wide mandate that everyone switch until a set date. Doing this sort of migration isn&#8217;t very complicated, but any errors may prove to be costly. If we re-consume a new topic from the beginning, for example, we may accidentally fill up our database, for example. We want to start consuming the new topic at around the same time we stopped consuming the old one (with a buffer of a few minutes preferably, just to be safe).</p>



<p>The first step here is to ensure that your consumer code is idempotent, but that’s something that you should always ensure &#8211; just imagine that you have to re-consume a couple of messages, in that case lacking idempotency may result in your system getting strange data and bugs.</p>



<h2 class="wp-block-heading">Setting up Kafka on your machine</h2>



<p><em>(Feel free to skip this section if you have everything set up.)</em></p>



<p>Kafka releases aren’t included in most package managers, except for Homebrew in Mac systems. They should be available, however, in the <a href="https://kafka.apache.org/downloads" target="_blank" rel="noreferrer noopener">official download page</a>. For Unix systems (Mac, Linux, WSL, *BSD), simply get one of the binary downloads and extract it wherever you prefer. Then, make sure to add the bin folder to your $PATH, so that you can use these scripts in any folder. In my case, I put the extracted archive in $HOME/.local/share/kafka, so I edit my .zshrc (or .bashrc in a plainer Linux/WSL system) and add:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
export PATH=$HOME/.local/share/kafka/bin:$PATH
</pre></div>


<p><br>Now we can use the official kafka scripts in any directory. That is, unless we have some form of authentication. We can add additional configs to a file somewhere, and include that file in our commands. Let’s put a file called <code>dev.cfg</code> in <code>$HOME/.config/kafka/</code> (the exact directory doesn’t matter, but .config is the appropriate directory for configs), and write the following on it:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
    username=&quot;me&quot; \
    password=&quot;noneofyourbusiness&quot;;
</pre></div>


<p>This is just an example, your broker&#8217;s security config may vary. After doing this, just add to any of the Kafka commands you use:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
--command-config $HOME/.config/kafka/dev.cfg
</pre></div>


<h2 class="wp-block-heading">Checking consumer offsets</h2>



<p>Before migrating topics, it&#8217;s best if we make sure that the old topic consumer is totally up-to-date. We can use this command to check the consumption lag:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
kafka-consumer-groups.sh \
	--bootstrap-server=&#039;&lt;your broker endpoints, separated by commas&gt;&#039; \
	--describe \
	--group=&#039;&lt;your consumer group&gt;&#039;

</pre></div>


<p>This should yield something like the output below:</p>



<pre class="wp-block-code"><code>TOPIC      PARTITION   NEWEST_OFFSET   OLDEST_OFFSET     CONSUMER_OFFSET     LEAD         LAG
your-topic 0           30000000        0                 30000000            30000000     0
your-topic 1           23900000        0                 23900000            23900000     0

CLIENT_HOST      CLIENT_ID         TOPIC          ASSIGNED_PARTITIONS
/128.0.0.0       your-consumer     your-topic     0
/128.0.0.1     	 your-consumer     your-topic     1</code></pre>



<p>From this we can see that there is zero lag, since the newest offset is equal to the consumer offset on both partitions. We can also see that our consumers are still running (they&#8217;re the clients with ID &#8220;your-consumer&#8221;).</p>



<h2 class="wp-block-heading">Performing the Kafka consumer migration</h2>



<p>Before switching topics or brokers, we should first create a consumer group for the new configuration. This will allow us to change the offsets <em>before</em> beginning the message consumption proper. The easiest way to do this is to use <a href="https://github.com/edenhill/kcat"><code>kcat</code></a>, a simple command-line tool that allows us to consume and produce Kafka messages. To create a consumer group, you must consume messages, so it&#8217;s a matter of setting up <code>kcat</code> (check the install guide on the kcat repo) and consuming a few messages from the new topic:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
kcat \
	-C \
	-b &#039;&lt;your brokers&gt;&#039; \
	-t new-topic \
	-G new-consumer-group

# If you have authentication, just add: 

	-X security.protocol=SASL_SSL \
	-X sasl.mechanisms=SCRAM-SHA-512 \
	-X sasl.username=&quot;me&quot; \
	-X sasl.password=&quot;noneofyourbusiness&quot;

</pre></div>


<p>Just run this for a second, check that messages come out, and then run the describe command for the new group:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
kafka-consumer-groups.sh \
	--bootstrap-server=&#039;new-broker&#039; \
	--describe \
	--group=&#039;new-group&#039;


TOPIC     PARTITION   NEWEST_OFFSET   OLDEST_OFFSET     CONSUMER_OFFSET     LEAD         LAG
new-topic 0           12387000        0                 12                  12           12386988
new-topic 1           12360000        0                 38                  38           12359962

CLIENT_HOST      CLIENT_ID         TOPIC          ASSIGNED_PARTITIONS
</pre></div>


<p>We have huge lag here, but that&#8217;s fine, as we&#8217;re going to reset the offsets anyway. Stop the workers consuming from the older topic by whatever means you can and note down the time at which they stopped. We will now reset the consumer group offset for this new group. Just a note: in this case, we don&#8217;t have any consumers connected to this group, but if we did we&#8217;d also have to turn them off. You <strong>cannot</strong> reset a consumer group offset if there are clients connected to it.</p>



<p>To reset the offsets, just run the following command (here we&#8217;ll assume that we stopped the previous consumers at 10:00 of March 15th, 2023, and subtract ten minutes just to be safe):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
kafka-consumer-groups.sh \
	--bootstrap-server=&#039;new-brokers&#039; \
	--group=&#039;new-group&#039; \
	--topic=&#039;new-topic&#039; \
	--reset-offsets \
	--to-datetime 2023-03-15T09:50:00.000 \
	--dry-run
</pre></div>


<p>Running this dry run will not make any changes, It will only show you the new offsets for the consumer group, e.g.:</p>



<pre class="wp-block-code"><code>TOPIC     PARTITION   NEWEST_OFFSET   OLDEST_OFFSET     CONSUMER_OFFSET     LEAD         LAG
new-topic 0           12387000        0                 12386998            12386988     2
new-topic 1           12360000        0                 12369951            12369951     49

CLIENT_HOST      CLIENT_ID         TOPIC          ASSIGNED_PARTITIONS</code></pre>



<p>If nothing looks strange to you, go ahead, substitute <code>--dry-run</code> with <code>--execute</code> and run the command. Afterwards, deploy the new consumer configuration, turn on the worker, and let it run.</p>
<p>The post <a href="https://blogit.create.pt/joaorafael/2023/03/15/kafka-consumer-broker-migration-aws-msk/">Performing broker migrations on your Kafka consumers</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/joaorafael/2023/03/15/kafka-consumer-broker-migration-aws-msk/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The future of dynamic color palettes in CSS</title>
		<link>https://blogit.create.pt/pedrolopes/2022/05/25/the-future-of-dynamic-color-palettes-in-css/</link>
					<comments>https://blogit.create.pt/pedrolopes/2022/05/25/the-future-of-dynamic-color-palettes-in-css/#respond</comments>
		
		<dc:creator><![CDATA[Pedro Lopes]]></dc:creator>
		<pubDate>Wed, 25 May 2022 14:58:49 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12707</guid>

					<description><![CDATA[<p>When you have a theme based on a color picked by your users, it can be hard to find intermediate values for things like hover and active states, or even colors that look or contrast well together. There are currently some convoluted ways of doing this, using CSS filters to change brightness or contrast, or [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2022/05/25/the-future-of-dynamic-color-palettes-in-css/">The future of dynamic color palettes in CSS</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When you have a theme based on a color picked by your users, it can be hard to find intermediate values for things like hover and active states, or even colors that look or contrast well together.</p>



<p>There are currently some convoluted ways of doing this, using <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/filter">CSS filters</a> to change brightness or contrast, or <a href="https://developer.epages.com/blog/coding/css-can-do-that-color-manipulation-for-the-fearless/">using CSS variables to separate each of the color’s values and use the calc function to manipulate them</a>.</p>



<p>With the <a href="https://www.w3.org/TR/css-color-5">CSS Color Module Level 5</a>, there are some great new features that will make this manipulation much easier to achieve.</p>



<p>Keep in mind, these features are not yet widely supported by browsers, being either experimental or hidden behind flags. Hopefully, these will start to roll out during this year.</p>



<h2 class="wp-block-heading">Color spaces</h2>



<p>Before getting into color manipulation, one other feature that will improve the results of dynamic color palettes are <strong>color spaces</strong>.</p>



<p>Color spaces essentially determine how colors are defined and how they can be represented. The <a href="https://www.w3.org/TR/css-color-4/">CSS Color 4</a> introduces a bunch of ways to define colors, one of them being <strong>Lightness Chroma Hue</strong> (LCH). LCH introduces many improvements over RGB, such as more colors and more uniformity. For more detail on this, I recommend Lea Verou’s blog post <a href="https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/">“LCH colors in CSS: what, why, and how?”</a>.</p>



<h2 class="wp-block-heading">Color mix</h2>



<p>The <code>color-mix</code> function lets us mix two colors with a given weight to each. You can mix the theme color with white or black to make it lighter or darker, or mix it with the secondary color to get interpolated values between them.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
color: color-mix(in srgb, var(--primary-color) 70%, white);
color: color-mix(in srgb, var(--primary-color) 70%, black);
color: color-mix(in lch, var(--primary-color), var(--secondary-color));
</pre></div>


<p><strong>Resources:</strong></p>



<ul class="wp-block-list"><li><a href="https://www.w3.org/TR/css-color-5/#color-mix">CSS Color 5 &#8211; color-mix</a></li><li><a href="https://caniuse.com/mdn-css_types_color_color-mix">Can I Use &#8211; color-mix</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix">MDN &#8211; color-mix</a></li></ul>



<h2 class="wp-block-heading">Relative colors</h2>



<p>With relative colors, you can define color values based on a given color, and change the individual values that make up that given color. Remember the approach I mentioned above that separates each of the color’s components into a CSS variable? This <a href="https://blog.jim-nielsen.com/2021/css-relative-colors/">blog post by Jim Nielsen</a> compares the two approaches.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
// Reduce the primary color transparency
color: rgb(from var(--primary-color) r g b / 80%);

// Reduce the lightness using the LCH color space
color: lch(from var(--primary-color) calc(l / 2) c h);
</pre></div>


<p><strong>Resources:</strong></p>



<ul class="wp-block-list"><li><a href="https://www.w3.org/TR/css-color-5/#relative-colors">CSS Color 5 &#8211; relative colors</a></li></ul>



<h2 class="wp-block-heading">Color contrast</h2>



<p>With the <code>color-contrast</code> function, we can let the browser automatically determine a color that contrasts with a given color and matches accessibility requirements.</p>



<p>At its simplest, the function receives a color value (typically the background color) and returns either white or black, depending on which has better contrast.</p>



<p>If you want custom contrast colors instead of black or white, you can provide a list of colors to pick from (using the <code>vs</code> keyword), and the color with the highest contrast will be chosen. As a backup, you can define a contrast target (using the <code>to</code> keyword) and if no color matches that contrast, white or black will be picked. The contrast target can be given as a number or as a level from WCAG (AA, AA-large, AAA, and AAA-large).</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
// Chooses black or white based on which has better contrast
color: color-contrast(var(--bg-color));

// Chooses a contrasting color from a given list (after the &quot;vs&quot;), that result in  a contrast level of at least AA. If none match, picks white or black
color: color-contrast(
	var(--bg-color)
	vs
	var(--text-color),
	var(--text-color--light),
	var(--text-color--lightest),
	to AA
);
</pre></div>


<p><strong>Resources:</strong></p>



<ul class="wp-block-list"><li><a href="https://www.w3.org/TR/css-color-5/#colorcontrast">CSS Color 5 &#8211; color-contrast</a></li><li><a href="https://caniuse.com/mdn-css_types_color_color-contrast">Can I Use &#8211; color-contrast</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-contrast">MDN &#8211; color-contrast</a></li></ul>



<h2 class="wp-block-heading">Conclusion</h2>



<p>The future is looking bright for dynamic color themes in CSS. We will soon be able to move away from convoluted hacks and start using native functions.</p>



<p>Do you find these color features useful? How do you get around this currently? Do you know of any other features that you think help with this topic? Leave a comment or reach out to me on Twitter <a href="https://twitter.com/pedronavelopes" target="_blank" rel="noreferrer noopener">@pedronavelopes</a>.</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2022/05/25/the-future-of-dynamic-color-palettes-in-css/">The future of dynamic color palettes in CSS</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/pedrolopes/2022/05/25/the-future-of-dynamic-color-palettes-in-css/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Handling not found routes in Angular</title>
		<link>https://blogit.create.pt/pedrolopes/2022/05/05/handling-not-found-routes-in-angular/</link>
					<comments>https://blogit.create.pt/pedrolopes/2022/05/05/handling-not-found-routes-in-angular/#respond</comments>
		
		<dc:creator><![CDATA[Pedro Lopes]]></dc:creator>
		<pubDate>Thu, 05 May 2022 11:31:15 +0000</pubDate>
				<category><![CDATA[Angular]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[404]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12669</guid>

					<description><![CDATA[<p>In this post, we will see how we can handle 404 routes using a not found component in an Angular. There are two types of 404 routes that we want to handle. Static 404 &#8211; the URL the user navigates to doesn&#8217;t match any route Dynamic 404 &#8211; the URL matches a route, but the [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2022/05/05/handling-not-found-routes-in-angular/">Handling not found routes in Angular</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In this post, we will see how we can handle 404 routes using a not found component in an Angular.</p>



<p>There are two types of 404 routes that we want to handle.</p>



<ul class="wp-block-list"><li><strong>Static 404</strong> &#8211; the URL the user navigates to doesn&#8217;t match any route</li><li><strong>Dynamic 404</strong> &#8211; the URL matches a route, but the data associated with that route does not exist. For example, you navigate to a detail page with an ID, but no item exists with that ID.</li></ul>



<p>For this post, I assume that there is a component named <code>NotFoundComponent</code> that is the not found page to show the user. Replace this with whatever component</p>



<h2 class="wp-block-heading">Static 404 routes</h2>



<p>To set up a static 404 page, you need to add two routes to your <code>RoutingModule</code> configuration.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const routes: Routes = &#x5B;
    // Other routes
    { path: &#039;404&#039;, component: NotFoundComponent },
    { path: &#039;**&#039;, component: NotFoundComponent }
]
</pre></div>


<p>We used a catchall route <code><em>'</em>**'</code> that matches whatever route didn&#8217;t match above, and shows our not found page.</p>



<p>Make sure to keep the catchall route at the end of your routes, otherwise the routes below it will not be accessible.</p>



<p>Another option here would&#8217;ve been to redirect the user to the <code>'404'</code> route, but that way you lose the context of the URL. If the user navigates back, he would go to the non-existing route and be redirected to the <code>'404'</code> path again. If this is the behavior you want, switch the last route with <code>{ path: '**', redirectTo: '404' }</code>.</p>



<h2 class="wp-block-heading">Dynamic 404 routes</h2>



<p>Now that we have the static 404 route configured, we can use the router to navigate to it whenever we want to show the not found page to the user.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
this.router.navigate(&#x5B;&#039;/404&#039;], { skipLocationChange: true });
</pre></div>


<p>By using the option <code>skipLocationChange: true</code>, we have the same behavior as mentioned above. Even though the router navigates to the route, the browser URL stays the same, allowing the user to easily go back.</p>



<h3 class="wp-block-heading">Personalizing the 404 message</h3>



<p>You may want to personalize the message shown on the 404 page. One way to do this is using the navigation state.</p>



<p>When navigating to the 404 page, you can include a <code>state</code> in the navigation options.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
this.router.navigate(&#x5B;&#039;/404&#039;], { 
    skipLocationChange: true,
    state: {
        // Whatever data you need on the 404 page
    	source: &#039;article&#039;,
        id: 123456
    }
});
</pre></div>


<p>On your <code>NotFoundComponent</code>, you can access this object in the constructor using the router&#8217;s <a href="https://angular.io/api/router/Router#getcurrentnavigation"><code>getCurrentNavigation</code></a> method.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
export class NotFoundComponent {
  constructor(private router: Router) {
    console.log(this.router.getCurrentNavigation().extras.state.source);
  }
}
</pre></div>


<p>You must access the state in the constructor, as it is only available while the router is navigating.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>In this post, we saw how to implement a 404 route in Angular. We looked at how we can redirect to it dynamically and even how to personalize the 404 page with route dependent data!</p>



<p>Have questions, corrections, or an alternative way of handling this? Leave a comment or reach out to me on Twitter <a href="https://twitter.com/pedronavelopes">@pedronavelopes</a> and let me know! Thanks for reading!</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2022/05/05/handling-not-found-routes-in-angular/">Handling not found routes in Angular</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/pedrolopes/2022/05/05/handling-not-found-routes-in-angular/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CSS Scroll Shadows</title>
		<link>https://blogit.create.pt/pedrolopes/2022/03/24/css-scroll-shadows/</link>
					<comments>https://blogit.create.pt/pedrolopes/2022/03/24/css-scroll-shadows/#respond</comments>
		
		<dc:creator><![CDATA[Pedro Lopes]]></dc:creator>
		<pubDate>Thu, 24 Mar 2022 13:52:04 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[FrontEnd Development]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12643</guid>

					<description><![CDATA[<p>Nowadays, it&#8217;s crucial that your webpages are responsive. The problem we sometimes run into, is the fact that some components don&#8217;t adapt well into mobile. In this post, we&#8217;ll look at a way to make scrollable components more intuitive on mobile devices using CSS scroll shadows. Let&#8217;s think of a table. It&#8217;s a collection of [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2022/03/24/css-scroll-shadows/">CSS Scroll Shadows</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Nowadays, it&#8217;s crucial that your webpages are responsive. The problem we sometimes run into, is the fact that some components don&#8217;t adapt well into mobile.</p>



<p>In this post, we&#8217;ll look at a way to make scrollable components more intuitive on mobile devices using CSS scroll shadows.</p>



<p>Let&#8217;s think of a table. It&#8217;s a collection of rows with columned data. One way to make a table responsive is by collapsing each row into a card. This will, however, remove the link between rows for any given column.</p>



<p>An alternative is to make the table scroll horizontally. This gives your data space to breathe and maintains the link given by columns. All done and pretty easy, right? Well, you might run into this problem:</p>



<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://digitalpress.fra1.cdn.digitaloceanspaces.com/c8lrmyd/2022/03/table-no-shadow.png" alt="Column of items without an indication that there is more content to the right" /></figure></div>



<p>If your column width happens to match the width of the table element, your users will have no idea that there is extra content to the side.</p>



<h2 class="wp-block-heading">Adding Shadows</h2>



<p>One way to fix this is by using scroll shadows. A scroll shadow is a shadow applied at the border of the element when there is the possibility of scrolling. That same example with a scroll shadow might look like this:</p>



<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://digitalpress.fra1.cdn.digitaloceanspaces.com/c8lrmyd/2022/03/ScrollShadowsExample.png" alt="3 tables are shown using css scroll shadows. On the left, the table is showing the first column and there is a shadow on the right but not on the left. In the middle, there is a column with shadows on both side. On the right is the last column of the table, showing a shadow on the left but not on the right." /><figcaption>Different scroll positions for the same element using CSS scroll shadows</figcaption></figure></div>



<p>As you can see, the shadow is only visible when there is space to scroll. There are many ways to do this, I&#8217;m going to show you a way that only uses CSS.</p>



<p>First, we start by adding the shadows with two radial gradients.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
.scroll-shadows-h {
  background:
    radial-gradient(farthest-side at 0 50%, rgba(0,0,0,0.4), rgba(0,0,0,0)),
    radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,0.4), rgba(0,0,0,0)) 100% 0;
  background-repeat: no-repeat;
  background-size: 14px 100%, 14px 100%;
}
</pre></div>


<div class="wp-block-image"><figure class="aligncenter size-full"><img decoding="async" width="214" height="313" src="https://blogit.create.pt/wp-content/uploads/2022/03/imagem.png" alt="" class="wp-image-12651" srcset="https://blogit.create.pt/wp-content/uploads/2022/03/imagem.png 214w, https://blogit.create.pt/wp-content/uploads/2022/03/imagem-205x300.png 205w" sizes="(max-width: 214px) 100vw, 214px" /></figure></div>



<h2 class="wp-block-heading">Hiding the shadows</h2>



<p>This results in the shadows being visible even when there isn&#8217;t space to scroll. To fix this, we add shadow covers that hide the shadows at the beginning and end of the element, instead of its viewport.</p>



<p>We can implement this using the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment">background-attachment</a> property. To quote the MDN, &#8220;The <code>background-attachment</code> CSS property sets whether a background image&#8217;s position is fixed within the viewport, or scrolls with its containing block&#8221;.</p>



<p>Setting the <code>background-attachment</code> of the shadow covers to <code>local</code>, means that they are fixed relative to the content of the element. When we scroll inside the element, the background scrolls as well.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
.scroll-shadows-h {
  background:
    /* Shadow covers */
    linear-gradient(to right, #fff 30%, rgba(255,255,255,0)),
    linear-gradient(to right, rgba(255,255,255,0), #fff 70%) 100% 0,
   
    /* Shadows */
    radial-gradient(farthest-side at 0 50%, rgba(0,0,0,0.4), rgba(0,0,0,0)),
    radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,0.4), rgba(0,0,0,0)) 100% 0;
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
</pre></div>


<p>This class is the class used in the example in the image above. The cool thing about this implementation is that it&#8217;s very versatile. We can apply it vertically or use any background we want to. You could replace the shadows with an image (e.g. an arrow) and this effect would still work, as the covers will continue to overlap it. Check the <a href="https://codepen.io/pedronave/pen/ZEvpwZP">CodePen below</a> for some examples!</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-codepen wp-block-embed-codepen"><div class="wp-block-embed__wrapper">
<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" title="CSS Scroll Shadows" src="https://codepen.io/pedronave/embed/preview/ZEvpwZP?default-tabs=html%2Cresult&#038;height=300&#038;host=https%3A%2F%2Fcodepen.io&#038;slug-hash=ZEvpwZP#?secret=NySH3eOTBD" data-secret="NySH3eOTBD" scrolling="no" frameborder="0" height="300"></iframe>
</div></figure>



<p>Thanks for reading! Do you find this useful? Do you think there are better ways to achieve this effect? Let me know in the comments below, or reach out to me on Twitter <a href="https://twitter.com/pedronavelopes">@pedronavelopes</a>!</p>



<p>This blog post was inspired by Lea Verou&#8217;s post &#8220;<a href="https://lea.verou.me/2012/04/background-attachment-local/"><em>Pure CSS scrolling shadows with background-attachment: local</em></a>&#8220;. Go check it out!</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2022/03/24/css-scroll-shadows/">CSS Scroll Shadows</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/pedrolopes/2022/03/24/css-scroll-shadows/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET EF Core 6 support for groupby top(n) queries</title>
		<link>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/</link>
					<comments>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/#respond</comments>
		
		<dc:creator><![CDATA[Telmo Rodrigues]]></dc:creator>
		<pubDate>Fri, 04 Feb 2022 16:14:46 +0000</pubDate>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Sql]]></category>
		<category><![CDATA[entity framework]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12605</guid>

					<description><![CDATA[<p>EF Core 6 comes with some GroupBy queries improvements. In this post I wanna talk about the improvements related to &#8220;group by top(n)&#8221; queries. Let&#8217;s say we have the following table Documents: and that we want to get the two most recent documents for each user. For instance, if we have the following records: the [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/">.NET EF Core 6 support for groupby top(n) queries</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>EF Core 6 comes with some GroupBy queries improvements. In this post I wanna talk about the improvements related to &#8220;group by top(n)&#8221; queries.</p>



<p></p>



<p></p>



<p>Let&#8217;s say we have the following table Documents:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CREATE TABLE &#x5B;dbo].&#x5B;Documents](
    &#x5B;Id] &#x5B;integer] PRIMARY KEY,
    &#x5B;UserId] &#x5B;integer] NOT NULL,
    &#x5B;Title] &#x5B;nvarchar](50) NOT NULL,
    &#x5B;Body] &#x5B;nvarchar](250) NOT NULL,
    &#x5B;CreatedOn] &#x5B;datetime] NOT NULL
)
</pre></div>


<p>and that we want to get the two most recent documents for each user. For instance, if we have the following records:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2022/02/image-6.png" alt="" class="wp-image-12606" width="523" height="183" srcset="https://blogit.create.pt/wp-content/uploads/2022/02/image-6.png 523w, https://blogit.create.pt/wp-content/uploads/2022/02/image-6-300x105.png 300w" sizes="(max-width: 523px) 100vw, 523px" /></figure>



<p>the query should return</p>



<figure class="wp-block-image size-full"><img decoding="async" width="520" height="146" src="https://blogit.create.pt/wp-content/uploads/2022/02/image-7.png" alt="" class="wp-image-12607" srcset="https://blogit.create.pt/wp-content/uploads/2022/02/image-7.png 520w, https://blogit.create.pt/wp-content/uploads/2022/02/image-7-300x84.png 300w" sizes="(max-width: 520px) 100vw, 520px" /></figure>



<p>To do this query using EF Core and LINQ we can try to group the Documents by UserId and then sort each group by the CreatedOn column to pick the first two documents for each user.</p>



<p>We can start by trying to group all documents for each user</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
 var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
</pre></div>


<p>and then for each group we try to sort its elements by the CreatedOn column</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
        .SelectMany(userDocs =&gt; userDocs.OrderByDescending(doc =&gt; doc.CreatedOn).Take(2))
        .ToArrayAsync();
</pre></div>


<p>If we try to execute this query using a previous version of EF Core 6 we get the following error:</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
    .OrderByDescending(doc =&amp;gt; doc.CreatedOn)&#039; could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to &#039;AsEnumerable&#039;, &#039;AsAsyncEnumerable&#039;, &#039;ToList&#039;, or &#039;ToListAsync&#039;. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.&#039;
</pre></div>


<p></p>



<p>This is because the previous versions of EF don&#8217;t know how to translate the GroupBy inner expressions to sql. After following their suggestion I ended up with this query</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .Select(doc =&gt; doc.UserId)
        .Distinct()
        .SelectMany(userId =&gt; 
            ctx
            .Documents
            .Where(doc =&gt; doc.UserId == userId)
            .OrderByDescending(doc =&gt; doc.CreatedOn)
            .Take(2)
        )
        .ToArrayAsync();
</pre></div>


<p>However this query has two main issues. It does a distinct over the UserId column, loads all the user ids to application memory and then it does a query for each user resulting in a n+1 query problem.</p>



<p>One way to solve these issues is to forget LINQ and rewrite the query using raw sql with a partition by UserId and the ROW_NUMBER() window funtion, doing a CTE .</p>



<p>Now, with the EF Core 6 we can use the first version of the query, since the EF Core team has added the support for translating some GroupBy inner expressions and it can translate this LINQ query to a single sql query.</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
        .SelectMany(userDocs =&gt; userDocs.OrderByDescending(doc =&gt; doc.CreatedOn).Take(2))
        .ToArrayAsync();
</pre></div>


<p>You can read more about these features and other improvements added to GroupBy queries&nbsp;<a href="https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/whatsnew#improved-groupby-support">here</a>&nbsp;and check the related github issues&nbsp;<a href="https://github.com/dotnet/efcore/issues/12088">12088</a>&nbsp;<a href="https://github.com/dotnet/efcore/issues/13805">13805</a>&nbsp;</p>



<p>Happy coding!</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/">.NET EF Core 6 support for groupby top(n) queries</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>10 easy ways to improve web accessibility</title>
		<link>https://blogit.create.pt/pedrolopes/2021/09/10/10-easy-ways-to-improve-web-accessibility/</link>
					<comments>https://blogit.create.pt/pedrolopes/2021/09/10/10-easy-ways-to-improve-web-accessibility/#respond</comments>
		
		<dc:creator><![CDATA[Pedro Lopes]]></dc:creator>
		<pubDate>Fri, 10 Sep 2021 12:37:40 +0000</pubDate>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FrontEnd Development]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12548</guid>

					<description><![CDATA[<p>When you first start learning about accessibility, it may seem daunting to make your current projects more accessible. In this post, I&#8217;ll give you some easy steps to make this process a bit easier. I would like you to keep in mind that this will not make your website fully accessible, it&#8217;s just an easy [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2021/09/10/10-easy-ways-to-improve-web-accessibility/">10 easy ways to improve web accessibility</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When you first start learning about accessibility, it may seem daunting to make your current projects more accessible. In this post, I&#8217;ll give you some easy steps to make this process a bit easier.</p>



<p>I would like you to keep in mind that this will not make your website fully accessible, it&#8217;s just an easy way to vastly improve accessibility.</p>



<h2 class="wp-block-heading">1 &#8211; Follow WCAG and WebAIM checklist</h2>



<p>The WCAG (Web Content Accessibility Guidelines) is a set of guidelines on how the web can be made more accessible. It takes 4 principles into consideration:</p>



<ol class="wp-block-list"><li>Perceivable &#8211; Just because something is perceivable with one sense (usually sight), not all users can perceive it</li><li>Operable &#8211; Can users use UI components and navigate the content. For example, hover interactions can&#8217;t be operated by someone without a mouse</li><li>Understandable &#8211; Can all users understand the content</li><li>Robust &#8211; Is it robust enough for the content to be consumed by a wide variety of user agents, and does it work with accessibility tools.</li></ol>



<p>The <a href="https://webaim.org/standards/wcag/checklist" target="_blank" rel="noreferrer noopener">WebAIM Checklist</a> was created from these guidelines and simplified the implementation of these principles. This checklist should be seen as a companion to start implementing accessible interfaces, not as the final resource on what make a website accessible.</p>



<h2 class="wp-block-heading">2 &#8211; Provide alternatives to non-text content</h2>



<p>Non-sighted users may have a hard time taking in non-text content, as such, <a href="https://www.w3.org/TR/WCAG21/#non-text-content">it&#8217;s important to provide alternatives to these</a>.</p>



<ul class="wp-block-list"><li>Provide alt text for images The alt text should be an alternative to the image content<ul><li>If an image is not relevant for the context, you can hide it from screen readers by providing an empty alt text.</li></ul></li><li>Use aria-label for other elements<ul><li>The aria-label lets you label elements for screen readers</li></ul></li></ul>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
// 👎 No descriptive alt text
&lt;img src=&quot;puppy.jpg&quot;&gt;

// 👍 Descriptive alt text
&lt;img src=&quot;puppy.jpg&quot; alt=&quot;Labrador puppy running in the grass&quot;&gt;

// 👍 Empty alt text excludes the image that isn&#039;t relevant
&lt;button&gt;
	&lt;img src=&quot;home-icon.jpg&quot; alt=&quot;&quot;&gt;
	Home
&lt;/button&gt;
</pre></div>


<h2 class="wp-block-heading">3 &#8211; Use native and semantic elements</h2>



<p>When implementing an HTML page, try to <a href="https://www.w3.org/TR/WCAG21/#info-and-relationships">use native and semantic elements</a>.</p>



<p>If you need a button, you should use a &lt;button&gt; element, not a div with an onclick event or an anchor link.</p>



<p>This is the case because different elements mean different things, and have different behaviors. By using the native HTML elements, we know it will have the expected behavior. And by using a semantic element, we ensure that the user understands what the element will do, as in, a button will trigger an action, and a link will trigger a navigation to somewhere else.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
// 👎 Non-semantic element
&lt;div class=&quot;button&quot; click=&quot;onclick&quot;&gt;
	Click me!
&lt;/div&gt;

// 👍 Semantic element
&lt;button click=&quot;onclick&quot;&gt;
	Click me!
&lt;/button&gt;
</pre></div>


<h2 class="wp-block-heading">4 &#8211; Use ARIA attributes in elements</h2>



<p>When there is no native element which matches your need, you may have to implement it yourself.</p>



<p>To make sure the element you are implementing is accessible, you should use ARIA (Accessible Rich Internet Applications) attributes.</p>



<p>These will allow you to add semantics to elements which have no meaning, modify existing semantics, add extra labels and descriptions, express relationships between elements, etc.</p>



<p>The <a href="https://www.w3.org/TR/wai-aria-practices-1.1/">ARIA practices document</a> specifies the patterns that each element should have. When implementing an element, you give it a role and commit to following all the patterns and interactions defined in the ARIA practices.</p>



<h2 class="wp-block-heading">5 &#8211; Understand focus and tab order</h2>



<p>Tab order refers to the order in which the items on a page will be focused using the keyboard.</p>



<p>Some elements are implicitly focusable (such as inputs, buttons and links), and are added to the tab order automatically.</p>



<p>The tab order is determined by the <strong>DOM order,</strong> but this can be different from the <strong>visual order</strong> which can be changed by CSS. Therefore, <a href="https://www.w3.org/TR/WCAG21/#focus-order">you should make sure that the reading and navigation order are logical and intuitive</a>.</p>



<p>To change the tab order, you can use the tab index attribute:</p>



<ul class="wp-block-list"><li>-1<ul><li>Removes the element from the natural tab order, but it is focusable through code.</li><li>Useful when we have hidden elements (such as modals) which should not be focusable when hidden</li></ul></li><li>0<ul><li>Adds the element to the natural tab order.</li><li>Allows elements to be focused and receive keyboard input.</li></ul></li><li>0<ul><li>Jumps element to the front of the tab order</li><li>If there are multiple elements, order goes from lowest to highest</li><li><strong>This is discouraged</strong> because it can make it confusing for screen readers, as they navigate the page linearly</li></ul></li></ul>



<p><strong><a href="https://www.w3.org/TR/WCAG21/#focus-visible">Make sure you have a focus ring</a>.</strong> A focus ring lets users know which element is focused. This is essential for keyboard users.</p>



<h2 class="wp-block-heading">6 &#8211; Bypass Blocks</h2>



<p>If your page has a lot of navigation links, a keyboard user will have to tab through all these links before being able to reach the main content. To make your website more convenient to use, you can provide users with a <a href="https://webaim.org/techniques/skipnav/">skip link</a>.</p>



<p>The skip link will be the first focusable element on the page and links the user to the main content, skipping the focus to it directly.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
&lt;body&gt;
  &lt;a href=&quot;#maincontent&quot;&gt;Skip to main content&lt;/a&gt;
  &lt;!-- Navigation links ---&gt;
  &lt;main id=&quot;maincontent&quot;&gt;
    &lt;h1&gt;Heading&lt;/h1&gt;
    &lt;p&gt;This is the first paragraph&lt;/p&gt;
  &lt;/main&gt;
&lt;/body&gt;
</pre></div>


<p>To make sure the skip link doesn&#8217;t affect your page, you can hide it until it is focused, meaning only keyboard users will see it.</p>



<p>Alternatively to skip links, if you provide a proper <strong>heading structure</strong>, screen readers will also be able to skip around the page and navigate to each section much more easily. This will, however, not provide a skip mechanism for users who just use the keyboard to navigate.</p>



<h2 class="wp-block-heading">7 &#8211; Use ARIA attributes in CSS selectors</h2>



<p>You can use ARIA attributes in your CSS selectors. This makes sure that ARIA is being used correctly, and removes the need for additional selectors.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
// 👎 Aditional selector
.toggle.pressed

// 👍 ARIA attributes
.toggle&#x5B;aria-pressed=&quot;true&quot;]
</pre></div>


<h2 class="wp-block-heading">8 &#8211; Responsive design</h2>



<p>Even if you don&#8217;t need to implement mobile designs, a responsive design ensures that the user can zoom in the page and the content adjusts properly. <a href="https://www.w3.org/TR/WCAG21/#resize-text">Your page should be zoomable up to 200% without losing content or functionality.</a></p>



<ul class="wp-block-list"><li>Use relative font-size, allowing the browser to rescale the text</li><li>Use appropriate touch targets (&gt;48px) so users have enough space to touch a single button</li><li>Space touch targets about 32px from each other</li></ul>



<h2 class="wp-block-heading">9 &#8211; Color and Contrast</h2>



<p><a href="https://webaim.org/resources/contrastchecker/">There are tools which allow you to easily check for contrast</a>. Some browsers even let you check this directly in the dev tools.</p>



<p>You also have to keep in mind that some users will not be able to distinguish some colors. As such, <strong><a href="https://www.w3.org/TR/WCAG21/#use-of-color">information should not be conveyed by color alone</a>.</strong> Make sure you add other elements (such as captions or icons) to indicate the state of the elements.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img decoding="async" width="671" height="170" src="https://blogit.create.pt/wp-content/uploads/2021/09/Compare-colorblind2.png" alt="On the left, two form fields using green and red to convey their status. On the right, a view of the same forms is shown, simulating red/green color blindness. Both these fields are the same color." class="wp-image-12551" srcset="https://blogit.create.pt/wp-content/uploads/2021/09/Compare-colorblind2.png 671w, https://blogit.create.pt/wp-content/uploads/2021/09/Compare-colorblind2-300x76.png 300w" sizes="(max-width: 671px) 100vw, 671px" /><figcaption>Comparison of interface using only color as a state indicator. Colorblind people will not be able to distinguish these colors</figcaption></figure></div>



<h2 class="wp-block-heading">10 &#8211; How to apply these tips</h2>



<p>Good accessibility ensures good UX. As such, accessibility should be focused from the beginning of development.</p>



<p>When this doesn&#8217;t happen, we inevitably have to fix accessibility issues later. You can identify some issues using the following techniques:</p>



<ul class="wp-block-list"><li>Use the accessibility inspector included in the browser</li><li>Navigate through your website using only a keyboard</li><li>Simulate impaired vision through browser extensions (e.g. <a href="https://addons.mozilla.org/en-US/firefox/addon/nocoffee/">NoCoffee</a>)</li></ul>



<p>After identifying some issues, how should we tackle them? As with bugs, we should focus on high impact, low effort issues.</p>



<ul class="wp-block-list"><li>How frequently is this piece of UI used?</li><li>How badly does this affect our users?</li><li>How expensive is it to fix?</li></ul>



<h2 class="wp-block-heading">Conclusion</h2>



<p>Accessibility is starting to make it to the front of developer concerns. With more popularity come more resources to help us develop better interfaces and experiences for all users.</p>



<p>Hopefully, this article provided you with an initial idea on how to approach web accessibility.</p>
<p>The post <a href="https://blogit.create.pt/pedrolopes/2021/09/10/10-easy-ways-to-improve-web-accessibility/">10 easy ways to improve web accessibility</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/pedrolopes/2021/09/10/10-easy-ways-to-improve-web-accessibility/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Collaborative work, why and how?</title>
		<link>https://blogit.create.pt/goncalomelo/2021/05/10/collaborative-work-why-and-how/</link>
					<comments>https://blogit.create.pt/goncalomelo/2021/05/10/collaborative-work-why-and-how/#respond</comments>
		
		<dc:creator><![CDATA[Gonçalo Melo]]></dc:creator>
		<pubDate>Mon, 10 May 2021 16:00:32 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Coollaboration]]></category>
		<category><![CDATA[Ideas]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12273</guid>

					<description><![CDATA[<p>The work of a collaborative team allows to produce work that is more than the sum of the individual contributions of the team members. Yes, it is important!</p>
<p>The post <a href="https://blogit.create.pt/goncalomelo/2021/05/10/collaborative-work-why-and-how/">Collaborative work, why and how?</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>The work of a collaborative team allows to produce work that is more than the sum of the individual contributions of the team members. Yes, it is important!</p>



<h2 class="wp-block-heading" id="b89a"><strong>How do we know collaboration is happening?</strong></h2>



<p id="83a4">My reflection results from one recent team experience, in a software development context. We worked collaboratively to implement a new feature and after a work session two things about the final result called my attention:</p>



<p id="15b4">1. It was not possible to identify the “owner” of the idea. Everyone said something that contributed to the work produced. It truly belonged to everyone.</p>



<p id="59c9">2. The result we found was better than something I was aware of being able to find.</p>



<p id="2644">It is something I read, heard, and even talked about often. But for me it was good to be able to experience and learn in practice. There are few things that replace practice.</p>



<p id="d9ac">This is basic, it is. I knew that. But for me it was a special moment to be able to feel this energy. At the same time, I look at this and think “how come we don’t always do this?”.</p>



<h2 class="wp-block-heading" id="4332">How collaboration happens?</h2>



<p id="856b">Some simple and practical actions to improve collaborative work.</p>



<h3 class="wp-block-heading" id="4b84"><strong>Accept all contributions</strong></h3>



<p id="f60f">The brain is very quick to identify reasons for not doing anything. Perhaps it is a hidden survival mechanism. As a result, idle is safer than boiling. This is a common place, on the other hand it is differentiating. The process of building on each other’s ideas is one of the critical factors to generate energy that will keep the work session active.</p>



<h3 class="wp-block-heading" id="8b9d"><strong>Feed the ideas that come up</strong></h3>



<p id="dcf4">Initially denying an idea because we see a point we disagree with inhibits collaboration. In other words, the team must be comfortable sharing. A flow of new ideas when each team member builds and contributes on top of each other’s ideas is fantastic. At the end it is not even possible to identify whose final idea is. There is only “us” in the result.</p>



<h3 class="wp-block-heading" id="46a2"><strong>Desire to discover something new</strong></h3>



<p id="bad3">When we restrict ourselves only to what we know, what we can discover will be limited. Dismantle pre-conceived ideas, especially our own. Being open minded to different points of view allows more contributions. It is easy and safe to say no. Take a chance and say why not? Or even better how can we achieve this?</p>



<h2 class="wp-block-heading" id="2ef2">Try It Out</h2>



<p id="55aa">Offer someone the opportunity to share their ideas. These are small but extremely important things, and they are also actionable. They are within everyone&#8217;s reach.</p>
<p>The post <a href="https://blogit.create.pt/goncalomelo/2021/05/10/collaborative-work-why-and-how/">Collaborative work, why and how?</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/goncalomelo/2021/05/10/collaborative-work-why-and-how/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Performance Testing An API, How To Start Doing It With JMeter?</title>
		<link>https://blogit.create.pt/diogocoelho/2021/04/23/performance-testing-an-api-how-to-start-doing-it-with-jmeter/</link>
					<comments>https://blogit.create.pt/diogocoelho/2021/04/23/performance-testing-an-api-how-to-start-doing-it-with-jmeter/#respond</comments>
		
		<dc:creator><![CDATA[Diogo Coelho]]></dc:creator>
		<pubDate>Fri, 23 Apr 2021 16:15:09 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Automatic Testing]]></category>
		<category><![CDATA[JMeter]]></category>
		<category><![CDATA[Performance Test]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12241</guid>

					<description><![CDATA[<p>This article will talk about how to start using JMeter for Testing an API. How to install JMeter, what are the components of it and how to use it. It will, also, show a short introduction of what is performance testing. First&#160;of&#160;all,&#160;let&#8217;s&#160;talk&#160;about&#160;Performance&#160;Testing.&#160;What&#160;is&#160;Performance&#160;Testing? Performance&#160;Testing&#160;is&#160;a&#160;software&#160;testing&#160;process&#160;used&#160;for&#160;testing&#160;the&#160;speed,&#160;response&#160;time,&#160;stability,&#160;reliability,&#160;scalability&#160;and&#160;resource&#160;usage&#160;of&#160;a&#160;software&#160;application&#160;under&#160;a particular&#160;workload.&#160;&#160;The&#160;focus&#160;of&#160;Performance&#160;Testing&#160;is&#160;checking&#160;a&#160;software&#160;program&#8217;s Speed&#160;&#8211;&#160;Determines&#160;whether&#160;the&#160;application&#160;responds&#160;quickly Scalability&#160;&#8211;&#160;Determines&#160;the maximum user load&#160;the&#160;software&#160;application&#160;can&#160;handle. Stability&#160;&#8211;&#160;Determines&#160;if&#160;the&#160;application&#160;is&#160;stable&#160;under&#160;varying&#160;loads What&#160;is&#160;the&#160;Purpose&#160;of&#160;doing&#160;it? The&#160;main&#160;purpose&#160;of&#160;performance&#160;testing&#160;is&#160;to&#160;identify&#160;and&#160;eliminate&#160;the&#160;performance&#160;bottlenecks&#160;in&#160;the&#160;software&#160;application. Now let&#8217;s introduce [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/diogocoelho/2021/04/23/performance-testing-an-api-how-to-start-doing-it-with-jmeter/">Performance Testing An API, How To Start Doing It With JMeter?</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>This article will talk about how to start using JMeter for Testing an API. </p>



<p>How to install JMeter, what are the components of it and how to use it. It will, also, show a short introduction of what is performance testing. </p>



<h2 class="wp-block-heading"><strong>First&nbsp;of&nbsp;all,&nbsp;let&#8217;s&nbsp;talk&nbsp;about&nbsp;Performance&nbsp;Testing.&nbsp;What&nbsp;is&nbsp;Performance&nbsp;Testing?</strong></h2>



<p>Performance&nbsp;Testing&nbsp;is&nbsp;a&nbsp;software&nbsp;testing&nbsp;process&nbsp;used&nbsp;for&nbsp;testing&nbsp;the&nbsp;speed,&nbsp;response&nbsp;time,&nbsp;stability,&nbsp;reliability,&nbsp;scalability&nbsp;and&nbsp;resource&nbsp;usage&nbsp;of&nbsp;a&nbsp;software&nbsp;application&nbsp;under&nbsp;a particular&nbsp;workload.&nbsp;&nbsp;<br>The&nbsp;focus&nbsp;of&nbsp;Performance&nbsp;Testing&nbsp;is&nbsp;checking&nbsp;a&nbsp;software&nbsp;program&#8217;s</p>



<ul class="wp-block-list"><li>Speed&nbsp;&#8211;&nbsp;Determines&nbsp;whether&nbsp;the&nbsp;application&nbsp;responds&nbsp;quickly</li><li>Scalability&nbsp;&#8211;&nbsp;Determines&nbsp;the maximum user load&nbsp;the&nbsp;software&nbsp;application&nbsp;can&nbsp;handle.</li><li>Stability&nbsp;&#8211;&nbsp;Determines&nbsp;if&nbsp;the&nbsp;application&nbsp;is&nbsp;stable&nbsp;under&nbsp;varying&nbsp;loads</li></ul>



<h3 class="wp-block-heading"><strong>What&nbsp;is&nbsp;the&nbsp;Purpose&nbsp;of&nbsp;doing&nbsp;it?</strong></h3>



<p>The&nbsp;main&nbsp;purpose&nbsp;of&nbsp;performance&nbsp;testing&nbsp;is&nbsp;to&nbsp;identify&nbsp;and&nbsp;eliminate&nbsp;the&nbsp;performance&nbsp;bottlenecks&nbsp;in&nbsp;the&nbsp;software&nbsp;application.</p>



<h2 class="wp-block-heading">Now let&#8217;s introduce JMeter</h2>



<h3 class="wp-block-heading">How to install it?</h3>



<p>JMeter&nbsp;is&nbsp;an&nbsp;application&nbsp;base&nbsp;in&nbsp;java.&nbsp;This&nbsp;means,&nbsp;that&nbsp;every&nbsp;computer&nbsp;with&nbsp;java&nbsp;installed&nbsp;can&nbsp;run&nbsp;this&nbsp;application.&nbsp;So&nbsp;let&#8217;s&nbsp;see&nbsp;how&nbsp;to&nbsp;install&nbsp;it.</p>



<h3 class="wp-block-heading">1- Download Java.</h3>



<p>&nbsp;First&nbsp;of&nbsp;all,&nbsp;you&nbsp;will&nbsp;need&nbsp;to&nbsp;install&nbsp;Java&nbsp;on&nbsp;your&nbsp;computer.&nbsp;Here&nbsp;you&nbsp;can&nbsp;download&nbsp;and&nbsp;Install&nbsp;the&nbsp;latest&nbsp;version&nbsp;of&nbsp;Java&nbsp;SE&nbsp;Development&nbsp;Kit <a href="https://www.oracle.com/java/technologies/javase-downloads.html">https://www.oracle.com/java/technologies/javase-downloads.html</a>.</p>



<h3 class="wp-block-heading">2- Download JMeter. </h3>



<p>At&nbsp;the&nbsp;point&nbsp;of&nbsp;writing,&nbsp;the&nbsp;latest&nbsp;version&nbsp;is&nbsp;Apache&nbsp;JMeter&nbsp;5.4.1&nbsp;(Requires&nbsp;Java&nbsp;8+)&nbsp;and&nbsp;you&nbsp;can&nbsp;download&nbsp;it here <a href="http://jmeter.apache.org/download_jmeter.cgi">http://jmeter.apache.org/download_jmeter.cgi</a>. Choose&nbsp;the&nbsp;Binaries&nbsp;file&nbsp;(either&nbsp;apache-jmeter-5.4.1.zip&nbsp;or&nbsp;apache-jmeter-5.4.1.tgz).</p>



<h3 class="wp-block-heading">3- Installation.</h3>



<p>Installing&nbsp;Jmeter&nbsp;is&nbsp;easy!&nbsp;You&nbsp;only&nbsp;need&nbsp;to&nbsp;unzip&nbsp;the&nbsp;file&nbsp;to&nbsp;a&nbsp;directory&nbsp;of&nbsp;your&nbsp;choice&nbsp;and&nbsp;that&#8217;s&nbsp;it!</p>



<h3 class="wp-block-heading">4- Start JMeter </h3>



<p>JMeter can be used in 3 modes. These 3 modes are: </p>



<ol class="wp-block-list"><li>GUI Mode</li><li>Server Mode</li><li>Command Line Mode</li></ol>



<p>In&nbsp;this&nbsp;article,&nbsp;we&nbsp;will&nbsp;focus&nbsp;on&nbsp;<strong>GUI&nbsp;Mode</strong>.&nbsp;So,&nbsp;to&nbsp;start&nbsp;the&nbsp;GUI&nbsp;Mode,&nbsp;you&nbsp;will&nbsp;need&nbsp;to&nbsp;execute&nbsp;the&nbsp;following&nbsp;file&nbsp;<strong>/bin/ApacheJMeter.jar</strong>.&nbsp;This&nbsp;will&nbsp;open&nbsp;the&nbsp;application&nbsp;as&nbsp;the&nbsp;following&nbsp;example.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-1024x560.png" alt="" class="wp-image-12245" width="1070" height="586" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-1024x560.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-300x164.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-768x420.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-1536x840.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-696x381.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen-1068x584.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/AppOpen.png 1920w" sizes="(max-width: 1070px) 100vw, 1070px" /></figure>



<h2 class="wp-block-heading">How to use JMeter?</h2>



<p>Now&nbsp;that&nbsp;we&nbsp;have&nbsp;JMeter&nbsp;installed&nbsp;and&nbsp;running,&nbsp;we&nbsp;need&nbsp;to&nbsp;understand&nbsp;the&nbsp;components&nbsp;that&nbsp;are&nbsp;used&nbsp;to&nbsp;create&nbsp;a&nbsp;Test&nbsp;Plan.</p>



<p>When&nbsp;we&nbsp;open&nbsp;JMeter,&nbsp;we&nbsp;can&nbsp;see&nbsp;that&nbsp;there&nbsp;is&nbsp;already&nbsp;a&nbsp;&#8220;Test&nbsp;Plan&#8221;&nbsp;component.&nbsp;This&nbsp;component&nbsp;is&nbsp;where&nbsp;we&nbsp;add&nbsp;components&nbsp;for&nbsp;our&nbsp;JMeter&nbsp;Test.&nbsp;Here&nbsp;is&nbsp;an&nbsp;image&nbsp;of&nbsp;how&nbsp;these&nbsp;components&nbsp;are&nbsp;organized.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="742" height="290" src="https://blogit.create.pt/wp-content/uploads/2021/04/Jmeter.png" alt="" class="wp-image-12246" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/Jmeter.png 742w, https://blogit.create.pt/wp-content/uploads/2021/04/Jmeter-300x117.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/Jmeter-696x272.png 696w" sizes="(max-width: 742px) 100vw, 742px" /></figure>



<p>The&nbsp;components&nbsp;that&nbsp;we&nbsp;are&nbsp;gonna&nbsp;talk&nbsp;here&nbsp;will&nbsp;be:</p>



<ul class="wp-block-list"><li>Thread Group</li><li>Samplers </li><li>Listeners </li><li>Config Elements</li></ul>



<h4 class="wp-block-heading">Thread Group</h4>



<p>Thread&nbsp;group&nbsp;is&nbsp;a&nbsp;collection&nbsp;of&nbsp;threads.&nbsp;This&nbsp;is&nbsp;the&nbsp;component&nbsp;where&nbsp;you&nbsp;define&nbsp;how&nbsp;many&nbsp;threads&nbsp;will&nbsp;run.&nbsp;Essentially,&nbsp;each&nbsp;thread represents&nbsp;a&nbsp;user&nbsp;using&nbsp;the&nbsp;application&nbsp;under&nbsp;test.</p>



<p>The&nbsp;thread&nbsp;group&nbsp;let&#8217;s&nbsp;you&nbsp;set&nbsp;the&nbsp;value&nbsp;of&nbsp;threads&nbsp;that&nbsp;you&nbsp;want&nbsp;to&nbsp;run(simulating&nbsp;the&nbsp;number&nbsp;of&nbsp;users, that&nbsp;you&nbsp;to&nbsp;test,&nbsp;using&nbsp;your&nbsp;app).For&nbsp;example,&nbsp;if&nbsp;you&nbsp;set&nbsp;threads&nbsp;number&nbsp;to&nbsp;100.&nbsp;JMeter&nbsp;will&nbsp;create&nbsp;and&nbsp;make&nbsp;100&nbsp;request&nbsp;to&nbsp;the&nbsp;application&nbsp;under&nbsp;test.</p>



<h4 class="wp-block-heading">Samplers</h4>



<p>JMeter&nbsp;supports&nbsp;testing&nbsp;HTTP,&nbsp;FTP,&nbsp;JDBC&nbsp;and&nbsp;many&nbsp;other&nbsp;protocols.</p>



<p>We&nbsp;already&nbsp;know&nbsp;that&nbsp;Thread&nbsp;Groups&nbsp;simulate&nbsp;user&nbsp;request&nbsp;to&nbsp;the&nbsp;server, but&nbsp;how&nbsp;does&nbsp;a&nbsp;Thread&nbsp;Group&nbsp;know&nbsp;which&nbsp;type&nbsp;of&nbsp;requests&nbsp;(HTTP,&nbsp;FTP&nbsp;etc.)&nbsp;it&nbsp;needs&nbsp;to&nbsp;make?&nbsp;The&nbsp;answer&nbsp;is&nbsp;Samplers.</p>



<p>The&nbsp;user&nbsp;request&nbsp;could&nbsp;be&nbsp;FTP&nbsp;Request,&nbsp;HTTP&nbsp;Request,&nbsp;JDBC&nbsp;Request, etc. In&nbsp;this&nbsp;example, we&nbsp;will&nbsp;concentrate&nbsp;in<strong> HTTP&nbsp;Request</strong>.</p>



<h4 class="wp-block-heading">Listeners</h4>



<p>Listeners&nbsp;shows&nbsp;the&nbsp;results&nbsp;of&nbsp;the&nbsp;test&nbsp;execution.&nbsp;They&nbsp;can&nbsp;show&nbsp;results&nbsp;in&nbsp;a&nbsp;different&nbsp;format&nbsp;such&nbsp;as&nbsp;a&nbsp;tree,&nbsp;table,&nbsp;graph&nbsp;or&nbsp;log&nbsp;file.</p>



<p>Graph&nbsp;result&nbsp;listeners&nbsp;display&nbsp;the&nbsp;server&nbsp;response&nbsp;times&nbsp;on&nbsp;a&nbsp;Graph.</p>



<p>View&nbsp;Result&nbsp;Tree&nbsp;show&nbsp;results&nbsp;of&nbsp;the&nbsp;user&nbsp;request&nbsp;in&nbsp;basic&nbsp;HTML&nbsp;format.</p>



<p>Table&nbsp;Result&nbsp;show&nbsp;summary&nbsp;of&nbsp;a&nbsp;test&nbsp;result&nbsp;in&nbsp;table&nbsp;format.</p>



<p>Log&nbsp;show&nbsp;summary&nbsp;of&nbsp;a&nbsp;test&nbsp;result&nbsp;in&nbsp;the&nbsp;text&nbsp;file.</p>



<h4 class="wp-block-heading">Config Elements</h4>



<p>Set&nbsp;up&nbsp;defaults&nbsp;and&nbsp;variables&nbsp;for&nbsp;later&nbsp;use&nbsp;by&nbsp;samplers.</p>



<p>The&nbsp;figure&nbsp;below&nbsp;shows&nbsp;some&nbsp;commonly&nbsp;used&nbsp;configuration&nbsp;elements&nbsp;in&nbsp;JMeter.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/ConfigurationElements.png" alt="" class="wp-image-12248" width="1058" height="277" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/ConfigurationElements.png 632w, https://blogit.create.pt/wp-content/uploads/2021/04/ConfigurationElements-300x78.png 300w" sizes="(max-width: 1058px) 100vw, 1058px" /></figure>



<h3 class="wp-block-heading">Let&#8217;s create a test</h3>



<p>As&nbsp;was&nbsp;shown&nbsp;before,&nbsp;JMeter&nbsp;starts&nbsp;with&nbsp;a&nbsp;Test&nbsp;Plan&nbsp;Component&nbsp;already&nbsp;created&nbsp;(you&nbsp;can&nbsp;change&nbsp;the&nbsp;name&nbsp;to&nbsp;anything&nbsp;more&nbsp;suitable&nbsp;to&nbsp;your&nbsp;case).&nbsp;</p>



<p>Now&nbsp;let&#8217;s&nbsp;start&nbsp;creating&nbsp;our&nbsp;test.&nbsp;In&nbsp;this&nbsp;case&nbsp;we&nbsp;will&nbsp;use&nbsp;<a href="https://my-json-server.typicode.com/">https://my-json-server.typicode.com/</a>&nbsp;to&nbsp;simulate&nbsp;an&nbsp;API. </p>



<p>Initially,&nbsp;let&#8217;s&nbsp;add&nbsp;a&nbsp;Thread&nbsp;Group.&nbsp;Right&nbsp;click&nbsp;on&nbsp;the&nbsp;test&nbsp;plan,&nbsp;then&nbsp;<strong>Add&nbsp;-&gt;&nbsp;Threads(Users)&nbsp;-&gt;&nbsp;Thread&nbsp;Group</strong>.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-1024x576.png" alt="" class="wp-image-12250" width="1069" height="602" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-1024x576.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-300x169.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-768x432.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-1536x864.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-696x392.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-1068x601.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup-747x420.png 747w, https://blogit.create.pt/wp-content/uploads/2021/04/ThreadGroup.png 1920w" sizes="(max-width: 1069px) 100vw, 1069px" /></figure>



<p>You&nbsp;can&nbsp;see&nbsp;that&nbsp;there&nbsp;is&nbsp;some&nbsp;settings&nbsp;that&nbsp;we&nbsp;need&nbsp;to&nbsp;adjust.&nbsp;At&nbsp;the&nbsp;top,&nbsp;there&nbsp;is&nbsp;a&nbsp;setting&nbsp;that&nbsp;says&nbsp;Action&nbsp;to&nbsp;be&nbsp;taken&nbsp;after&nbsp;a&nbsp;Sampler&nbsp;Error.&nbsp;Normally,&nbsp;I&nbsp;always&nbsp;use&nbsp;this&nbsp;in&nbsp;<strong>Continue</strong>&nbsp;but&nbsp;you&nbsp;can&nbsp;use&nbsp;the&nbsp;one&nbsp;that&nbsp;suits&nbsp;your&nbsp;case.</p>



<p>The&nbsp;next&nbsp;3&nbsp;settings&nbsp;will&nbsp;be&nbsp;the&nbsp;ones&nbsp;that&nbsp;we&nbsp;gonna&nbsp;focus&nbsp;for&nbsp;now.</p>



<ul class="wp-block-list"><li>Number&nbsp;of&nbsp;Threads&nbsp;(users)&nbsp;&#8211;&nbsp;is&nbsp;the&nbsp;number&nbsp;of&nbsp;threads(users)&nbsp;that&nbsp;will&nbsp;be&nbsp;running&nbsp;your&nbsp;test&nbsp;plan.</li><li>Ramp-up&nbsp;period&nbsp;(seconds)&nbsp;&#8211;&nbsp;is&nbsp;the&nbsp;value&nbsp;in&nbsp;seconds&nbsp;that&nbsp;defines&nbsp;how&nbsp;much&nbsp;time&nbsp;until&nbsp;all&nbsp;threads&nbsp;are&nbsp;working.&nbsp;Example:&nbsp;100&nbsp;Threads&nbsp;and&nbsp;10&nbsp;seconds&nbsp;of&nbsp;ramp-up&nbsp;period,&nbsp;this&nbsp;means&nbsp;that&nbsp;the&nbsp;threads&nbsp;will&nbsp;start,&nbsp;gradually,&nbsp;until&nbsp;at&nbsp;the&nbsp;point&nbsp;of&nbsp;10&nbsp;seconds&nbsp;all&nbsp;100&nbsp;threads&nbsp;will&nbsp;be&nbsp;working.</li><li>Loop&nbsp;Count&nbsp;&#8211;&nbsp;You&nbsp;can&nbsp;set&nbsp;this&nbsp;to&nbsp;the <strong>Infinite</strong>&nbsp;and&nbsp;will&nbsp;only&nbsp;stop&nbsp;threads&nbsp;when&nbsp;you&nbsp;press&nbsp;the&nbsp;button&nbsp;to&nbsp;stop.&nbsp;Also,&nbsp;you&nbsp;can&nbsp;set&nbsp;a&nbsp;loop&nbsp;count,&nbsp;that&nbsp;is&nbsp;the&nbsp;times&nbsp;that&nbsp;each&nbsp;thread&nbsp;will&nbsp;execute&nbsp;the&nbsp;test&nbsp;plan.&nbsp;Example,&nbsp;if&nbsp;you&nbsp;put&nbsp;the&nbsp;value&nbsp;3,&nbsp;the&nbsp;threads&nbsp;will&nbsp;execute&nbsp;the&nbsp;plan&nbsp;3&nbsp;times&nbsp;and&nbsp;then&nbsp;will&nbsp;stop.</li></ul>



<p>So,&nbsp;in&nbsp;our&nbsp;example&nbsp;lets&nbsp;try&nbsp;10&nbsp;threads,&nbsp;with&nbsp;5&nbsp;seconds&nbsp;of&nbsp;Ramp-up&nbsp;Time&nbsp;and&nbsp;the&nbsp;value&nbsp;3&nbsp;in&nbsp;the&nbsp;loop&nbsp;count.&nbsp;I&nbsp;will&nbsp;also&nbsp;change&nbsp;the&nbsp;name&nbsp;of&nbsp;the&nbsp;thread&nbsp;group&nbsp;to&nbsp;know&nbsp;how&nbsp;many&nbsp;threads&nbsp;I&nbsp;am&nbsp;using.&nbsp;It&nbsp;Should&nbsp;look&nbsp;like&nbsp;this.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-1024x576.png" alt="" class="wp-image-12251" width="1068" height="602" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-1024x576.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-300x169.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-768x432.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-1536x864.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-696x392.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-1068x601.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads-747x420.png 747w, https://blogit.create.pt/wp-content/uploads/2021/04/10Threads.png 1920w" sizes="(max-width: 1068px) 100vw, 1068px" /></figure>



<p>Let&#8217;s&nbsp;continue&nbsp;adding&nbsp;more&nbsp;components.&nbsp;This&nbsp;time, let&#8217;s&nbsp;add&nbsp;a&nbsp;way&nbsp;to&nbsp;define&nbsp;variables.&nbsp;Right-click&nbsp;on&nbsp;the&nbsp;Thread&nbsp;Group,&nbsp;then&nbsp;<strong>Add&nbsp;-&gt;&nbsp;Config-Element&nbsp;-&gt;&nbsp;User&nbsp;Defined&nbsp;Variables</strong>.&nbsp;</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/Variables-1024x251.png" alt="" class="wp-image-12252" width="1067" height="262" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/Variables-1024x251.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables-300x73.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables-768x188.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables-1536x376.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables-696x170.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables-1068x261.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables-1716x420.png 1716w, https://blogit.create.pt/wp-content/uploads/2021/04/Variables.png 1920w" sizes="(max-width: 1067px) 100vw, 1067px" /></figure>



<p>This&nbsp;component&nbsp;will&nbsp;let&nbsp;you&nbsp;define&nbsp;some&nbsp;variable&nbsp;to&nbsp;use&nbsp;afterwards.&nbsp;Let&#8217;s&nbsp;define&nbsp;some.</p>



<ul class="wp-block-list"><li>url:&nbsp;my-json-server.typicode.com</li><li>postId:&nbsp;1</li></ul>



<p>&nbsp;Now,&nbsp;to&nbsp;use&nbsp;these&nbsp;variables&nbsp;in&nbsp;other&nbsp;components&nbsp;you&nbsp;will&nbsp;need&nbsp;to&nbsp;do&nbsp;it&nbsp;in&nbsp;the&nbsp;following&nbsp;way.</p>



<ul class="wp-block-list"><li>${url}&nbsp;for&nbsp;the&nbsp;<strong>url</strong>&nbsp;Value&nbsp;</li><li>${postId}&nbsp;for&nbsp;the&nbsp;<strong>postId</strong>&nbsp;Value</li></ul>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-1024x203.png" alt="" class="wp-image-12253" width="1069" height="213" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-1024x203.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-300x59.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-768x152.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-1536x304.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-696x138.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/userVariable-1068x212.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/userVariable.png 1923w" sizes="(max-width: 1069px) 100vw, 1069px" /></figure>



<p>Finally,&nbsp;let&#8217;s&nbsp;add&nbsp;some&nbsp;real&nbsp;requests.&nbsp;Here&nbsp;as&nbsp;example&nbsp;we&nbsp;will&nbsp;make&nbsp;3&nbsp;different&nbsp;requests.&nbsp;Http&nbsp;Request&nbsp;to&nbsp;get&nbsp;all&nbsp;posts,&nbsp;Http&nbsp;Request&nbsp;to&nbsp;get&nbsp;one&nbsp;Post,&nbsp;and&nbsp;Http&nbsp;Request&nbsp;to&nbsp;Post&nbsp;a&nbsp;new&nbsp;Post.&nbsp;Remember&nbsp;that&nbsp;the&nbsp;site&nbsp;used&nbsp;in&nbsp;this&nbsp;example&nbsp;has&nbsp;paths&nbsp;to&nbsp;request&nbsp;posts&nbsp;and&nbsp;to&nbsp;add&nbsp;posts.</p>



<p>How&nbsp;to&nbsp;add&nbsp;an&nbsp;HTTP&nbsp;Request&nbsp;?&nbsp;Right-click&nbsp;on&nbsp;the&nbsp;Thread&nbsp;Group,&nbsp;then&nbsp;<strong>Add&nbsp;-&gt;&nbsp;Smapler&nbsp;-&gt;&nbsp;Http&nbsp;Request</strong>.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-1024x277.png" alt="" class="wp-image-12255" width="1069" height="290" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-1024x277.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-300x81.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-768x208.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-1536x416.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-696x188.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-1068x289.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest-1551x420.png 1551w, https://blogit.create.pt/wp-content/uploads/2021/04/HttpRequest.png 1935w" sizes="(max-width: 1069px) 100vw, 1069px" /></figure>



<p>Now&nbsp;that&nbsp;we&nbsp;have&nbsp;an&nbsp;Http&nbsp;Request&nbsp;component,&nbsp;let&#8217;s&nbsp;configure&nbsp;to&nbsp;make&nbsp;a&nbsp;Http&nbsp;Request&nbsp;to&nbsp;get&nbsp;all&nbsp;posts.&nbsp;The&nbsp;path&nbsp;to&nbsp;this&nbsp;request&nbsp;is&nbsp;<span style="text-decoration: underline">https://jsonplaceholder.typicode.com/posts</span>. The&nbsp;configurations&nbsp;of&nbsp;this&nbsp;component&nbsp;are:</p>



<ul class="wp-block-list"><li><strong>Protocol</strong>&nbsp;-&gt;&nbsp;&#8220;https&#8221;</li><li><strong>Server&nbsp;Name&nbsp;or&nbsp;IP</strong>&nbsp;-&gt;&nbsp;${url}&nbsp;(because&nbsp;we&nbsp;have&nbsp;this&nbsp;value&nbsp;defined&nbsp;in&nbsp;a&nbsp;variable)</li><li><strong>Port&nbsp;Number</strong> -&gt;&nbsp;in&nbsp;this&nbsp;case, nothing but&nbsp;if&nbsp;you&nbsp;need&nbsp;to&nbsp;your&nbsp;specific&nbsp;case,&nbsp;here&nbsp;is&nbsp;where&nbsp;you&nbsp;put&nbsp;the&nbsp;port&nbsp;number.&nbsp;Example:&nbsp;to&nbsp;make&nbsp;a&nbsp;request&nbsp;to&nbsp;https://localhost:80,&nbsp;you&nbsp;would&nbsp;need&nbsp;to&nbsp;put&nbsp;the&nbsp;value&nbsp;80&nbsp;in&nbsp;here.</li><li><strong>HTTP&nbsp;Request</strong>&nbsp;-&gt;&nbsp;GET</li><li><strong>Path</strong>&nbsp;-&gt;&nbsp;&#8220;/typicode/demo/posts&#8221;</li></ul>



<p>Now&nbsp;that&nbsp;we&nbsp;have&nbsp;everything,&nbsp;let&#8217;s&nbsp;run&nbsp;?&nbsp;Click&nbsp;on&nbsp;the&nbsp;start&nbsp;Button&nbsp;above&nbsp;and&nbsp;see&nbsp;what&nbsp;happens.&nbsp;Nothing&nbsp;?&nbsp;Stop&nbsp;the&nbsp;process&nbsp;and&nbsp;let&#8217;s&nbsp;see&nbsp;what&nbsp;is&nbsp;missing.</p>



<p>The&nbsp;piece&nbsp;that&nbsp;is&nbsp;missing&nbsp;is&nbsp;<strong>listeners</strong>.&nbsp;We&nbsp;need&nbsp;listeners&nbsp;to&nbsp;understand&nbsp;what&nbsp;is&nbsp;happening.&nbsp;In&nbsp;this&nbsp;case,&nbsp;the&nbsp;<strong>View&nbsp;Results&nbsp;Tree</strong>&nbsp;and&nbsp;<strong>Summary&nbsp;Report</strong>.&nbsp;Let&#8217;s&nbsp;add&nbsp;these&nbsp;two&nbsp;listeners&nbsp;by&nbsp;Right-clicking&nbsp;in&nbsp;the&nbsp;Thread&nbsp;Group,&nbsp;then&nbsp;<strong>Add&nbsp;-&gt;&nbsp;Listener&nbsp;-&gt;&nbsp;View&nbsp;Results&nbsp;Tree</strong>&nbsp;and&nbsp;<strong>Add&nbsp;-&gt;&nbsp;Listener&nbsp;-&gt;&nbsp;Summary&nbsp;Report</strong>.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-1024x246.png" alt="" class="wp-image-12256" width="1070" height="258" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-1024x246.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-300x72.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-768x184.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-1536x369.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-696x167.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/Listeners-1750x420.png 1750w, https://blogit.create.pt/wp-content/uploads/2021/04/Listeners.png 1908w" sizes="(max-width: 1070px) 100vw, 1070px" /></figure>



<p>Now,&nbsp;if&nbsp;you&nbsp;start&nbsp;the&nbsp;process,&nbsp;you&nbsp;will&nbsp;see&nbsp;that&nbsp;these&nbsp;listeners&nbsp;represent&nbsp;information&nbsp;about&nbsp;the&nbsp;request.&nbsp;</p>



<p>The&nbsp;View&nbsp;Results&nbsp;Tree&nbsp;show&nbsp;every&nbsp;request&nbsp;information.&nbsp;In&nbsp;here,&nbsp;you&nbsp;can&nbsp;see&nbsp;the&nbsp;request&nbsp;body&nbsp;and&nbsp;headers,&nbsp;and&nbsp;the&nbsp;response&nbsp;body&nbsp;and&nbsp;headers.</p>



<p>In&nbsp;this&nbsp;example,&nbsp;when&nbsp;we&nbsp;choose&nbsp;the&nbsp;<strong>Response&nbsp;Body</strong>&nbsp;of&nbsp;one&nbsp;request&nbsp;we&nbsp;will&nbsp;see&nbsp;that&nbsp;there&nbsp;will&nbsp;be&nbsp;a&nbsp;JSON&nbsp;with&nbsp;data&nbsp;relative&nbsp;to&nbsp;what&nbsp;they&nbsp;call&nbsp;as&nbsp;posts.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-1024x551.png" alt="" class="wp-image-12257" width="1072" height="578" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-1024x551.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-300x161.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-768x413.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-1536x827.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-696x375.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-1068x575.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample-780x420.png 780w, https://blogit.create.pt/wp-content/uploads/2021/04/PostsExample.png 1906w" sizes="(max-width: 1072px) 100vw, 1072px" /></figure>



<p>The&nbsp;Summary&nbsp;Report&nbsp;Aggregates&nbsp;the&nbsp;information&nbsp;of&nbsp;different&nbsp;types&nbsp;of&nbsp;request.&nbsp;In&nbsp;this&nbsp;case,&nbsp;we&nbsp;only&nbsp;have&nbsp;one&nbsp;request,&nbsp;so,&nbsp;it&nbsp;will&nbsp;show&nbsp;informations&nbsp;about&nbsp;that&nbsp;request.What&nbsp;are&nbsp;the&nbsp;informations&nbsp;that&nbsp;this&nbsp;will&nbsp;show&nbsp;?&nbsp;</p>



<ul class="wp-block-list"><li>#Samples&nbsp;&#8211;&nbsp;are&nbsp;the&nbsp;number&nbsp;of&nbsp;requests&nbsp;made&nbsp;</li><li>Average&nbsp;&#8211;&nbsp;shows&nbsp;&nbsp;the&nbsp;average&nbsp;time&nbsp;needed&nbsp;to&nbsp;make&nbsp;these&nbsp;requests&nbsp;</li><li>Min&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;value&nbsp;of&nbsp;the&nbsp;request&nbsp;that&nbsp;take&nbsp;less&nbsp;time&nbsp;to&nbsp;finish</li><li>Max&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;value&nbsp;of&nbsp;the&nbsp;request&nbsp;that&nbsp;take&nbsp;more&nbsp;time&nbsp;to&nbsp;finish</li><li>Std.&nbsp;Dev.&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;standard&nbsp;deviation&nbsp;of&nbsp;the&nbsp;request&nbsp;times&nbsp;to&nbsp;the&nbsp;average</li><li>Error&nbsp;%&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;percentage&nbsp;of&nbsp;requests&nbsp;that&nbsp;failed</li><li>Throughput&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;number&nbsp;of&nbsp;requests&nbsp;processed&nbsp;by&nbsp;time&nbsp;</li><li>Received&nbsp;KB/sec&nbsp;&#8211;&nbsp;&nbsp;shows&nbsp;the&nbsp;amount&nbsp;of&nbsp;data&nbsp;downloaded&nbsp;from&nbsp;the&nbsp;server&nbsp;&nbsp;time</li><li>Sent&nbsp;KB/sec&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;amount&nbsp;of&nbsp;data&nbsp;uploaded&nbsp;to&nbsp;the&nbsp;server&nbsp;time&nbsp;</li><li>Avg.&nbsp;Bytes&nbsp;&#8211;&nbsp;shows&nbsp;the&nbsp;average&nbsp;size&nbsp;of&nbsp;the&nbsp;response&nbsp;sample</li></ul>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-1024x181.png" alt="" class="wp-image-12259" width="1069" height="190" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-1024x181.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-300x53.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-768x136.png 768w, https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-1536x271.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-696x123.png 696w, https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport-1068x189.png 1068w, https://blogit.create.pt/wp-content/uploads/2021/04/SummaryReport.png 1920w" sizes="(max-width: 1069px) 100vw, 1069px" /></figure>



<p>We&nbsp;have&nbsp;all&nbsp;we&nbsp;need,&nbsp;let&#8217;s&nbsp;add&nbsp;more&nbsp;Requests.&nbsp;Let&#8217;s&nbsp;create&nbsp;a&nbsp;request&nbsp;that&nbsp;creates&nbsp;a&nbsp;post,&nbsp;and&nbsp;create&nbsp;a&nbsp;request&nbsp;that&nbsp;obtains&nbsp;only&nbsp;one&nbsp;post.&nbsp;Also,&nbsp;change&nbsp;the&nbsp;name&nbsp;of&nbsp;the&nbsp;Http&nbsp;Request&nbsp;components&nbsp;to&nbsp;now&nbsp;what&nbsp;is&nbsp;the&nbsp;correspondent&nbsp;request.&nbsp;Remember&nbsp;to&nbsp;put&nbsp;the&nbsp;Http&nbsp;Request&nbsp;before&nbsp;the&nbsp;listeners.&nbsp;The&nbsp;Listeners&nbsp;will&nbsp;only&nbsp;listen&nbsp;to&nbsp;what&nbsp;are&nbsp;before&nbsp;them.&nbsp;Remember&nbsp;this!&nbsp;</p>



<p>The&nbsp;create&nbsp;a&nbsp;post&nbsp;request&nbsp;configurations&nbsp;are:</p>



<ol class="wp-block-list"><li><strong>Protocol</strong>&nbsp;-&gt;&nbsp;&#8220;https&#8221;</li><li><strong>Server&nbsp;Name&nbsp;or&nbsp;IP</strong>&nbsp;-&gt;&nbsp;${url}&nbsp;(because&nbsp;we&nbsp;have&nbsp;this&nbsp;value&nbsp;defined&nbsp;in&nbsp;a&nbsp;variable)</li><li><strong>HTTP&nbsp;Request</strong>&nbsp;-&gt;&nbsp;Post</li><li><strong>Path</strong>&nbsp;-&gt;&nbsp;&#8220;/typicode/demo/posts&#8221;</li><li><strong>Body&nbsp;Data</strong>&nbsp;&#8211;&nbsp;we&nbsp;will&nbsp;put&nbsp;a&nbsp;JSON&nbsp;like&nbsp;this&nbsp;{&#8220;title&#8221;:&nbsp;&#8220;Car&nbsp;Crash&#8221;}</li></ol>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2021/04/CreatePost-1024x306.png" alt="" class="wp-image-12261" width="1086" height="326" srcset="https://blogit.create.pt/wp-content/uploads/2021/04/CreatePost-1024x306.png 1024w, https://blogit.create.pt/wp-content/uploads/2021/04/CreatePost-300x90.png 300w, https://blogit.create.pt/wp-content/uploads/2021/04/CreatePost-1536x459.png 1536w, https://blogit.create.pt/wp-content/uploads/2021/04/CreatePost-696x208.png 696w" sizes="(max-width: 1086px) 100vw, 1086px" /></figure>



<p>And,&nbsp;The&nbsp;get&nbsp;one&nbsp;post&nbsp;request&nbsp;configurations&nbsp;are:</p>



<ol class="wp-block-list" id="block-add80d93-dc9f-41db-9cbc-14ed3602e60e"><li><strong>Protocol</strong>&nbsp;-&gt;&nbsp;&#8220;https&#8221;</li><li><strong>Server&nbsp;Name&nbsp;or&nbsp;IP</strong>&nbsp;-&gt;&nbsp;${url}&nbsp;(because&nbsp;we&nbsp;have&nbsp;this&nbsp;value&nbsp;defined&nbsp;in&nbsp;a&nbsp;variable)</li><li><strong>HTTP&nbsp;Request</strong>&nbsp;-&gt;&nbsp;Get</li><li><strong>Path</strong>&nbsp;-&gt;&nbsp;&#8220;/typicode/demo/posts/${postId}&#8221;</li></ol>



<p>Run&nbsp;the&nbsp;test&nbsp;plan&nbsp;and&nbsp;see&nbsp;the&nbsp;results.&nbsp;Try&nbsp;to&nbsp;do&nbsp;it&nbsp;for&nbsp;another&nbsp;API.&nbsp;</p>



<p>These&nbsp;are&nbsp;the&nbsp;basic&nbsp;examples&nbsp;that&nbsp;we&nbsp;have&nbsp;for&nbsp;you&nbsp;right&nbsp;now.&nbsp;More&nbsp;advanced&nbsp;tips&nbsp;will&nbsp;come.&nbsp;</p>



<p>See&nbsp;you&nbsp;next&nbsp;time.</p>



<h3 class="wp-block-heading">References</h3>



<ul class="wp-block-list"><li><a href="https://www.guru99.com/jmeter-element-reference.html ">https://www.guru99.com/jmeter-element-reference.html</a></li><li><a href="https://www.guru99.com/hands-on-with-jmeter-gui.html">https://www.guru99.com/hands-on-with-jmeter-gui.html</a></li></ul>



<p></p>
<p>The post <a href="https://blogit.create.pt/diogocoelho/2021/04/23/performance-testing-an-api-how-to-start-doing-it-with-jmeter/">Performance Testing An API, How To Start Doing It With JMeter?</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/diogocoelho/2021/04/23/performance-testing-an-api-how-to-start-doing-it-with-jmeter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
