<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Peter Lindholm</title>
    <description>The latest articles on DEV Community by Peter Lindholm (@peterlindholm).</description>
    <link>https://dev.to/peterlindholm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F455803%2F9050d6cb-5539-42e4-b8a0-8ec6fd3a00cb.jpg</url>
      <title>DEV Community: Peter Lindholm</title>
      <link>https://dev.to/peterlindholm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peterlindholm"/>
    <language>en</language>
    <item>
      <title>The case of the Mysterious Azure Storage spikes</title>
      <dc:creator>Peter Lindholm</dc:creator>
      <pubDate>Sat, 20 Feb 2021 15:39:15 +0000</pubDate>
      <link>https://dev.to/peterlindholm/the-case-of-the-mysterious-azure-storage-spikes-13n2</link>
      <guid>https://dev.to/peterlindholm/the-case-of-the-mysterious-azure-storage-spikes-13n2</guid>
      <description>&lt;p&gt;Recently I noticed a significant increase in Azure costs on a client project. For this particular client cloud storage is used for virtual machine disks, a few assets and hosting of a set of application. Cloud storage costs is something I've almost thought of as free. Naively.&lt;/p&gt;

&lt;p&gt;Over a short period of time storage costs increased more than 300%. Weird. I checked and compared usage over a couple of billing periods. No spikes in user traffic that could explain this.&lt;/p&gt;

&lt;p&gt;Fortunately Azure Cost Analysis lets you dive pretty deep on all individually incurred costs. The majority of costs was incurred by 'lrs write operations'. Digging into the 'Total Requests' metric of the storage account I was seeing approx. 1.4M requests per hour.&lt;/p&gt;

&lt;p&gt;Drilling further into ingress/egress metrics revealed almost no data moving across the network 🤔&lt;/p&gt;

&lt;p&gt;Next step was grouping the different kinds of requests making up those crazy numbers. Only a single operation stood out with millions of operations occurring during a regular day: ChangeNotify.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed?
&lt;/h2&gt;

&lt;p&gt;So, troubleshooting 101...what has changed? Going through the latest commit log revealed upgrades to a few Azure Functions projects (sharing storage). The projects was updated to Azure Function v3 runtime and moving from .NET Core 2.1 to .NET Core 3.1. But no code changes.&lt;/p&gt;

&lt;p&gt;This gave a few Google'able hints to go for and surely I was not the only one seeing this.&lt;/p&gt;

&lt;p&gt;Apparently the culprit seemed to be how IConfiguration was built and used inside individual functions. In the oldest of the functions, before DI in Azure Functions was a thing, I had this approach to accessing the configuration data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var config = new ConfigurationBuilder()
                .SetBasePath(context.FunctionAppDirectory)
                .AddJsonFile("local.settings.json", 
                    optional: true, 
                    reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In particular this line below was causing the issue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;'local.settings.json' is as the name implies meant for local usage/testing scenarios. It is never committed to source control and thus never published to Azure. But even though it is marked as optional, something in the Azure Functions runtime goes crazy because of this "missing" file.&lt;/p&gt;

&lt;p&gt;I cleaned up the old functions and allowed for them to use constructor injection of whatever configuration was needed in the functions. This was I completely removed the above code block initialising the config.&lt;/p&gt;

&lt;p&gt;Did a few quick tests and deployed to production. Either way the functions would be better off that before. But immediately I saw the transactions count dropping.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C4NLcBo1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5vyeldfpv6e3rilz7t1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C4NLcBo1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5vyeldfpv6e3rilz7t1.png" alt="Screenshot-2021-02-20-at-15.18.10"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Guess when my cleanup was deployed? 😀&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;I have no idea why the increased storage operations was triggered after upgrading to a newer runtime. But my best bet is that the Azure Functions team have had a regression 🤷‍♂️&lt;/p&gt;

&lt;p&gt;This issue was a welcome opportunity for me to learn more about the Cost Management part of an Azure Subscription. Going forward monitoring of cost analysis grouped by resources will be Yet Another™️ activity to include in my day-to-day operations.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Switching the offset for a UTC date in SQL Server</title>
      <dc:creator>Peter Lindholm</dc:creator>
      <pubDate>Thu, 20 Aug 2020 18:23:49 +0000</pubDate>
      <link>https://dev.to/peterlindholm/switching-the-offset-for-a-utc-date-in-sql-server-31pc</link>
      <guid>https://dev.to/peterlindholm/switching-the-offset-for-a-utc-date-in-sql-server-31pc</guid>
      <description>&lt;p&gt;I was doing some work recently where I needed to group some data from SQL Server by year, month, week, etc.&lt;/p&gt;

&lt;p&gt;The simplified version was something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT  
    COUNT(x),   
    YEAR(CreatedUtc)
FROM    
    dbo.[Order]
GROUP BY
    YEAR(CreatedUtc)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CreatedUtc data type is datetimeoffset storing zulu datetimes.&lt;/p&gt;

&lt;p&gt;Even though I knew I was only looking at data from 2020 I was still seeing 2 rows - one for 2019 and one for 2020.&lt;/p&gt;

&lt;p&gt;I tested my date filtering (omitted for brevity in the sample above) and everything was fine. All dates was within the 2020 UTC bounds.&lt;/p&gt;

&lt;p&gt;So after digging a bit more I found the offending row resulting in the 2019 group. The date was: &lt;strong&gt;‘2019-12-31 23:56:43.0052080 +00:00’&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thinking of it, it of course makes perfect sense that the built-in YEAR function is not aware of timezones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YEAR(‘2019-12-31 23:56:43.0052080 +00:00’)&lt;/strong&gt; will (naturally) return 2019.&lt;/p&gt;

&lt;p&gt;We need to switch the offset in the datetimeoffset to the timezone required for the task. In my use-case of a building a report that means switching to CEST/Central European Standard Time.&lt;/p&gt;

&lt;p&gt;The YEAR snippet now instead becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YEAR(SWITCHOFFSET(CreatedUtc, DATEPART(TZOFFSET, CreatedUtc AT TIME ZONE 'Central Europe Standard Time')))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full (still simplified) sample becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`
SELECT  
    COUNT(x),   
    YEAR(SWITCHOFFSET(CreatedUtc, DATEPART(TZOFFSET, CreatedUtc AT TIME ZONE 'Central Europe Standard Time')))
FROM
    dbo.[Order]
GROUP BY
    YEAR(SWITCHOFFSET(CreatedUtc, DATEPART(TZOFFSET, CreatedUtc AT TIME ZONE 'Central Europe Standard Time')))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice: I haven’t yet done any benchmarking on the above approach and it might make sense to extract this to a function to clean things up a bit.&lt;/p&gt;

&lt;p&gt;Also see the official SWITCHOFFSET documentation.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/sql/t-sql/functions/switchoffset-transact-sql?view=sql-server-ver15"&gt;https://docs.microsoft.com/en-us/sql/t-sql/functions/switchoffset-transact-sql?view=sql-server-ver15&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have another better approach please do let me know :-)&lt;/p&gt;

</description>
      <category>sql</category>
    </item>
  </channel>
</rss>
