<?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>Forem: Lyn Chen 🦄</title>
    <description>The latest articles on Forem by Lyn Chen 🦄 (@lyncozy).</description>
    <link>https://forem.com/lyncozy</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%2F571756%2F5ba03d59-5930-4288-bcb4-017f7e81b790.png</url>
      <title>Forem: Lyn Chen 🦄</title>
      <link>https://forem.com/lyncozy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lyncozy"/>
    <language>en</language>
    <item>
      <title>Storing Billions of VM Metrics with TimescaleDB</title>
      <dc:creator>Lyn Chen 🦄</dc:creator>
      <pubDate>Tue, 25 Oct 2022 19:07:02 +0000</pubDate>
      <link>https://forem.com/lyncozy/storing-billions-of-vm-metrics-with-timescaledb-1k3p</link>
      <guid>https://forem.com/lyncozy/storing-billions-of-vm-metrics-with-timescaledb-1k3p</guid>
      <description>&lt;p&gt;Originally published &lt;a href="https://webapp.io/blog/storing-millions-of-vm-metrics-with-timescaledb/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With the recent launch of our Layerfile analytics project, we encountered a cool engineering problem - how to store billions of virtual machine (VM) metrics in PostgreSQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the recent launch of our &lt;a href="https://docs.webapp.io/advanced-workflows/layerfile-analytics"&gt;Layerfile analytics project&lt;/a&gt;, we encountered a cool engineering problem - how to store billions of &lt;a href="https://webapp.io/blog/the-difference-between-vms-and-containers/"&gt;virtual machine&lt;/a&gt; (VM) metrics in &lt;a href="https://webapp.io/blog/postgres-is-the-answer/"&gt;PostgreSQL&lt;/a&gt;. The metrics we wanted to track were the VM's CPU, disk and memory usage at a one second interval throughout the duration of its life. Our data can be considered time-series data as it is timestamped and append only.&lt;/p&gt;

&lt;p&gt;While &lt;a href="https://webapp.io/blog/postgres-is-the-answer/"&gt;PostgreSQL&lt;/a&gt; will be sufficient for our first few million rows, we will start to see its performance decline as the number of writes increases and our table grows. The main pain points we faced included:&lt;/p&gt;

&lt;p&gt;Reads and writes being too slow at scale&lt;br&gt;
Threat of growing table size causing disk pressure&lt;br&gt;
With these points in mind, we chose &lt;a href="https://www.timescale.com/"&gt;TimescaleDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is TimescaleDB?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TimescaleDB is a time-series database built on top of PostgreSQL. It is an extension to PostgreSQL that implements tools to aide in the handling and processing of &lt;a href="https://www.influxdata.com/what-is-time-series-data/"&gt;time-series data&lt;/a&gt;. The Timescale extension runs within a PostgreSQL server processing queries first to determine the planning and execution of queries involving time-series data. This enables much higher data ingestion rates and greatly improves query performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eXoo-dVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wwz1q78gf2a88fkijw7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eXoo-dVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wwz1q78gf2a88fkijw7.jpeg" alt="Ingest Rate: PostgreSQL vs Timescale Source: https://docs.timescale.com/timescaledb/latest/overview/how-does-it-compare/timescaledb-vs-postgres/" width="880" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How we used Timescale to solve our problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first step taken was to convert the table storing our metrics into a &lt;a href="https://docs.timescale.com/timescaledb/latest/overview/core-concepts/hypertables-and-chunks/"&gt;Hypertable&lt;/a&gt;. Hypertables look and feel like regular PostgreSQL tables but are partitioned by Timescale into time based chunks. Creating a Hypertable allows us to take advantage of Timescale's full suite of tooling in addition to the ingestion and query performance.&lt;/p&gt;

&lt;p&gt;The next step was to create a &lt;a href="https://docs.timescale.com/timescaledb/latest/overview/core-concepts/compression/"&gt;compression&lt;/a&gt; policy on the Hypertable. Timescale will compress chunks of data older than an interval you specify in a compression policy, in our case, 1 week. This data can still be accessed but not updated. Enabling compression on a Hypertable has between a 91-96% storage savings.&lt;/p&gt;

