<?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: Misha Zaslavskiy</title>
    <description>The latest articles on DEV Community by Misha Zaslavskiy (@misha_zaslavskiy).</description>
    <link>https://dev.to/misha_zaslavskiy</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%2F3451148%2Ff4ec5e02-6772-44c0-893d-276c89629c2c.png</url>
      <title>DEV Community: Misha Zaslavskiy</title>
      <link>https://dev.to/misha_zaslavskiy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/misha_zaslavskiy"/>
    <language>en</language>
    <item>
      <title>To buy or to build - that is the question for a CAD manager</title>
      <dc:creator>Misha Zaslavskiy</dc:creator>
      <pubDate>Fri, 19 Sep 2025 17:52:24 +0000</pubDate>
      <link>https://dev.to/misha_zaslavskiy/to-buy-or-to-build-that-is-the-question-for-a-cad-manager-1m3d</link>
      <guid>https://dev.to/misha_zaslavskiy/to-buy-or-to-build-that-is-the-question-for-a-cad-manager-1m3d</guid>
      <description>&lt;p&gt;I've been asked this question so many times over the years, so I thought I don't need to think about the answer. But maybe the right answer is now different?&lt;/p&gt;

&lt;p&gt;Any semiconductor company needs &lt;strong&gt;a lot&lt;/strong&gt; of CAD tools. And while it's tempting (and rewarding) to develop your own "pet" tool, often this wasn't the best idea. Yes, such a tool will never be available to your competitors, which is a major selling point for the sponsor. With a home-grown tool you have full control over the list of features. Your own company decides how long it should be supported and when it's time to retire or refactor it. And you are insured from a sticker shock during the next EDA (Electronic Design Automation) contract renewal.&lt;/p&gt;

&lt;p&gt;However here is the hard truth: a tool productization and long-term support could easily take 10X more resources than the first viable version. It's exciting to jump into building a cool prototype, and equally easy to underestimate efforts necessary for thorough testing, documentation and trainings. Every home-grown tool adds a long-term support load for the team, and imagine what will happen if the original developer decides to leave the company? There will surely be bugs discovered, new feature requests and evolution of the adjacent tools that provide input and rely on the output. EDA companies are able to spread the cost of this work across many clients, and even then their support and documentation is not always perfect. But unless your company sells EDA tools, my default recommendation was always: buy all the tools that you need and you can afford. There could be exceptions that only prove the general rule, say this tool will be intertwined with the "secret sauce" of your business, or you need something that doesn't exist yet on the market.&lt;/p&gt;

&lt;p&gt;Now if all those arguments make sense, why would I reconsider them now? Well, software development is rapidly changing with AI assist tools like Cursor and Copilot. Whether we like it or not, it's already noticeable in the job market. The cost of SW development is going down, and I think this is also applicable to the long-term support efforts. LLMs are quite good at writing unit tests and documentation. Alternatively with full access to the source code, documentation is not that critical anymore. Instead of sifting through manuals, which could be out-of-date or not comprehensive, the end user could now ask a question in the chat window.&lt;/p&gt;

&lt;p&gt;Here is a practical example to demonstrate this idea. In my recent two jobs I've been involved in the roll-out of IPLM - Intellectual Property Lifecycle Management tool. There is a need to track internal and external IP blocks that go to a semiconductor product. Those blocks form a hierarchical tree with arbitrary depth, and each IP has set of common attributes like provider, revision and IP maturity level (alpha, beta, production), as well as set of unique attributes that are only applicable to specific kind of IPs, like the output voltage for a bandgap, or clock frequency for a CPU core. The goals of IPLM system is to store all this information in the internal database and provide API for IP registration, search mechanism and release/audit capabilities for a product tape-out. And additional value of such tool comes from integration with data repositories, analog and digital development flows, ticketing system, etc. There are commercial IPLM tools available on the market, for example Keysight HUB and Perforce IPLM. They are not cheap, and more importantly integration of those tools in the workflow still requires a substantial amount of effort from the CAD team. An experienced engineer on my team spent couple months setting-up one of them, and it was only possible after we established regular calls with the supplier application engineer. &lt;/p&gt;

