{"id":46829,"date":"2025-03-20T00:00:00","date_gmt":"2025-03-20T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/"},"modified":"2025-11-13T12:57:17","modified_gmt":"2025-11-13T20:57:17","slug":"optimizing-software-development-vcs-activity-monitoring-with-griddb","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/","title":{"rendered":"Optimizing Software Development: VCS Activity Monitoring with GridDB"},"content":{"rendered":"<h2><strong>Introduction<\/strong><\/h2>\n<p>In today&#8217;s competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving this is monitoring developer activity in Version Control Systems (VCS) to optimize collaboration and code quality. By analyzing patterns in code commits, pull requests, merges, and branching, organizations can identify bottlenecks, improve workflows, and ultimately boost productivity.<\/p>\n<p>Popular VCS tools such as Git, SVN, and GitLab allow teams to track changes, but analyzing large-scale development activities over time can be challenging. This is where GridDB, a high-performance time-series database, proves invaluable. Specifically designed to manage vast amounts of time-sensitive data, GridDB enables teams to efficiently capture, store, and analyze VCS events.<\/p>\n<h3><strong>Why Use GridDB for VCS Activity Monitoring?<\/strong><\/h3>\n<p><strong>Time-Stamped Data Handling<\/strong> \u00a0<br \/>\nEach commit, pull request, and merge event in a VCS is tied to a specific timestamp. GridDB is optimized for time-series data, making it ideal for capturing and analyzing time-sensitive developer activities.<\/p>\n<p><strong>Scalability<\/strong> \u00a0<br \/>\nIn large, distributed teams, thousands of commits and pull requests may occur daily. GridDB\u2019s scalable architecture ensures that even large volumes of VCS events can be ingested and queried efficiently, without performance degradation.<\/p>\n<p><strong>Efficient Data Retrieval<\/strong> \u00a0<br \/>\nGridDB allows time-based queries to quickly retrieve developer activities over specific periods (e.g., daily, weekly, monthly), providing real-time insights into team productivity and collaboration.<\/p>\n<p><strong>Historical Insights<\/strong> \u00a0<br \/>\nBy analyzing past events\u2014such as spikes in code conflicts or periods of low activity\u2014teams can uncover patterns that lead to more efficient workflows. GridDB\u2019s ability to store and query historical data facilitates in-depth analysis of development trends.<\/p>\n<p>In this blog, we\u2019ll explore how to monitor <strong>Version Control System (VCS) Activity<\/strong> using GridDB with a simple spring boot project. Specifically, we\u2019ll track key development events such as:<\/p>\n<ul>\n<li>Code commits<\/li>\n<li>Pull requests<\/li>\n<li>Code merges<\/li>\n<\/ul>\n<p>By storing and analyzing this data with GridDB, software teams, and project managers can:<\/p>\n<ul>\n<li>Monitor developer productivity by tracking code changes over time.<\/li>\n<li>Identify patterns such as merge conflicts or periods of high\/low activity.<\/li>\n<li>Optimize collaboration by evaluating branching strategies and pull request workflows.<\/li>\n<li>Perform historical analysis to improve long-term development trends and practices.<\/li>\n<\/ul>\n<h2>Setting Up GridDB Cluster and Spring Boot Integration: For Real-Time Monitoring<\/h2>\n<p>The first step is to set up a GridDB cluster and integrate it with our Spring Boot application as follows.<\/p>\n<ul>\n<li><strong>Source Code for this Project<\/strong><\/li>\n<\/ul>\n<p>You can clone the GridDBnet blogs repo and grab the apporipriate branch for the source code.<\/p>\n<p><code>$ git clone https:\/\/github.com\/griddbnet\/Blogs.git --branch vcs<\/code><\/p>\n<ul>\n<li><strong>Setting up GridDB Cluster<\/strong><\/li>\n<\/ul>\n<p>GridDB provides flexible options to meet different requirements. For development, a single-node cluster on our local machine may be sufficient. However, in production, distributed clusters across multiple machines are typically preferred for improved fault tolerance and scalability. For detailed guidance on setting up clusters based on our deployment strategy, refer to the GridDB documentation.<\/p>\n<p>To set up a GridDB cluster, follow the steps mentioned <a href=\"https:\/\/docs.griddb.net\/gettingstarted\/using-apt\/#install-with-apt-get\">here<\/a>.<\/p>\n<ul>\n<li><strong>Setting up Spring Boot Application<\/strong><\/li>\n<\/ul>\n<p>Once ourGridDB cluster is operational, the next step is connecting it to ourSpring Boot application. The GridDB Java Client API provides the necessary tools to establish this connection. To simplify the process, you can include the <code>griddb-spring-boot-starter<\/code> library as a dependency in our project, which offers pre-configured beans for a streamlined connection setup.<\/p>\n<p><strong>Project Structure<\/strong><\/p>\n<p>Here&#8217;s a suggested project structure for such an application:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">\u251c\u2500\u2500\u2500my-griddb-app\n\u2502 \u00a0 \u2502 \u00a0 pom.xml\n\u2502 \u00a0 \u2502 \u00a0 \n\u2502 \u00a0 \u251c\u2500\u2500\u2500src\n\u2502 \u00a0 \u2502 \u00a0 \u251c\u2500\u2500\u2500main\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u251c\u2500\u2500\u2500java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2514\u2500\u2500\u2500mycode\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502 \u00a0 MySpringBootApplication.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u251c\u2500\u2500\u2500config\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 GridDBConfig.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u251c\u2500\u2500\u2500controller\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 ChartController.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u251c\u2500\u2500\u2500dto\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 VcsActivityDTO.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2514\u2500\u2500\u2500service\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ChartService.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 MetricsCollectionService.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RestTemplateConfig.java\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2502\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u2514\u2500\u2500\u2500resources\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502 \u00a0 application.properties\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2502\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u2514\u2500\u2500\u2500templates\n\u2502 \u00a0 \u2502 \u00a0 \u2502 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 charts.html<\/code><\/pre>\n<\/div>\n<p>This structure separates controllers, models, repositories, services, and the application entry point into distinct layers, enhancing modularity and maintainability.<\/p>\n<p><strong>Add GridDB Dependency<\/strong><\/p>\n<p>To enable interaction with GridDB in our Spring Boot project, we must include the GridDB Java Client API dependency. This can be accomplished by adding the appropriate configuration to the project build file, such as <code>pom.xml<\/code> for Maven or the equivalent file for Gradle.<\/p>\n<p>Here&#8217;s an example of how to configure the dependency in the<code>pom.xml<\/code> file:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">&lt;project \n\u00a0 xmlns_xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n\u00a0 xsi_schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\n\u00a0 &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n\u00a0 &lt;groupId&gt;com.example&lt;\/groupId&gt;\n\u00a0 &lt;artifactId&gt;my-griddb-app&lt;\/artifactId&gt;\n\u00a0 &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\n\u00a0 &lt;name&gt;my-griddb-app&lt;\/name&gt;\n\u00a0 &lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\n\n\u00a0 &lt;parent&gt;\n\u00a0 \u00a0 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n\u00a0 \u00a0 &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;\n\u00a0 \u00a0 &lt;version&gt;3.2.4&lt;\/version&gt;\n\u00a0 \u00a0 &lt;relativePath \/&gt; &lt;!-- lookup parent from repository --&gt;\n\u00a0 &lt;\/parent&gt;\n\n\u00a0 &lt;properties&gt;\n\u00a0 \u00a0 &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;\n\u00a0 \u00a0 &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;\n\u00a0 &lt;\/properties&gt;\n\n\u00a0 &lt;dependencies&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;spring-boot-starter-actuator&lt;\/artifactId&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;junit&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;junit&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 &lt;version&gt;3.8.1&lt;\/version&gt;\n\u00a0 \u00a0 \u00a0 &lt;scope&gt;test&lt;\/scope&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;com.github.griddb&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;gridstore&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 &lt;version&gt;5.6.0&lt;\/version&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;!-- Spring Boot dependencies --&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 &lt;exclusions&gt;\n\u00a0 \u00a0 \u00a0 \u00a0 &lt;exclusion&gt;\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &lt;artifactId&gt;spring-boot-starter-logging&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 \u00a0 &lt;\/exclusion&gt;\n\u00a0 \u00a0 \u00a0 &lt;\/exclusions&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 &lt;scope&gt;test&lt;\/scope&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;\/artifactId&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;!-- JSON processing --&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;jackson-databind&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 &lt;version&gt;2.15.0&lt;\/version&gt; &lt;!-- or the latest version --&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 \u00a0 &lt;!-- Lombok --&gt;\n\u00a0 \u00a0 &lt;dependency&gt;\n\u00a0 \u00a0 \u00a0 &lt;groupId&gt;org.projectlombok&lt;\/groupId&gt;\n\u00a0 \u00a0 \u00a0 &lt;artifactId&gt;lombok&lt;\/artifactId&gt;\n\u00a0 \u00a0 \u00a0 &lt;optional&gt;true&lt;\/optional&gt;\n\u00a0 \u00a0 &lt;\/dependency&gt;\n\u00a0 &lt;\/dependencies&gt;\n&lt;\/project&gt;<\/code><\/pre>\n<\/div>\n<p><strong>Generate GitHub API Access Token<\/strong><\/p>\n<p>To access GitHub data such as commits and pull requests, you&#8217;ll need a <strong>GitHub Personal Access Token<\/strong>. Follow the instructions in the official GitHub documentation to create one:<\/p>\n<ol>\n<li>Log in to GitHub.<\/li>\n<li>Navigate to the <a href=\"https:\/\/docs.github.com\/en\/enterprise-server@3.3\/authentication\/keeping-your-account-and-data-secure\/creating-a-personal-access-token\"><strong>GitHub Personal Access Token Documentation<\/strong><\/a>.<\/li>\n<li>Follow the steps to generate a token with the necessary scopes (<code>repo<\/code>, <code>user<\/code>).<\/li>\n<\/ol>\n<p><strong>Configure GridDB Connection<\/strong><\/p>\n<p>After adding the GridDB dependency, the next step is configuring the connection details for our GridDB cluster in our Spring Boot application. This is usually configured in the <code>application.properties<\/code> file, where you can specify various settings for the application.<\/p>\n<p>Here\u2019s a quick example of how to set up those connection details:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">GRIDDB_NOTIFICATION_MEMBER=127.0.0.1:10001\nGRIDDB_CLUSTER_NAME=myCluster\nGRIDDB_USER=admin\nGRIDDB_PASSWORD=admin\nmanagement.endpoints.web.exposure.include=*\nserver.port=9090\n\n\n# GitHub API token and configuration\ngithub.api.token=github_DXXXXXXXXXXXXA5OyZwdXr\ngithub.api.base-url=https:\/\/api.github.com<\/code><\/pre>\n<\/div>\n<ul>\n<li><code>griddb.cluster.host<\/code>: The hostname or IP address of ourGridDB cluster.<\/li>\n<li><code>griddb.cluster.port<\/code>: The port number on which the GridDB cluster is listening.<\/li>\n<li><code>griddb.cluster.user<\/code>: The username for accessing the GridDB cluster.<\/li>\n<li><code>griddb.cluster.password<\/code>: The password for the specified GridDB user (replace with ouractual password).<\/li>\n<li><code>server.port=9090<\/code>: Sets the port on which ourSpring Boot application will run.<\/li>\n<li><code>github.api.token<\/code>: The personal access token for authenticating with the GitHub API, as generated<\/li>\n<li><code>github.api.base-url<\/code>: The base URL for making requests to the GitHub API (e.g., <code>https:\/\/api.github.com<\/code>).<\/li>\n<\/ul>\n<p><strong>Create GridDB Client Bean<\/strong><\/p>\n<p>To interact effectively with GridDB in our Spring Boot application,we need to create a dedicated Spring Bean to manage the GridDB connection. This bean will establish the connection using the parameters defined in the <code>application.properties<\/code> file and will act as the central interface for interacting with the GridDB cluster across the application.<\/p>\n<p>Here&#8217;s an example of how to define this bean in a Java class named <code>GridDbConfig.java<\/code>:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.config;\n\nimport java.util.Properties;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.PropertySource;\n\nimport com.toshiba.mwcloud.gs.GSException;\nimport com.toshiba.mwcloud.gs.GridStore;\nimport com.toshiba.mwcloud.gs.GridStoreFactory;\n\n@Configuration\n@PropertySource(\"classpath:application.properties\")\npublic class GridDBConfig {\n\n @Value(\"${GRIDDB_NOTIFICATION_MEMBER}\")\n\u00a0 private String notificationMember;\n\n @Value(\"${GRIDDB_CLUSTER_NAME}\")\n\u00a0 private String clusterName;\n\n @Value(\"${GRIDDB_USER}\")\n\u00a0 private String user;\n\n @Value(\"${GRIDDB_PASSWORD}\")\n\u00a0 private String password;\n\n @Bean\n\u00a0 public GridStore gridStore() throws GSException {\n\u00a0 \u00a0 \/\/ Acquiring a GridStore instance\n\u00a0 \u00a0 Properties properties = new Properties();\n\u00a0 \u00a0 properties.setProperty(\"notificationMember\", notificationMember);\n\u00a0 \u00a0 properties.setProperty(\"clusterName\", clusterName);\n\u00a0 \u00a0 properties.setProperty(\"user\", user);\n\u00a0 \u00a0 properties.setProperty(\"password\", password);\n\u00a0 \u00a0 return GridStoreFactory.getInstance().getGridStore(properties);\n }\n}<\/code><\/pre>\n<\/div>\n<h2>Metric Collection<\/h2>\n<p>Next, we will focus on collecting, transforming, and storing GitHub data for real-time VCS activity monitoring. The key metrics we&#8217;ll be tracking include <code>commits<\/code>, <code>pull requests<\/code>, and other GitHub events that provide insights into developer productivity and project activity.<\/p>\n<p>To collect the necessary data, we utilize specific API endpoints provided by GitHub. These endpoints allow us to track various development activities:<\/p>\n<ul>\n<li>\n<p><strong>Commits<\/strong>: Accessed via the endpoint <code>GET \/repos\/{owner}\/{repo}\/commits<\/code>, this provides a list of commits in a specified repository.<\/p>\n<\/li>\n<li>\n<p><strong>Pull Requests<\/strong>: The endpoint <code>GET \/repos\/{owner}\/{repo}\/pulls<\/code> returns information on pull requests, including their current status.<\/p>\n<\/li>\n<li>\n<p><strong>Repository Events<\/strong>: We can retrieve a comprehensive list of events using the endpoint <code>GET \/repos\/{owner}\/{repo}\/events<\/code>. This encompasses all significant actions within the repository.<\/p>\n<\/li>\n<\/ul>\n<p><strong>Loading Data into GridDB<\/strong><\/p>\n<p>Once the required data is collected from GitHub, the next step is to load this information into GridDB for storage and further analysis. Here\u2019s a high-level overview of the process:<\/p>\n<p>Here\u2019s a high-level overview of the process:<\/p>\n<ul>\n<li><strong>Authentication<\/strong>: We begin by authenticating with GitHub\u2019s API using an access token. This token ensures that our requests are authorized and can retrieve the necessary data. Therefore, we will set the header as follows for our API calls.<\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">\u00a0 private HttpHeaders createHeaders() {\n\u00a0 \u00a0 HttpHeaders headers = new HttpHeaders();\n\u00a0 \u00a0 headers.set(\"Authorization\", \"Bearer \" + githubApiToken);\n\u00a0 \u00a0 return headers;\n }<\/code><\/pre>\n<\/div>\n<ul>\n<li><strong>Data Transformation and Mapping<\/strong>: After retrieval, the data will undergo transformation to align with the schema defined in GridDB. This step involves cleaning the data, filtering out irrelevant information, and mapping it to the appropriate fields within GridDB. Here is our <code>VcsActivityDTO<\/code>which is how our data will be stored in db.<\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.dto;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport java.util.Date;\n\nimport com.toshiba.mwcloud.gs.RowKey;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class VcsActivityDTO {\n @RowKey\n\u00a0 public Date timestamp; \/\/ Time of the activity\n\u00a0 private String eventType; \/\/ Event type: commit, pull request, merge, branch\n\u00a0 private String developerId; \/\/ Developer who performed the activity\n\u00a0 private String repositoryId; \/\/ Repository ID or name\n\u00a0 private String branch; \/\/ Branch associated with the activity\n\u00a0 private String status; \/\/ Status (e.g., success, open, merged, conflict)\n}<\/code><\/pre>\n<\/div>\n<ul>\n<li><strong>Data Ingestion<\/strong>: Finally, the transformed data will be loaded into GridDB, where it can be accessed for real-time monitoring and analysis of developer activities.<br \/>\nWe will insert the data into our database as follows:<\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">\u00a0 \u00a0TimeSeries<VcsActivityDTO> ts = store.putTimeSeries(\"vcsData\", VcsActivityDTO.class);\n\u00a0 \u00a0 for (VcsActivityDTO activity : result) {\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 \u00a0 ts.append(activity);\n }<\/code><\/pre>\n<\/div>\n<p>Below is the complete <code>MetricsCollectionService.java<\/code>, which implements all the aforementioned steps.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.service;\n\nimport java.util.ArrayList;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.util.UriComponentsBuilder;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.JsonMappingException;\nimport com.toshiba.mwcloud.gs.*;\nimport mycode.dto.VcsActivityDTO;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.List;\nimport java.util.Map;\n\n@Service\npublic class MetricsCollectionService {\n @Autowired\n\u00a0 GridStore store;\n\n @Autowired\n\u00a0 RestTemplate restTemplate;\n\n @Value(\"${github.api.token}\")\n\u00a0 private String githubApiToken;\n\n @Value(\"${github.api.base-url}\")\n\u00a0 private String githubBaseUrl;\n\n @Scheduled(fixedRate = 2222260) \/\/ Collect metrics every minute\n\u00a0 public void collectMetrics() throws GSException, JsonMappingException, JsonProcessingException, ParseException {\n\u00a0 \u00a0 String repoOwner = \"microsoft\"; \n\u00a0 \u00a0 String repoName = \"vscode\"; \n\n\u00a0 \u00a0 List<VcsActivityDTO> commits = getCommits(repoOwner, repoName);\n\u00a0 \u00a0List<VcsActivityDTO> pullRequests = getPullRequests(repoOwner, repoName);\n\u00a0 \u00a0 List<VcsActivityDTO> branchEvents = getBranchEvents(repoOwner, repoName);\n\n\u00a0 \u00a0System.out.println(\"Collected Commits: \" + commits.size());\n\u00a0 \u00a0System.out.println(\"Collected Pull Requests: \" + pullRequests.size());\n\u00a0 \u00a0 System.out.println(\"Collected Pull Requests: \" + branchEvents.size());\n\u00a0 \u00a0 List<VcsActivityDTO> result = new ArrayList<>();\n\u00a0 \u00a0 result.addAll(commits);\n\u00a0 \u00a0 result.addAll(pullRequests);\n\u00a0 \u00a0 result.addAll(branchEvents);\n\u00a0 \u00a0 TimeSeries<VcsActivityDTO> ts = store.putTimeSeries(\"vcsData\", VcsActivityDTO.class);\n\u00a0 \u00a0 for (VcsActivityDTO activity : result) {\n\u00a0 \u00a0 \u00a0 \u00a0 ts.append(activity);\n }\n }\n\n\u00a0 private HttpHeaders createHeaders() {\n\u00a0 \u00a0 HttpHeaders headers = new HttpHeaders();\n\u00a0 \u00a0 headers.set(\"Authorization\", \"Bearer \" + githubApiToken);\n\u00a0 \u00a0 return headers;\n }\n\n\u00a0 \/\/ Method to retrieve commits from a specific repository\n\u00a0 public List<VcsActivityDTO> getCommits(String repoOwner, String repoName) throws ParseException {\n\u00a0 \u00a0 String url = UriComponentsBuilder.fromHttpUrl(githubBaseUrl)\n .path(\"\/repos\/{owner}\/{repo}\/commits\")\n .buildAndExpand(repoOwner, repoName)\n .toUriString();\n\n\u00a0 \u00a0 HttpHeaders headers = createHeaders();\n\u00a0 \u00a0 HttpEntity<String> entity = new HttpEntity<>(headers);\n\n\u00a0 \u00a0 ResponseEntity<List> response = restTemplate.exchange(url, HttpMethod.GET, entity, List.class);\n\u00a0 \u00a0 List<VcsActivityDTO> commitActivities = new ArrayList<>();\n\n\u00a0 \u00a0 List<Map<String, Object>> commits = (List<Map<String, Object>>) response.getBody();\n\u00a0 \u00a0 if (commits != null) {\n\u00a0 \u00a0 \u00a0 for (Map<String, Object> commit : commits) {\n\u00a0 \u00a0 \u00a0 \u00a0 commitActivities.add(mapCommitToVcsActivityDTO(commit));\n }\n }\n\n\u00a0 \u00a0 return commitActivities;\n }\n\n\u00a0 public List<VcsActivityDTO> getPullRequests(String repoOwner, String repoName) throws ParseException {\n\u00a0 \u00a0 String url = UriComponentsBuilder.fromHttpUrl(githubBaseUrl)\n .path(\"\/repos\/{owner}\/{repo}\/pulls\")\n .queryParam(\"state\", \"all\") \/\/ Retrieves both open and closed pull requests\n .buildAndExpand(repoOwner, repoName)\n .toUriString();\n\n\u00a0 \u00a0 HttpHeaders headers = createHeaders();\n\u00a0 \u00a0 HttpEntity<String> entity = new HttpEntity<>(headers);\n\n\u00a0 \u00a0 ResponseEntity<List> response = restTemplate.exchange(url, HttpMethod.GET, entity, List.class);\n\u00a0 \u00a0 List<VcsActivityDTO> prActivities = new ArrayList<>();\n\n\u00a0 \u00a0 List<Map<String, Object>> pullRequests = (List<Map<String, Object>>) response.getBody();\n\u00a0 \u00a0 if (pullRequests != null) {\n\u00a0 \u00a0 \u00a0 for (Map<String, Object> pr : pullRequests) {\n\u00a0 \u00a0 \u00a0 \u00a0 prActivities.add(mapPullRequestToVcsActivityDTO(pr));\n }\n }\n\n\u00a0 \u00a0 return prActivities;\n }\n\n\u00a0 private VcsActivityDTO mapCommitToVcsActivityDTO(Map<String, Object> commitData) throws ParseException {\n\u00a0 \u00a0 Map<String, Object> commitInfo = (Map<String, Object>) commitData.get(\"commit\");\n\u00a0 \u00a0 Map<String, Object> authorInfo = (Map<String, Object>) commitInfo.get(\"author\");\n\n\u00a0 \u00a0 String eventType = \"Commit\";\n\u00a0 \u00a0 String developerId = (String) authorInfo.get(\"name\");\n\u00a0 \u00a0 String repositoryId = (String) commitInfo.get(\"url\"); \n\u00a0 \u00a0 String branch = \"main\"; \n\u00a0 \u00a0 String status = \"Success\";\n\u00a0 \u00a0 String timestamp = (String) authorInfo.get(\"date\");\n\n\u00a0 \u00a0 return new VcsActivityDTO(new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\").parse(timestamp), eventType, developerId, repositoryId, branch, status);\n }\n\n\u00a0 private VcsActivityDTO mapPullRequestToVcsActivityDTO(Map<String, Object> prData) throws ParseException {\n\u00a0 \u00a0 String eventType = \"Pull Request\";\n\u00a0 \u00a0 Map<String, Object> userInfo = (Map<String, Object>) prData.get(\"user\");\n\u00a0 \u00a0 String developerId = (String) userInfo.get(\"login\");\n\u00a0 \u00a0 String repositoryId = (String) userInfo.get(\"repos_url\");; \n\u00a0 \u00a0 String branch = (String) ((Map<String, Object>)prData.get(\"base\")).get(\"ref\"); \n\u00a0 \u00a0 String status = (String) prData.get(\"state\"); \n\u00a0 \u00a0 String timestamp = (String) prData.get(\"created_at\");\n\u00a0 \u00a0 return new VcsActivityDTO(new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\").parse(timestamp), eventType, developerId, repositoryId, branch, status);\n }\n\n\u00a0 public List<VcsActivityDTO> getBranchEvents(String repoOwner, String repoName) throws ParseException{\n\u00a0 \u00a0 String url = UriComponentsBuilder.fromHttpUrl(githubBaseUrl)\n .path(\"\/repos\/{owner}\/{repo}\/events\")\n .buildAndExpand(repoOwner, repoName)\n .toUriString();\n\n\u00a0 \u00a0 HttpHeaders headers = createHeaders();\n\u00a0 \u00a0 HttpEntity<String> entity = new HttpEntity<>(headers);\n\n\u00a0 \u00a0 ResponseEntity<List> response = restTemplate.exchange(url, HttpMethod.GET, entity, List.class);\n\u00a0 \u00a0 List<VcsActivityDTO> branchActivities = new ArrayList<>();\n\n\u00a0 \u00a0 List<Map<String, Object>> events = response.getBody();\n\u00a0 \u00a0 if (events != null) {\n\u00a0 \u00a0 \u00a0 for (Map<String, Object> eventData : events) {\n\u00a0 \u00a0 \u00a0 \u00a0 String eventType = (String) eventData.get(\"type\");\n\u00a0 \u00a0 \u00a0 \u00a0 if (\"CreateEvent\".equals(eventType) || \"DeleteEvent\".equals(eventType)) {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Map<String, Object> payload = (Map<String, Object>) eventData.get(\"payload\");\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String refType = (String) payload.get(\"ref_type\");\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (\"branch\".equals(refType)) {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String branchName = (String) payload.get(\"ref\");\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String developerId = (String) ((Map<String, Object>)eventData.get(\"actor\")).get(\"login\"); \u00a0\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String timestamp = (String) eventData.get(\"created_at\");\n\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Map to VcsActivityDTO\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VcsActivityDTO activity = new VcsActivityDTO(new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\").parse(timestamp),\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 eventType.equals(\"CreateEvent\") ? \"Branch Creation\" : \"Branch Deletion\",\n developerId,\n repoName,\n branchName,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"Success\"\n );\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 branchActivities.add(activity);\n }\n }\n }\n }\n\u00a0 \u00a0 return branchActivities;\n }\n\n}<\/code><\/pre>\n<\/div>\n<p>By following above steps, we can effectively extract data on developer activities from github, load it into GridDB.<\/p>\n<h2><strong>Data Querying in GridDB and Visualization with Thymeleaf<\/strong><\/h2>\n<p>Once the data is stored and available in GridDB, the next step is to visualize this data in a way that provides actionable insights.<\/p>\n<p>In this section, we\u2019ll explore how to build a dashboard using Spring Boot, <code>Thymeleaf<\/code>, and <code>Chart.js<\/code> to render charts that display commits and pull request trends over time.<\/p>\n<p>Here are the steps to achieve this:<\/p>\n<ul>\n<li><strong>Building the Chart Controller<\/strong><\/li>\n<\/ul>\n<p>The <code>ChartController<\/code> acts as the intermediary between backend data in GridDB and the frontend visualizations displayed on the dashboard. Its responsibilities include handling HTTP requests, interacting with the service layer to fetch data, and passing that data to Thymeleaf templates for rendering.<\/p>\n<p>Here\u2019s how the <code>ChartController<\/code> is implemented:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.controller;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\n\nimport mycode.service.ChartService;\nimport mycode.dto.VcsActivityDTO;\n\nimport java.text.SimpleDateFormat;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@Controller\npublic class ChartController {\n\n @Autowired\n\u00a0 ChartService chartService;\n\n @Autowired\n\u00a0 private ObjectMapper objectMapper;\n\n @GetMapping(\"\/charts\")\n\u00a0 public String showCharts(Model model) {\n\u00a0 \u00a0 try {\n\u00a0 \u00a0 \u00a0 List<VcsActivityDTO> events = chartService.getVcsEvents();\n\u00a0 \u00a0 \u00a0 model.addAttribute(\"events\", events);\n\n\u00a0 \u00a0 \u00a0 \/\/ Prepare data for charts\n\u00a0 \u00a0 \u00a0 Map<String, Integer> commitData = prepareCommitData(events);\n\u00a0 \u00a0 \u00a0 Map<String, Integer> prData = preparePullRequestData(events);\n\n\u00a0 \u00a0 \u00a0 \/\/ Convert Maps to JSON Strings for use in JavaScript in the Thymeleaf template\n\u00a0 \u00a0 \u00a0 String commitDataJson = objectMapper.writeValueAsString(commitData);\n\u00a0 \u00a0 \u00a0 String prDataJson = objectMapper.writeValueAsString(prData);\n\n\u00a0 \u00a0 \u00a0 model.addAttribute(\"commitDataJson\", commitDataJson);\n\u00a0 \u00a0 \u00a0 model.addAttribute(\"prDataJson\", prDataJson);\n\n } catch (Exception e) {\n\u00a0 \u00a0 \u00a0 e.printStackTrace();\n }\n\u00a0 \u00a0 return \"charts\";\n }\n\n\u00a0 private Map<String, Integer> prepareCommitData(List<VcsActivityDTO> events) {\n\u00a0 \u00a0 Map<String, Integer> commitMap = new HashMap<>();\n\u00a0 \u00a0 SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd\"); \n\n\u00a0 \u00a0 for (VcsActivityDTO event : events) {\n\u00a0 \u00a0 \u00a0 if (\"Commit\".equals(event.getEventType())) {\n\u00a0 \u00a0 \u00a0 \u00a0 String timestamp = dateFormat.format(event.getTimestamp());\n\u00a0 \u00a0 \u00a0 \u00a0 commitMap.put(timestamp, commitMap.getOrDefault(timestamp, 0) + 1);\n }\n }\n\u00a0 \u00a0 return commitMap;\n }\n\n\u00a0 private Map<String, Integer> preparePullRequestData(List<VcsActivityDTO> events) {\n\u00a0 \u00a0 Map<String, Integer> prMap = new HashMap<>();\n\u00a0 \u00a0 SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd\"); \/\/ Date format\n\n\u00a0 \u00a0 for (VcsActivityDTO event : events) {\n\u00a0 \u00a0 \u00a0 if (\"Pull Request\".equals(event.getEventType())) {\n\u00a0 \u00a0 \u00a0 \u00a0 String timestamp = dateFormat.format(event.getTimestamp()); \n\u00a0 \u00a0 \u00a0 \u00a0 prMap.put(timestamp, prMap.getOrDefault(timestamp, 0) + 1);\n }\n }\n\u00a0 \u00a0 return prMap;\n }\n}<\/code><\/pre>\n<\/div>\n<ul>\n<li><strong>Implementing the Chart Service<\/strong><\/li>\n<\/ul>\n<p>The <code>ChartService<\/code> acts as the business logic layer, encapsulating the operations needed to query GridDB and process the results.<\/p>\n<p>The <code>ChartService<\/code> class retrieves VCS (Version Control System) events from a GridStore database container called <code>\"vcsData\"<\/code>. The service processes each row of the result, mapping fields like <code>Timestamp<\/code>, <code>EventType<\/code>, <code>DeveloperId<\/code>, <code>RepositoryId<\/code>, <code>Branch<\/code>, and <code>Status<\/code> into a <code>VcsActivityDTO<\/code> object. Finally, it returns a list of these DTOs representing the VCS activity events.<\/p>\n<p>Here\u2019s how the <code>ChartService<\/code> is implemented:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.service;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.toshiba.mwcloud.gs.Container;\nimport com.toshiba.mwcloud.gs.GridStore;\nimport com.toshiba.mwcloud.gs.Query;\nimport com.toshiba.mwcloud.gs.Row;\nimport com.toshiba.mwcloud.gs.RowSet;\n\nimport mycode.dto.VcsActivityDTO;\n\n@Service\npublic class ChartService {\n\n @Autowired\n\u00a0 GridStore store;\n\n\u00a0 public List<VcsActivityDTO> getVcsEvents() throws Exception {\n\n\u00a0 \u00a0 Container<?, Row> container = store.getContainer(\"vcsData\");\n\u00a0 \u00a0 if (container == null) {\n\u00a0 \u00a0 \u00a0 throw new Exception(\"Container not found.\");\n }\n\u00a0 \u00a0 List<VcsActivityDTO> eventList = new ArrayList<>();\n\n\n\u00a0 \u00a0 SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\");\n\u00a0 \u00a0 Date now = new Date();\n\n\u00a0 \u00a0 String nowString = dateFormat.format(now);\n\u00a0 \u00a0 String startTime = \"1971-12-23T18:18:52.000Z\";\n\n\u00a0 \u00a0 String queryString = \"select * where Timestamp >= TIMESTAMP('\" + startTime\n + \"') and Timestamp <= TIMESTAMP('\" + nowString + \"')\";\n\u00a0 \u00a0 Query<Row> query = container.query(queryString);\n\u00a0 \u00a0 RowSet<Row> rs = query.fetch();\n\n\u00a0 \u00a0 while (rs.hasNext()) {\n\u00a0 \u00a0 \u00a0 Row row = rs.next();\n\u00a0 \u00a0 \u00a0 VcsActivityDTO event = new VcsActivityDTO();\n\u00a0 \u00a0 \u00a0 event.setTimestamp(row.getTimestamp(0));\n\u00a0 \u00a0 \u00a0 event.setEventType(row.getString(2));\n\u00a0 \u00a0 \u00a0 event.setDeveloperId(row.getString(3));\n\u00a0 \u00a0 \u00a0 event.setRepositoryId(row.getString(4));\n\u00a0 \u00a0 \u00a0 event.setBranch(row.getString(5));\n\u00a0 \u00a0 \u00a0 event.setStatus(row.getString(1));\n\u00a0 \u00a0 \u00a0 eventList.add(event);\n\n }\n\u00a0 \u00a0 return eventList;\n }\n\n}<\/code><\/pre>\n<\/div>\n<ul>\n<li><strong>Rendering Charts with Thymeleaf<\/strong><\/li>\n<\/ul>\n<p>With the data fetched and processed, the final step is to render the charts on the dashboard using Thymeleaf templates. Thymeleaf allows you to seamlessly integrate backend data into HTML views, making it a great choice for dynamic, data-driven applications.<\/p>\n<p>Below is the implementation of <code>charts.html<\/code>:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;html xmlns_th=\"http:\/\/www.thymeleaf.org\"&gt;\n\n&lt;head&gt;\n\u00a0 &lt;title&gt;VCS Activity Charts&lt;\/title&gt;\n\u00a0 &lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\"&gt;&lt;\/script&gt;\n\u00a0 &lt;style&gt;\n\u00a0 \u00a0 \/* Center the content and add padding *\/\n\u00a0 \u00a0 body {\n\u00a0 \u00a0 \u00a0 font-family: Arial, sans-serif;\n\u00a0 \u00a0 \u00a0 display: flex;\n\u00a0 \u00a0 \u00a0 justify-content: center;\n\u00a0 \u00a0 \u00a0 align-items: center;\n\u00a0 \u00a0 \u00a0 flex-direction: column;\n\u00a0 \u00a0 \u00a0 margin: 0;\n\u00a0 \u00a0 \u00a0 padding: 20px;\n\u00a0 \u00a0 \u00a0 background-color: #f5f5f5;\n }\n\n\u00a0 \u00a0 \/* Style containers for each chart *\/\n\u00a0 \u00a0 .chart-container {\n\u00a0 \u00a0 \u00a0 background-color: white;\n\u00a0 \u00a0 \u00a0 border-radius: 8px;\n\u00a0 \u00a0 \u00a0 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n\u00a0 \u00a0 \u00a0 padding: 20px;\n\u00a0 \u00a0 \u00a0 margin: 20px 0;\n\u00a0 \u00a0 \u00a0 width: 100%;\n\u00a0 \u00a0 \u00a0 max-width: 600px;\n }\n\n\u00a0 \u00a0 \/* Canvas styling with a fixed height *\/\n\u00a0 \u00a0 canvas {\n\u00a0 \u00a0 \u00a0 width: 100% !important;\n\u00a0 \u00a0 \u00a0 height: 300px !important;\n }\n\n\u00a0 \u00a0 \/* Chart title styling *\/\n\u00a0 \u00a0 h2 {\n\u00a0 \u00a0 \u00a0 text-align: center;\n\u00a0 \u00a0 \u00a0 color: #333;\n\u00a0 \u00a0 \u00a0 font-size: 24px;\n\u00a0 \u00a0 \u00a0 margin-bottom: 20px;\n }\n\u00a0 &lt;\/style&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n\n\u00a0 &lt;div class=\"chart-container\"&gt;\n\u00a0 \u00a0 &lt;h2&gt;Commit Activity&lt;\/h2&gt;\n\u00a0 \u00a0 &lt;canvas id=\"commitChart\"&gt;&lt;\/canvas&gt;\n\u00a0 &lt;\/div&gt;\n\n\u00a0 &lt;div class=\"chart-container\"&gt;\n\u00a0 \u00a0 &lt;h2&gt;Pull Request Activity&lt;\/h2&gt;\n\u00a0 \u00a0 &lt;canvas id=\"prChart\"&gt;&lt;\/canvas&gt;\n\u00a0 &lt;\/div&gt;\n\n\u00a0 &lt;!-- Inline JavaScript block to properly process Thymeleaf variables --&gt;\n\u00a0 &lt;script th_inline=\"javascript\"&gt;\n\u00a0 \u00a0 \/\/ Thymeleaf will automatically insert the JSON string correctly\n\u00a0 \u00a0 const commitData = [[${ commitDataJson }]];\n\u00a0 \u00a0 const prData = [[${ prDataJson }]];\n\n\u00a0 \u00a0 \/\/ Parse JSON data into JavaScript objects\n\u00a0 \u00a0 const parsedCommitData = JSON.parse(commitData);\n\u00a0 \u00a0 const parsedPrData = JSON.parse(prData);\n\n\u00a0 \u00a0 \/\/ Helper function to sort the data by date keys\n\u00a0 \u00a0 function sortByDate(data) {\n\u00a0 \u00a0 \u00a0 return Object.keys(data)\n .sort((a, b) =&gt; new Date(a) - new Date(b)) \u00a0\/\/ Sort the date strings in ascending order\n .reduce((obj, key) =&gt; {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 obj[key] = data[key]; \/\/ Rebuild the object in sorted order\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return obj;\n }, {});\n }\n\n\u00a0 \u00a0 \/\/ Sort the commit and PR data by date\n\u00a0 \u00a0 const sortedCommitData = sortByDate(parsedCommitData);\n\u00a0 \u00a0 const sortedPrData = sortByDate(parsedPrData);\n\n\u00a0 \u00a0 \/\/ Extract labels (dates) and values (counts) for Commit chart\n\u00a0 \u00a0 const commitLabels = Object.keys(sortedCommitData);\n\u00a0 \u00a0 const commitValues = Object.values(sortedCommitData);\n\n\u00a0 \u00a0 \/\/ Extract labels (dates) and values (counts) for Pull Request chart\n\u00a0 \u00a0 const prLabels = Object.keys(sortedPrData);\n\u00a0 \u00a0 const prValues = Object.values(sortedPrData);\n\n\u00a0 \u00a0 \/\/ Commit Activity Chart\n\u00a0 \u00a0 const commitCtx = document.getElementById('commitChart').getContext('2d');\n\u00a0 \u00a0 const commitChart = new Chart(commitCtx, {\n\u00a0 \u00a0 \u00a0 type: 'line',\n\u00a0 \u00a0 \u00a0 data: {\n\u00a0 \u00a0 \u00a0 \u00a0 labels: commitLabels,\n\u00a0 \u00a0 \u00a0 \u00a0 datasets: [{\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 label: 'Commits',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 data: commitValues,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 backgroundColor: 'rgba(75, 192, 192, 0.2)',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 borderColor: 'rgba(75, 192, 192, 1)',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 borderWidth: 2\n }]\n },\n\u00a0 \u00a0 \u00a0 options: {\n\u00a0 \u00a0 \u00a0 \u00a0 responsive: true,\n\u00a0 \u00a0 \u00a0 \u00a0 maintainAspectRatio: true,\n\u00a0 \u00a0 \u00a0 \u00a0 scales: {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 y: {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 beginAtZero: true\n }\n }\n }\n });\n\n\u00a0 \u00a0 \/\/ Pull Request Activity Chart\n\u00a0 \u00a0 const prCtx = document.getElementById('prChart').getContext('2d');\n\u00a0 \u00a0 const prChart = new Chart(prCtx, {\n\u00a0 \u00a0 \u00a0 type: 'line',\n\u00a0 \u00a0 \u00a0 data: {\n\u00a0 \u00a0 \u00a0 \u00a0 labels: prLabels,\n\u00a0 \u00a0 \u00a0 \u00a0 datasets: [{\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 label: 'Pull Requests',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 data: prValues,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 backgroundColor: 'rgba(153, 102, 255, 0.2)',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 borderColor: 'rgba(153, 102, 255, 1)',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 borderWidth: 2\n }]\n },\n\u00a0 \u00a0 \u00a0 options: {\n\u00a0 \u00a0 \u00a0 \u00a0 responsive: true,\n\u00a0 \u00a0 \u00a0 \u00a0 maintainAspectRatio: true,\n\u00a0 \u00a0 \u00a0 \u00a0 scales: {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 y: {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 beginAtZero: true\n }\n }\n }\n });\n\u00a0 &lt;\/script&gt;\n&lt;\/body&gt;\n\n&lt;\/html&gt;<\/code><\/pre>\n<\/div>\n<h3>Running the Project<\/h3>\n<p>To run the project, execute the following command to build and run our application:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">mvn clean install && mvn spring-boot:run \u00a0<\/code><\/pre>\n<\/div>\n<h3>Accessing the Dashboard<\/h3>\n<p>Once the application is up and running, open a web browser and navigate to <code>http:\/\/localhost:9090<\/code>. This URL will display our Thymeleaf-based dashboard, where we can view charts visualizing commit activity and pull request activity over time.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/03\/chart.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/03\/chart.png\" alt=\"\" width=\"993\" height=\"929\" class=\"aligncenter size-full wp-image-31406\" srcset=\"\/wp-content\/uploads\/2025\/03\/chart.png 993w, \/wp-content\/uploads\/2025\/03\/chart-300x281.png 300w, \/wp-content\/uploads\/2025\/03\/chart-768x719.png 768w, \/wp-content\/uploads\/2025\/03\/chart-600x561.png 600w\" sizes=\"(max-width: 993px) 100vw, 993px\" \/><\/a><\/p>\n<p>The charts on this dashboard is dynamically rendered using data retrieved from Github and processed by the application\u2019s <code>ChartService<\/code>.<\/p>\n<p><strong>Data Storage in GridDB:<\/strong><\/p>\n<p>The GridDB Shell tool allows for direct access and querying of data via the command line, as illustrated below.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/03\/GridDB.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/03\/GridDB.png\" alt=\"\" width=\"1339\" height=\"699\" class=\"aligncenter size-full wp-image-31407\" srcset=\"\/wp-content\/uploads\/2025\/03\/GridDB.png 1339w, \/wp-content\/uploads\/2025\/03\/GridDB-300x157.png 300w, \/wp-content\/uploads\/2025\/03\/GridDB-1024x535.png 1024w, \/wp-content\/uploads\/2025\/03\/GridDB-768x401.png 768w, \/wp-content\/uploads\/2025\/03\/GridDB-600x313.png 600w\" sizes=\"(max-width: 1339px) 100vw, 1339px\" \/><\/a><\/p>\n<h3><strong>Conclusion:<\/strong><\/h3>\n<p>Tracking VCS activity is critical for understanding team productivity and optimizing development workflows. By leveraging GridDB\u2019s ability to handle time-series data efficiently, teams can capture key events like commits, merges, and pull requests with ease, allowing for both real-time insights and in-depth historical analysis.<\/p>\n<p>With GridDB\u2019s scalability and fast data retrieval, software teams can monitor trends, resolve bottlenecks, and improve collaboration, ultimately leading to more efficient and productive development processes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In today&#8217;s competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving this is monitoring developer activity in Version Control Systems (VCS) to optimize collaboration and code quality. By analyzing patterns in code commits, pull requests, merges, and branching, organizations can identify bottlenecks, improve workflows, and ultimately boost [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":26421,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46829","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Optimizing Software Development: VCS Activity Monitoring with GridDB | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Introduction In today&#039;s competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Optimizing Software Development: VCS Activity Monitoring with GridDB | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Introduction In today&#039;s competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-20T07:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:57:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2020\/03\/chart.png\" \/>\n\t<meta property=\"og:image:width\" content=\"739\" \/>\n\t<meta property=\"og:image:height\" content=\"457\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Optimizing Software Development: VCS Activity Monitoring with GridDB\",\"datePublished\":\"2025-03-20T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:57:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\"},\"wordCount\":1589,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2020\/03\/chart.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\",\"name\":\"Optimizing Software Development: VCS Activity Monitoring with GridDB | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2020\/03\/chart.png\",\"datePublished\":\"2025-03-20T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:57:17+00:00\",\"description\":\"Introduction In today's competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2020\/03\/chart.png\",\"contentUrl\":\"\/wp-content\/uploads\/2020\/03\/chart.png\",\"width\":739,\"height\":457,\"caption\":\"GridDB Performance using Google Cloud Platform\"},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Optimizing Software Development: VCS Activity Monitoring with GridDB | GridDB: Open Source Time Series Database for IoT","description":"Introduction In today's competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/","og_locale":"en_US","og_type":"article","og_title":"Optimizing Software Development: VCS Activity Monitoring with GridDB | GridDB: Open Source Time Series Database for IoT","og_description":"Introduction In today's competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving","og_url":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2025-03-20T07:00:00+00:00","article_modified_time":"2025-11-13T20:57:17+00:00","og_image":[{"width":739,"height":457,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2020\/03\/chart.png","type":"image\/png"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Optimizing Software Development: VCS Activity Monitoring with GridDB","datePublished":"2025-03-20T07:00:00+00:00","dateModified":"2025-11-13T20:57:17+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/"},"wordCount":1589,"commentCount":0,"publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2020\/03\/chart.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/","url":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/","name":"Optimizing Software Development: VCS Activity Monitoring with GridDB | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2020\/03\/chart.png","datePublished":"2025-03-20T07:00:00+00:00","dateModified":"2025-11-13T20:57:17+00:00","description":"Introduction In today's competitive landscape, efficient software development is crucial for delivering high-quality products. A key factor in achieving","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/optimizing-software-development-vcs-activity-monitoring-with-griddb\/#primaryimage","url":"\/wp-content\/uploads\/2020\/03\/chart.png","contentUrl":"\/wp-content\/uploads\/2020\/03\/chart.png","width":739,"height":457,"caption":"GridDB Performance using Google Cloud Platform"},{"@type":"WebSite","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46829","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46829"}],"version-history":[{"count":1,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46829\/revisions"}],"predecessor-version":[{"id":51487,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46829\/revisions\/51487"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/26421"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}