&lt;p&gt;Finally, we used &lt;a href="https://docs.timescale.com/timescaledb/latest/overview/core-concepts/continuous-aggregates/"&gt;continuous aggregates&lt;/a&gt;. They are similar to PostgreSQL's &lt;a href="https://www.postgresql.org/docs/current/rules-materializedviews.html"&gt;materialized views&lt;/a&gt; but can be refreshed using a policy. We created a continuous aggregate that averages each stat over a 15 second interval refreshing every minute. This allows us to select already processed data from a smaller table, ready to be consumed by the front end.&lt;/p&gt;

</description>
      <category>timescaledb</category>
      <category>postgres</category>
      <category>programming</category>
      <category>startup</category>
    </item>
    <item>
      <title>Crypto miners are killing free CI</title>
      <dc:creator>Lyn Chen 🦄</dc:creator>
      <pubDate>Sun, 25 Apr 2021 22:06:45 +0000</pubDate>
      <link>https://forem.com/lyncozy/crypto-miners-are-killing-free-ci-4pii</link>
      <guid>https://forem.com/lyncozy/crypto-miners-are-killing-free-ci-4pii</guid>
      <description>&lt;p&gt;Originally published here: &lt;a href="https://layerci.com/blog/crypto-miners-are-killing-free-ci/"&gt;https://layerci.com/blog/crypto-miners-are-killing-free-ci/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CI providers like GitLab, TravisCI, and Shippable are all worsening or shutting down their free tiers due to cryptocurrency mining attacks.&lt;/p&gt;

&lt;p&gt;On September 1st, 2020, GitLab announced that their free CI offering was being restricted in response to "usage." Two months later, TravisCI announced that a similar restriction in response to "significant abuse."&lt;/p&gt;

&lt;p&gt;Concurrently with these pricing changes, the market capitalization of mineable cryptocurrencies has exploded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sOeJZXUt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc9suxzzfcof06vjqauy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sOeJZXUt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc9suxzzfcof06vjqauy.png" alt="crypto"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These events are related: As the market capitalization of cryptocurrency surged from $190 billion in January of 2020 to $2 trillion in April of 2021, it's become profitable for bad actors to make a full time job of attacking the free tiers of platform-as-a-service providers.&lt;/p&gt;

&lt;p&gt;717 GitHub commits in one month&lt;br&gt;
"testronan" is an avid Flask user. Every hour they make a commit to their only GitHub repository: "testronan/MyFirstRepository-Flask"&lt;/p&gt;

&lt;p&gt;The prolific programmer is certainly making sure that their contributions are well tested. Their repository contains configurations for five different CI providers: TravisCI, CircleCI, GitHub Actions, Wercker, and LayerCI.&lt;/p&gt;

&lt;p&gt;Seemingly quite proficient at shell scripting, their CI tasks run "listen.sh": A shell script that combines a complicated NodeJS script with some seemingly random numbers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yxbzQ-A2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pblcmwjf5n5kv4pamswu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yxbzQ-A2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pblcmwjf5n5kv4pamswu.png" alt="screenshot-layerci.com-2021.04.25-18_05_27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MyFirstRepository-Flask has nothing to do with Flask or webservers. It hosts cryptocurrency mining scripts that send WebDollars to an anonymous address. The numbers correspond to installation options for the NodeJS implementation of WebDollar&lt;/p&gt;

&lt;p&gt;The repository is not attacking GitHub directly, instead it abuses GitHub actions' "cron" feature to create a new commit every hour and mine WebDollars on four other CI providers.&lt;/p&gt;

&lt;p&gt;At WebDollar's April peak price of $.0005, the repository was making $77USD per month - a considerable sum in many countries, especially given that the only tools required are a laptop and an internet connection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7g04nPT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bn1dm0o77icoo0uaspm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7g04nPT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bn1dm0o77icoo0uaspm8.png" alt="cryptomining-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two wallet addresses that receive these coins are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.webdscan.io/address/WEBD%24gBJhmuwat3kvP2@%232E4K2zXX967grh9L43%24"&gt;https://www.webdscan.io/address/WEBD%24gBJhmuwat3kvP2@%232E4K2zXX967grh9L43%24&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.webdscan.io/address/WEBD%24gCszFRxzuMDbyNXnCXszoB2aIMSuV9kgbb%24"&gt;https://www.webdscan.io/address/WEBD%24gCszFRxzuMDbyNXnCXszoB2aIMSuV9kgbb%24&lt;/a&gt;&lt;br&gt;
Headless browser cryptocurrency mining&lt;br&gt;
"vippro99" is less subtle about their intentions. Out of dozens of repositories, most are related to cryptocurrency or browser automation.&lt;/p&gt;