&lt;p&gt;As far as I know, there were no specialized open-source IPLM tools available. So I decided to build and share a prototype for the basic IPLM system. The implementation is &lt;code&gt;Python&lt;/code&gt; and &lt;code&gt;MySQL database&lt;/code&gt;, and it has a registry of manufacturing processes, hierarchical IP classification and IP tree. Here is a &lt;a href="https://github.com/mishazaslavskiy/iplm" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The development process looked like this: define architecture, specify requirements, use Cursor AI code assist to do heavy lifting for coding, and iterate to pass tests and fine-tune functionality. The overall process took me ~ 1 week, some of this time spent on setting-up MySQL database, personal GH repo tokens and debugging CI/CD actions. For a project of this scale, you don't even need to spend money on a Cursor subscription, I run out of free tokens when the work was almost complete. Cursor is affordable and geared toward personal usage anyway, that's why I like it, but it's hard to beat free 😄&lt;/p&gt;

&lt;p&gt;In my estimation the amount of effort needed to bring such in-house prototype to production might be less than setting-up a commercial tool, and we could also save on licenses.&lt;/p&gt;

&lt;p&gt;Let me know in the comments below what you think about this experiment. Also if you find this project useful, what new features are the most important for your flow?&lt;/p&gt;

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

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

</description>
      <category>cad</category>
      <category>semiconductors</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Use LLM for EDA licenses analysis</title>
      <dc:creator>Misha Zaslavskiy</dc:creator>
      <pubDate>Thu, 28 Aug 2025 21:52:04 +0000</pubDate>
      <link>https://dev.to/misha_zaslavskiy/use-llm-for-eda-licenses-analysis-48k7</link>
      <guid>https://dev.to/misha_zaslavskiy/use-llm-for-eda-licenses-analysis-48k7</guid>
      <description>&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;If your company has an EDA license monitoring system, you have a lot of useful data available for analysis.&lt;/p&gt;

&lt;p&gt;Now what do we do with this "big-data"? There most likely will be time gaps caused by infrastructure failures/maintenance, as well as evolution of suppliers and available licenses over time, which certainly complicate manual analysis. &lt;/p&gt;

&lt;p&gt;With the advancement of AI/ML tools, you could now connect your Prometheus database with AI assist tool via what's called MCP: Model Context Protocol. This allows LLM to query your database, automatically load relevant and up-to-date information in the context window, and as a result LLM will be able to accurately answer questions about usage, trends or whatever else you are interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;Here is an example how to connect Prometheus DB to &lt;a href="https://cursor.com/en" rel="noopener noreferrer"&gt;Cursor AI code editor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Go to &lt;code&gt;Cursor Settings&lt;/code&gt; -&amp;gt; &lt;code&gt;Tools &amp;amp; Integration&lt;/code&gt; -&amp;gt; &lt;code&gt;New MCP Server&lt;/code&gt; and add this code to the &lt;code&gt;.cursor/mcp.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prometheus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--network"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"cad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"prometheus-mcp-server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="s2"&gt;"-p"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"8000:8000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--rm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"PROMETHEUS_URL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ghcr.io/pab1it0/prometheus-mcp-server:latest"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PROMETHEUS_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://prometheus:9090"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this example uses Docker deployment of MCP server. You don't need to run this container manually, Cursor will do it automatically. For that option you'll obviously need access to Docker, and Prometheus DB should run on the same &lt;code&gt;cad&lt;/code&gt; docker network. If your setup is different, you'll need to modify this JSON file accordingly, see the source reference at the bottom of this post.&lt;/p&gt;

&lt;p&gt;If your MCP tool shows green status and 5 enabled tools like in this snapshot, you are good to go.&lt;/p&gt;

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

&lt;p&gt;Otherwise check the Docker container status and logs. Or you could ask Cursor itself to assist with debugging, it gave me good hints after I renamed Docker network and accidentally broken my setup. If you decide to go this route, make sure to add mcp.json file into the context and be specific that you have issue with MCP tools.&lt;/p&gt;

&lt;p&gt;Now when our MCP tool is up, let's test it. Here is the Cursor chat prompt example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;query available licenses through MCP&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the result:&lt;/p&gt;

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

&lt;p&gt;This table gives accurate summary of all licenses available in my system right now, current usage and overview of the infrastructure. Not a bad summary for beginning, right? Now you could ask about historical usage, deep-dive into specific license utilization, find who are the most active users, or search for anomalies and outliers. And all of this can be done now using natural langue instead of learning PromQL - specialized Prometheus query language. The LLM also shows in the chat window the PromQL queries that were used to obtain necessary information. This could help to speed-up writing code for new dashboards. &lt;/p&gt;

&lt;p&gt;Please keep in mind that LLM output may be not always accurate, so it's a good idea to double check findings independently before acting on them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.descope.com/learn/post/mcp" rel="noopener noreferrer"&gt;What Is the Model Context Protocol (MCP) and How It Works&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://playbooks.com/mcp/pab1it0-prometheus" rel="noopener noreferrer"&gt;Prometheus MCP server&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cad</category>
      <category>mcp</category>
      <category>prometheus</category>
      <category>opensource</category>
    </item>
    <item>
      <title>EDA license utilization dashboard</title>
      <dc:creator>Misha Zaslavskiy</dc:creator>
      <pubDate>Thu, 28 Aug 2025 15:25:57 +0000</pubDate>
      <link>https://dev.to/misha_zaslavskiy/eda-license-utilization-dashboard-2d5c</link>
      <guid>https://dev.to/misha_zaslavskiy/eda-license-utilization-dashboard-2d5c</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nj22766nv9lxevgil6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nj22766nv9lxevgil6b.png" alt=" " width="800" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The 1st post in this series describes installation of the &lt;code&gt;flexlm_exporter&lt;/code&gt; utility with a standard Grafana dashboard. Out-of-the box this dashboard gives very useful historical usage statistic. However I always wanted to see more concise summary. For the contract renewal or license remix, CAD team needs to identify underutilized and overutilized licenses. With the default dashboard this could be a tedious process if your company uses many EDA tools. Moreover EDA companies are not financially interested to make it any easier, and their license scheme is often quite murky. A single tool may use dozens of different licenses depending on the input, tool version, available hardware, phase of the moon, or who knows what else. Some licenses could be used interchangeably for the same run, others can be only used in conjunction with one another, and more often then not, those details are not described in the documentation.&lt;/p&gt;

&lt;p&gt;To simplify long-term utilization analysis, I prepared an additional dashboard. There are 3 graphs so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;weekly average time-series that allows to filter-out the noise from nights/weekends and look for trends&lt;/li&gt;
&lt;li&gt;bar chart with average utilization over the whole plotting period, say the last 6 months&lt;/li&gt;
&lt;li&gt;utilization table with average, peak, zero and 100% usage metrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the &lt;a href="https://grafana.com/grafana/dashboards/24006-eda-license-utilization/" rel="noopener noreferrer"&gt;installation link&lt;/a&gt; from Grafana dashboards library. &lt;/p&gt;

</description>
      <category>cad</category>
      <category>opensource</category>
      <category>grafana</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Licenses monitoring dashboard installation</title>
      <dc:creator>Misha Zaslavskiy</dc:creator>
      <pubDate>Fri, 22 Aug 2025 23:15:30 +0000</pubDate>
      <link>https://dev.to/misha_zaslavskiy/licenses-monitoring-dashboard-installation-32kf</link>
      <guid>https://dev.to/misha_zaslavskiy/licenses-monitoring-dashboard-installation-32kf</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7ga6s8h5vtmnh8guwvn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7ga6s8h5vtmnh8guwvn.png" alt=" " width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;In this post I will share my notes for installation and configuration of 3 open-source tools that together work as an Electronic Design Automation (EDA) license monitoring system. The tools are &lt;code&gt;flexlm_exporter&lt;/code&gt;, &lt;code&gt;Prometheus time-series DB&lt;/code&gt; and &lt;code&gt;Grafana&lt;/code&gt; observability platform. &lt;/p&gt;

&lt;p&gt;While installation of each one of those components separately is well-described in their documentation, I haven't found online any resources that would give full picture how to configure them together and which installation option (cloud, bare metal, docker) to choose. So after some trial-and-error experiments here is a description of functional configuration. Obviously it's not the only viable option, but it could serve as a starting point for further improvements and production deployment in your environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;EDA licenses are expensive, and companies big and small want to optimize their license usage as much as possible. The first step for that is a usage monitoring system that goes beyond standard capabilities of &lt;code&gt;lmstat&lt;/code&gt; utility. It allows to analyze &lt;strong&gt;historical&lt;/strong&gt; license usage and answer essential questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do we have enough licenses of tool X? Ok, if the answer is no, you'll probably get plenty of complains from your hardware designers. But how many extra do we need, or maybe the issue is not the license amount but the infrastructure?&lt;/li&gt;
&lt;li&gt;are we paying for too many licenses of tool Y?&lt;/li&gt;
&lt;li&gt;is there an increase/decrease in demand for tool Z recently?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is crucial information that managers and executives need to define budget for the next EDA contract renewal, and the CAD team needs during regular license remix.&lt;/p&gt;