&lt;p&gt;The nodejs-monney repository contains various scripts to start instances of chrome with the Google's popular puppeteer project.&lt;/p&gt;

&lt;p&gt;The idea is simple: Mining cryptocurrency directly in CI is somewhat easily detectable (with executable content analysis, for example) but browser automation is a common workload within CI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H7M2_Ssj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qsz5qhc7pqw747r4yi7f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H7M2_Ssj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qsz5qhc7pqw747r4yi7f.png" alt="screenshot-layerci.com-2021.04.25-18_03_34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The referenced GitHub pages website contains a simple browser-based Monero miner, reminiscent of Coinhive.&lt;/p&gt;

&lt;p&gt;As of writing, the account is currently attacking JFrog's Shippable CI, which (perhaps relatedly) announced the end of its free tier earlier this year.&lt;/p&gt;

&lt;p&gt;"vippro99"'s comments indicate that they are in Vietnam. At the current price of Monero, each instance of their cryptocurrency miner on Shippable is giving $2.5USD per month, so maintaining a mere 60 concurrent instances would be equivalent to a full time job in that country.&lt;/p&gt;

&lt;p&gt;A solution for crypto&lt;br&gt;
Ethereum, the second most popular cryptocurrency, recently announced plans to fully disable computation-based mining as a way to earn new Ethereum, switching entirely to a proof-of-stake (POS) validation model.&lt;/p&gt;

&lt;p&gt;Beyond the environmental impact of traditional "proof of work" mining, there are externalities in many other fields like worldwide GPU shortages and attacks on free tiers of compute platforms like CI.&lt;/p&gt;

&lt;p&gt;Providers can do their best to enforce terms of service, but as long as it's profitable and untraceable to make such attacks, they will continue to become more sophisticated and circumvent measures. The only long-term way that we will continue to be able to enjoy free tiers on Heroku, Netlify, and GitHub are to switch away from proof-of-work.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>startup</category>
    </item>
    <item>
      <title>Introducing Wrap.sh - an internal hackathon project</title>
      <dc:creator>Lyn Chen 🦄</dc:creator>
      <pubDate>Mon, 01 Feb 2021 22:00:40 +0000</pubDate>
      <link>https://forem.com/lyncozy/introducing-wrap-sh-an-internal-hackathon-project-483k</link>
      <guid>https://forem.com/lyncozy/introducing-wrap-sh-an-internal-hackathon-project-483k</guid>
      <description>&lt;p&gt;Hey DEV Community!Some of the coolest people I've met were through university hackathons. It was always a great way to take a break from school/work, get to know others, and come up with interesting ideas to hard problems. I remember discovering my love for Awake Chocolate, learning new tools and pitching nervously the next day. What I loved most about these events is that no matter who won, everyone felt that they contributed and made something worth sharing.&lt;/p&gt;

&lt;p&gt;Unfortunately, I hadn't worked at a workplace before LayerCI where experimentation was so engrained into the company DNA. Why did we ever stop making things together and instead only go to engineering conferences? Smack in the middle of the pandemic, our team decided to do an internal hackathon together and the results were awesome.I remember discovering my love for Awake Chocolate, learning new tools and pitching nervously the next day. What I loved most about these events is that no matter who won, everyone felt that they contributed and made something worth sharing.&lt;/p&gt;

&lt;p&gt;Unfortunately, I hadn't worked at a workplace before LayerCI where experimentation was so engrained into the company DNA. Why did we ever stop making things together and instead only go to engineering conferences? Smack in the middle of the pandemic, our team decided to do an internal hackathon together and the results were awesome. &lt;/p&gt;

&lt;p&gt;Our very first open source project was born! &lt;/p&gt;

&lt;p&gt;I'm excited to share the winning, internal hackathon project idea my teammate Dmitri on the engineering team led - it's a bash script that can be installed with anyone's CI to create preview environments without having to spend the engineering hours building it yourself. &lt;/p&gt;

&lt;p&gt;Try for free here: &lt;a href="https://wrap.sh/" rel="noopener noreferrer"&gt;https://wrap.sh/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is a high level overview on the experience. Feel free to try it out and let us know what you think at &lt;a href="mailto:hello@wrap.sh"&gt;hello@wrap.sh&lt;/a&gt;&lt;/p&gt;

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

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

</description>
      <category>devops</category>
      <category>reactnative</category>
      <category>cicd</category>
      <category>go</category>
    </item>
  </channel>
</rss>