&lt;p&gt;Some companies choose to write their own system for license monitoring, others use commercially available options. &lt;/p&gt;

&lt;p&gt;In my experience the open source solution described in this post works pretty well. It is reasonably simple to install and maintain and will not break the bank.&lt;/p&gt;

&lt;p&gt;Note that Prometheus DB and Grafana are powerful and multi-purpose tools. Chances are that they are already installed in your organization, and you only need to configure the remaining pieces. Otherwise keep in mind that besides license monitoring, there are many other use cases where Grafana shines: compute cluster performance dashboards, alerts in case of infrastructure issues, collection of PPA and code coverage metrics, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;There are 3 components you'll need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/mjtrangoni/flexlm_exporter" rel="noopener noreferrer"&gt;flexlm_exporter&lt;/a&gt;, kudos to Mario Trangoni for developing and sharing!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt; time series DB&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt; observability platform and &lt;a href="https://grafana.com/grafana/dashboards/3854-flexlm/" rel="noopener noreferrer"&gt;FLEXlm dashboard&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;All 3 applications could be installed directly in your Linux environment or as Docker containers. In my opinion containerized installation is a cleaner way, and it also takes care of most dependencies. So below are the configuration files and gotchas for Docker-based installation.&lt;/p&gt;

&lt;h1&gt;
  
  
  flexlm_exporter
&lt;/h1&gt;

&lt;p&gt;Prepare a YAML configuration file that defines all suppliers/licenses that you'd like to monitor, and paths to license files. Here is the content of my experimental licenses.yaml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;licenses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dirt_cheap_llc&lt;/span&gt; 
    &lt;span class="na"&gt;license_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;/some_path/dirt_cheap_llc.txt&lt;/span&gt;
    &lt;span class="na"&gt;features_to_exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;monitor_users&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
    &lt;span class="na"&gt;monitor_reservations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
    &lt;span class="na"&gt;monitor_versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;False&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arm_and_leg_inc&lt;/span&gt;
    &lt;span class="na"&gt;license_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;/some_path/arm_and_leg_inc.txt&lt;/span&gt;
    &lt;span class="na"&gt;features_to_exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;monitor_users&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
    &lt;span class="na"&gt;monitor_reservations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
    &lt;span class="na"&gt;monitor_versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an executable file with this content and customize your paths before running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOCKER_REPOSITORY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"quay.io/mjtrangoni/flexlm_exporter:latest"&lt;/span&gt;

&lt;span class="c"&gt;# two variables below need to be customized with the actual paths in your network&lt;/span&gt;

&lt;span class="c"&gt;# define path to the directory with lmutil and other license utilities here&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LMUTIL_LOCAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"some_path"&lt;/span&gt;

&lt;span class="c"&gt;# put path to your YAML config file here&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CONFIG_PATH_LOCAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"some_path/licenses.yaml"&lt;/span&gt; 

docker run &lt;span class="nt"&gt;--name&lt;/span&gt; flexlm_exporter &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 9319:9319 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network&lt;/span&gt; cad &lt;span class="nt"&gt;--network-alias&lt;/span&gt; flexlm_exporter &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--volume&lt;/span&gt; &lt;span class="nv"&gt;$LMUTIL_LOCAL&lt;/span&gt;:/usr/bin/flexlm/ &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--volume&lt;/span&gt; &lt;span class="nv"&gt;$CONFIG_PATH_LOCAL&lt;/span&gt;:/home/exporter/config/licenses.yml &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;$DOCKER_REPOSITORY&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt;.lmutil&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/flexlm/lmutil"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--path&lt;/span&gt;.config&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/home/exporter/config/licenses.yml"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;--network cad --network-alias flexlm_exporter&lt;/code&gt; options. This trick helps to connect flexlm_exporter with Prometheus DB. Docker network allows to set aliases, that are more stable and easier to use vs IP addresses. Before executing this file, you'll need to create a new Docker network using those commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create cad
docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it's time to run the executable file and check that flexlm_exporter Docker container is running without issues.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prometheus DB
&lt;/h1&gt;

&lt;p&gt;Prepare configuration prometheus.yml file. This file defines where Prometheus "scrapes" the data from. In  our case we instruct Prometheus to get information from the flexlm_exporter server:port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;flexlm'&lt;/span&gt;
        &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="c1"&gt;# Here you'll need to specify server name and port of the exporter&lt;/span&gt;
&lt;span class="c1"&gt;# The network alias makes this task simple&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;flexlm_exporter:9319'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Customize your path to prometheus.yml configuration file and run Prometheus Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create prometheus-data
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; prometheus &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 9090:9090 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network&lt;/span&gt; cad &lt;span class="nt"&gt;--network-alias&lt;/span&gt; prometheus &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; /some_path/prometheus.yml:/etc/prometheus/prometheus.yml &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; prometheus-data:/prometheus &lt;span class="se"&gt;\&lt;/span&gt;
    prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the 1st &lt;code&gt;docker volume&lt;/code&gt; command, this will make a persistent docker volume to store Prometheus data when container is re-created. Similar volume will be used below to store Grafana dashboards and credentials.&lt;/p&gt;

&lt;h1&gt;
  
  
  Grafana
&lt;/h1&gt;

&lt;p&gt;Here are the commands to make one more Docker volume and run the 3rd container for Grafana:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create grafana-data

docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;grafana &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 &lt;span class="nt"&gt;--network&lt;/span&gt; cad &lt;span class="nt"&gt;--network-alias&lt;/span&gt; grafana &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; grafana-data:/var/lib/grafana grafana/grafana-enterprise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access Grafana, open this URL in your browser: &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To login the 1st time, both your login and password are &lt;code&gt;admin&lt;/code&gt;, then you'll be prompted to change the password.&lt;/p&gt;

&lt;p&gt;Now it's time to to add a new Grafana dashboard. First let's add a Prometheus data source to Grafana. Because we use Docker networks, the Prometheus URL will be &lt;code&gt;http://prometheus:9090&lt;/code&gt;. Go to Connections -&amp;gt; Data Sources -&amp;gt; Add new data source -&amp;gt; Prometheus:&lt;/p&gt;

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

&lt;p&gt;Then go to Dashboards -&amp;gt; New -&amp;gt; Import, and paste this URL: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://grafana.com/grafana/dashboards/3854-flexlm/&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;And select Prometheus as the data source. Note that if you don't see a valid Prometheus DB in the selection box, you might need to refresh your browser window before this step.&lt;/p&gt;

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

&lt;p&gt;If all parts work properly, now you will see historical license usage in your dashboard, like shown in the very first image at the top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;Here are useful commands that will help with debugging.&lt;/p&gt;

&lt;p&gt;List running docker containers with &lt;code&gt;docker ps&lt;/code&gt; command. There should be 3 containers running (Status=UP)&lt;/p&gt;

&lt;p&gt;If any of the containers is not running, use &lt;code&gt;docker logs &amp;lt;container_name&amp;gt;&lt;/code&gt; to see the diagnostic.&lt;/p&gt;

&lt;p&gt;Another option is to try accessing flexlm_exporter and Prometheus DB in Web browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://localhost:9319/" rel="noopener noreferrer"&gt;http://localhost:9319/&lt;/a&gt; - flexlm_exporter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here you could follow &lt;code&gt;Metrics&lt;/code&gt; link. When exporter works as expected, there will be information like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# TYPE flexlm_feature_issued gauge&lt;/span&gt;
&lt;span class="s"&gt;flexlm_feature_issued{app="arm_and_leg_inc",name="feature1"} &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;# HELP flexlm_feature_used License feature used labeled by app and feature name of the license.&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE flexlm_feature_used gauge&lt;/span&gt;
&lt;span class="s"&gt;flexlm_feature_used{app="arm_and_leg_inc",name="feature1"} &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;# HELP flexlm_feature_used_users License feature used by user labeled by app, feature name and username of the license.&lt;/span&gt;
&lt;span class="c1"&gt;# TYPE flexlm_feature_used_users gauge&lt;/span&gt;
&lt;span class="s"&gt;flexlm_feature_used_users{app="arm_and_leg_inc",name="feature1",since="1729442400",user="user1"} &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://localhost:9090/query" rel="noopener noreferrer"&gt;http://localhost:9090/query&lt;/a&gt; - Prometheus DB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first check is that URL is accessible. Then the following queries should work and respond with your license usage info:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;up
flexlm_server_status
flexlm_feature_issued
flexlm_feature_used
flexlm_feature_used_users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cad</category>
      <category>grafana</category>
      <category>prometheus</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
