Tuesday, January 27, 2026

Log tracing with OpenTelemetry and Jaeger: Code Example

Here, I am going to discuss about the Distributed Log Tracing in case of Microservices architecture. I have also recorded an Youtube video. Please go through the below Youtube video to get detailed information.


Problem statement: 

Suppose we have 3 services in our E-commerce application like Order, Payment and User service. Now, if user is calling Order service to create an order, then the order service is triggering the Payment service and Payment service is triggering the User service.

Client -> Order service -> Payment Service -> User service

Now, for each request, each of this 3 services is creating some logs. Suppose if some error comes and we need to debug then how can we identify which all logs are created from different microservices for a particular request. There is nothing in the logs by which we can group together the logs of a request

Solution:

This problem can be solved by adding an unique ID for each request in all logs for that request. So, if request 1 is creating 10 logs and each of these 10 logs are having the same unique ID then we can put these 10 logs in a single group based on this unique ID and this group of logs is related to request 1. Similarly each request will generate a separate unique ID in logs for grouping the logs and associate these groups with corresponding requests. 

This unique ID is basically termed as Trace ID. This trace ID can be created manually in each request and can be made propagated to each intervening microservices. But, this implementation is not Industry standard. There are few Industry recognized, well tested tool to achieve it. 

One of these tools is OpenTelementry. OpenTelemetry generates Trace ID for each request and instrument into each request. It gathers some metrics of each request life span through out each intervening microservices. These metrics are span ID, trace ID, span duration, request flow etc. These metrics are not stored in OpenTelemetry. OpenTelemetry just gathers these information by instrumenting the requests and the export these data to some backend services like Jaeger, ELK stack (Elastic Search, Loadash, Kibana), Grafana etc.

Here, I have implemented the open telemetry in my 3 microservices in Node.js. I am giving here the link of my GitHub repository. The technology stack I have used here are: 

Node.js
Microservices
OpenTelemetry
Jaeger

Please go through the above Youtube video and GitHub link to get complete idea.

GitHub repository: https://github.com/jksnu/opentelemetry_poc.git

Wednesday, November 12, 2025

Create VPC and Subnets in AWS CDK (Python) | Explained Step-by-Step 🚀

In this blog, we’ll explore how to create a VPC and subnets using AWS CDK in Python. Whether you’re new to AWS CDK or cloud networking, this post will help you understand how to set up a VPC with public and private subnets, configure CIDR blocks correctly, and understand how AWS handles availability zones.

You can also watch the complete hands-on tutorial on my YouTube channel here:



Understanding the VPC Basics:

A Virtual Private Cloud (VPC) is your private network in AWS. It allows you to control your IP address range, create subnets, and configure route tables and gateways.

When you create a VPC using AWS CDK, you define the following:

  • CIDR Block (e.g., 10.0.0.0/28)

  • Subnets (public/private/isolated)

  • Availability Zones

  • NAT Gateway (if private subnets need internet access)

Setting Up the VPC Using CDK:

Here’s how you can define your VPC in CDK:

from aws_cdk import (
    # Duration,
    Stack,
    aws_ec2 as ec2,
)
from constructs import Construct
import os

class AwsCdkVpcStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here
        self.vpc = ec2.Vpc(
            self,
            id=f"{os.getenv('AWS_ENV')}_{os.getenv('VPC_NAME')}",
            vpc_name=os.getenv('VPC_NAME'),
            cidr=os.getenv('CIDR_BLOCK'),
            max_azs=2,
            create_internet_gateway=True,
            nat_gateways=0,    

            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name=f"PublicSubnet_{os.getenv('AWS_ENV')}_{os.getenv('VPC_NAME')}_{self.region}",
                    subnet_type=ec2.SubnetType.PUBLIC,
                    cidr_mask=28,
                    map_public_ip_on_launch=True
                ),
                ec2.SubnetConfiguration(
                    name=f"PrivateSubnet_{os.getenv('AWS_ENV')}_{os.getenv('VPC_NAME')}_{self.region}",
                    subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS,
                    cidr_mask=28
                ),
                ec2.SubnetConfiguration(
                    name=f"IsolatedSubnet_{os.getenv('AWS_ENV')}_{os.getenv('VPC_NAME')}_{self.region}",
                    subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
                    cidr_mask=28
                ),
            ]
        )




Command Purpose
cdk synth Synthesizes your CDK code into a CloudFormation template
cdk bootstrap Prepares your AWS environment for CDK deployments
cdk deploy Deploys your stack(s) to AWS


GITHUB Link: https://github.com/jksnu/aws_vpc_cdk.git

Thursday, October 30, 2025

Learn AWS FREE! | Best Way to Start AWS Cloud Training (Official AWS Ski...


Want to start your AWS Cloud journey for FREE? 🌩️
In this video, I’ll show you how you can learn AWS services completely free using the official AWS Skill Builder platform — straight from Amazon Web Services itself!

🎓 What you’ll learn in this video:
✅ How to access AWS Skill Builder
✅ Best free courses to start with (Cloud Practitioner, EC2, S3, Lambda, etc.)
✅ How to get AWS Cloud Practitioner Certified (with no cost!)
✅ Tips to learn faster and track your AWS progress

📚 Start learning now:
👉 https://skillbuilder.aws

💡 Whether you’re a beginner or want to upgrade your cloud skills, this video will help you kickstart your AWS journey without spending a single rupee!

If you found this video helpful, don’t forget to LIKE 👍, SUBSCRIBE 🔔, and SHARE it with your friends who want to learn AWS for free

Saturday, September 13, 2025

Build a RAG-Based AI Chatbot with Multi-File Upload and Chroma DB (Vector DB) Integration

 Retrieval-Augmented Generation (RAG) has become a popular approach in building AI chatbots that provide accurate and context-aware answers. In this tutorial, we will build a RAG-based chatbot where users can upload multiple documents (PDF, Word, etc.) to create a custom knowledge base. When users query, the chatbot will fetch relevant context from these documents using Chroma DB (a vector database) and provide precise answers.

Watch the full step-by-step video tutorial here:
👉 YouTube Video: Build RAG-Based Chatbot with Multi-File Upload + Chroma DB


What is RAG (Retrieval-Augmented Generation)?

RAG combines:

  • Retrieval → Fetches relevant information from a knowledge base.

  • Generation → Uses an LLM (Large Language Model) like OpenAI GPT to generate context-aware answers.

This approach ensures:

  • No hallucinations (random answers).

  • Context-based responses from your documents.

Architecture Overview:
  1. User uploads documents (PDF, Word, PPT, etc.)
  2. Text extraction → Convert documents into text.
  3. Embeddings creation → Convert text into vector embeddings.
  4. Store embeddings in Chroma DB
  5. Query flow:
  • Convert user query into an embedding.
  • Fetch top N relevant chunks from Chroma DB.
  • Pass context + query to LLM for response. 


 

Tools & Libraries Used:

  • Python for backend
  • Chroma DB for vector storage
  • Hugging Face LLM
  • Hugging Face Embedding Model
  • Flask for API
Below are the code snippet for different steps. You can go through my Youtube video to the complete detail and GitHub repository link

Initialize Chroma DB and Create a Collection

import chromadb

client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection(name="docs")


Generate Embeddings:


import requests
from typing import List
import os
import logging

headers = {
    "Authorization": f"Bearer {os.getenv("HUGGINGFACEHUB_API_TOKEN")}",
    "Content-Type": "application/json"
}

logger = logging.getLogger(__name__)
EMBEDDING_MODEL = os.getenv("EMBEDDING_MODEL", "sentence-transformers/distilbert-base-nli-mean-tokens")    

# Function to get embedding for a given text using Hugging Face API
# This function assumes that the environment variable EMBEDDING_MODEL is set to a valid Hugging Face model ID
# Example: EMBEDDING_MODEL="sentence-transformers/distilbert-base-nli-mean-tokens"

def get_embedding(text: str) -> List[float]:
    try:
        url = f"https://api-inference.huggingface.co/models/{EMBEDDING_MODEL}"
        print(f"url: {url}")
        response = requests.post(url, headers=headers, json={"inputs": text}, timeout=60, verify=False)
        response.raise_for_status()
        embedding = response.json()
        return embedding  # This is a list of floats
    except Exception as e:
        logger.error(f"Error getting embedding: {e}")
        raise ValueError("Failed to get embedding from the model.")

Store embedded data in Chroma DB:

def add_documents_to_vector_store(docs: list[str], ids: list[str], filename: str) -> None:
    try:
        vectors = [get_embedding(text) for text in docs]
        collection.add(
            documents=docs,
            embeddings=vectors,
            ids=ids,
            metadatas=[{"filename": filename} for _ in docs]
        )
    except Exception as e:
        logger.error(f"Error adding documents to vector store: {e}")
        raise ValueError(f"Failed to add documents to vector store: {e}")

Query Chroma DB:

def query_similar_documents(query: str, top_k: int = 3) -> list[str]:
    try:
        context_files = get_uploaded_files()
        print(f"Context files available: {context_files}")
        if len(context_files) == 0:
            return []
        query_vector = get_embedding(query)
        results = collection.query(
            query_embeddings=[query_vector],
            n_results=top_k,
            where={"filename": {"$in": context_files}}
        )
        return results["documents"][0]
    except Exception as e:
        logger.error(f"Error querying similar documents: {e}")
        raise ValueError(f"Failed to query similar documents: {e}")

Combine with LLM for Answer Generation:

import os
import requests
import logging
from typing import List
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import re
import chromadb
from chromadb.config import Settings
from app.core.chroma_store import query_similar_documents, add_documents_to_vector_store

from huggingface_hub import InferenceClient

logger = logging.getLogger(__name__)

HUGGINGFACE_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
LLM_MODEL = os.getenv("LLM_MODEL") #    mistralai/Mixtral-8x7B-Instruct-v0.1

headers = {
    "Authorization": f"Bearer {os.getenv("HUGGINGFACEHUB_API_TOKEN")}",
    "Content-Type": "application/json"
}

def build_client() -> InferenceClient:
    return InferenceClient(
        model=LLM_MODEL,
        token=HUGGINGFACE_API_TOKEN,
        timeout=300
    )

def get_llm_response(prompt: str):
    try:

        client = build_client()
        SYSTEM_PROMPT = """You are a Personal assistant specialized in providing well formated answer from the context being provided."""
        messages = [
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": f"Provide well formated answer from the given context.\n\n{prompt}"}
        ]
        result = client.chat.completions.create(
            model=LLM_MODEL,
            messages=messages,
            temperature=0.1,
            max_tokens=200
        )
        text = result.choices[0].message.content
        if isinstance(text, list):
            text = "".join(part.get("text", "") if isinstance(part, dict) else str(part) for part in text)
        return text

    except Exception as e:
        logger.error(f"Error getting LLM response: {e}")
        raise ValueError("Failed to get response from the LLM model.")


Full Video Tutorial

📌 Watch the complete step-by-step guide with implementation here:
👉 Build RAG-Based Chatbot with Multi-File Upload + Chroma DB





Thursday, September 4, 2025

Deploy AWS Lambda Using AWS CDK in Python (Step-by-Step Guide)

 If you want to learn how to deploy an AWS Lambda function using the AWS Cloud Development Kit (CDK) in Python, you’ve landed in the right place! In this post, I’ll walk you through the prerequisites, setup, and exact steps you need to follow. I’ll also share some code snippets and give a reference to my YouTube video tutorial for better understanding.

🎥 Watch the complete tutorial on YouTube here: AWS CDK Tutorial in Python | Deploy Lambda from S3




Prerequisites

Before we get started, make sure you have the following ready:

  1. Programming Language Setup – Install Python (preferably 3.10+).

  2. Free-tier AWS Account – Sign up at AWS.

  3. Node.js and NPM Installed – Required for CDK installation.

Steps to Deploy Lambda with AWS CDK

Step 1) Configure AWS CLI: Run below command on CMD and provide your AWS Access Key, Secret Key, Region and output format.

                    aws configure

Step 2) Install AWS CDK: Run below NPM command to install AWS SDK globally:

                    npm install -g aws-cdk

Step 3) Verify installation: Run the below command in CMD and if it is giving correct response then installation is complete:

                    cdk --version

Step 4) Create a New CDK Project: Go to the folder where you want to create your project and run the below command in CMD to create CDK project structure in Python

                    cdk init app --language python

Step 5) Open Project in VSCode: Navigate into your project directory and open it in Visual Studio Code. 

Step 6) Add Lambda Deployment Code: In your Stack file, add the infrastructure code as follows:

from aws_cdk import (
    Duration,
    Stack,
    aws_lambda as _lambda,
    aws_lambda,
    aws_s3 as s3,
    aws_logs as logs,
    RemovalPolicy,
    aws_iam as iam,
    aws_scheduler as scheduler,
    aws_apigateway as apigwv,
    CfnOutput
)
from constructs import Construct
from typing import cast

class Hello_Lambda_CDK_Stack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        bucket_name = "jitendra-lambda-bucket"
        object_key = "mylambda.zip"

        # Define a log group for the Lambda function
        log_group = logs.LogGroup(
            self, f"HelloLambdaFN-LogGroup-ID",
            log_group_name=f"/aws/lambda/HelloLambdaFN-LogGroup",
            removal_policy=RemovalPolicy.DESTROY,
            retention=logs.RetentionDays.THREE_DAYS
        )

        # Define a Lambda function resource here
        my_lambda = _lambda.Function(
            self, f"HelloLambdaFN-ID",
            runtime=_lambda.Runtime.PYTHON_3_13,
            handler="lambda_function.lambda_handler",
            code=_lambda.Code.from_bucket(
                bucket = s3.Bucket.from_bucket_name(
                    self, f"HelloLambdaFN-Bucket-ID",
                    bucket_name
                ),
                key = object_key
            ),
            log_group=log_group,
            timeout=Duration.seconds(30),
            memory_size=128,
            function_name="HelloLambdaFN"
        )
       
        # Add permissions for the Lambda function to write to the log group
        log_group.grant_write(my_lambda)

        # Define an API Gateway HTTP API to trigger the Lambda function
        apigatewayobj = apigwv.LambdaRestApi(
            self, "HelloLambdaFN-API-Gateway",
            rest_api_name="HelloLambdaFN-API",
            handler=cast(aws_lambda.IFunction, my_lambda),
            proxy=True
        )  

        CfnOutput(
            self, "APIEndpoint",
            value=apigatewayobj.url,
            description="The endpoint URL of the HelloLambdaFN API Gateway",
        )

                
Step 7) Bootstrap AWS Environment: This prepares your AWS account to use CDK.
                
                            cdk bootstrap

Step 8) Build Your Application (Optional): For Python, explicit build isn’t needed.

Step 9) Synthesize CloudFormation Template: This generates the underlying CloudFormation template and highlight any error if there in your infrastructure code.

                            cdk synth

Step 10) Deploy the Stack: Run the below command in CMD and it will start creating your AWS infrastructure as per your code in step by step. Before final deployment, it will ask will confirmation and if you confirm then it will start final deployment:

                            Deploy the Stack

Step 11) Delete the Application: Now, if you want to delete your deployed stack, then you can delete it by running the below CDK command:

                            cdk destroy

With AWS CDK in Python, deploying a Lambda function directly from an S3 bucket is simple and efficient. By following these steps, you can manage your infrastructure as code and automate serverless deployments.

📺 Don’t forget to watch the complete tutorial video for a practical walkthrough: Click here to watch




Tuesday, April 22, 2025

Microservices Communication Using Istio | Docker + Minikube Setup on Windows (Hands-on Tutorial)

 Introduction

In the ever-evolving world of microservices architecture, choosing the right way to enable service-to-service communication is key. Whether you're building an enterprise-scale solution or experimenting with distributed systems, understanding how microservices talk to each other is a must.

In this blog, we will explore the popular ways of microservices communication, understand the power of the Service Mesh pattern with Istio, and finally go hands-on by setting up Istio on Windows using Docker and Minikube.

🎥 Watch Full Tutorial Here:
👉 Microservices Communication Using Istio | Docker + Minikube Setup on Windows (Hands-on Tutorial)



Microservices can communicate in a few different ways:

  1. HTTP REST APIs – Most common and simple.

  2. gRPC – Efficient and high-performance.

  3. Message Queues (Kafka, RabbitMQ) – For asynchronous and decoupled communication.

However, with increasing complexity, managing this communication becomes harder — that’s where Service Mesh comes in.

What is a Service Mesh?

A Service Mesh is a design pattern that provides a dedicated infrastructure layer to manage service-to-service communication. It offers:

  • Load balancing

  • Service discovery

  • Traffic management

  • Observability

  • Security (mTLS)

  • Fault tolerance

All without changing the application code!

Sidecar Proxy & Control Plane:

The service mesh uses the Sidecar Pattern, where each service instance runs alongside a proxy container (usually Envoy).
This proxy handles all the incoming and outgoing traffic, enabling advanced traffic control and telemetry.

The Control Plane (like Istio) configures these proxies and coordinates their behavior across the mesh.

Why Istio?

Istio is one of the most powerful and widely-used service meshes. It simplifies observability, traffic management, and security for microservices. It works seamlessly with Kubernetes and supports features like:

  • Traffic shaping

  • Canary deployments

  • Circuit breakers

  • Dashboards (Kiali, Jaeger)

Step-by-Step Setup (Windows + Docker + Minikube)

Prerequisites

  1. Install Docker Desktop

  2. Set Environment Path for Docker

  3. Install Minikube (ensure virtualization support is enabled)

  4. Create a DockerHub account

Service Mesh Setup Using Istio

1. Create Microservices
  • User Service

  • Order Service

  • Payment Service

2. Build Docker Images

 docker build -t user-service ./user
docker build -t order-service ./order
docker build -t payment-service ./payment

3.  Push Images to DockerHub

docker push docker-hub-username/user-service

         docker push docker-hub-username/order-service 

        docker push docker-hub-username/payment-service

4. Start Minikube 

        minikube start

 5. Install istio 

          istioctl install --set profile=demo -y

 6. Inject Istio container as a sidecar proxy in each pod 

          kubectl label namespace default istio-injection=enabled 

 7. Run deployment yaml files to create POD replicas 

          kubectl apply -f user-deployment.yaml

          kubectl apply -f order-deployment.yaml

          kubectl apply -f payment-deployment.yaml

 8. Run Istio yaml file to enable external gateway 

          kubectl apply -f istio-gateway.yaml

 9. Run horizonal pod autoscaling yaml 

          kubectl apply -f order-hpa.yaml

          kubectl apply -f payment-hpa.yaml

          kubectl apply -f user-hpa.yaml

 10. Run Circuit breaker yaml file 

          kubectl apply -f payment-cb.yaml

 11. Get External IP that is exposed by Istio gateway

          minikube tunnel

          # In another terminal

          kubectl get svc istio-ingressgateway -n istio-system

 12. Enable Observability - Optional

          istioctl dashboard kiali

          istioctl dashboard jaeger

 13. Test the User API through postman with below url and input body data

        

All the code and Yaml files can be found in my below GITHUB link:

GITHUB Repo Link: https://github.com/jksnu/Service-Mesh.git

Setting up a service mesh using Istio may seem overwhelming at first, but once done, it significantly simplifies and strengthens your microservice communication.

If you found this blog helpful, don't forget to subscribe, like, and share the video to help others learn!

👉 Click here to watch the complete hands-on tutorial on YouTube




 

Saturday, December 28, 2024

Master IAM Authentication: Lambda, API Gateway, and Signature V4 in Action

 Authentication and Authorization two very important pillar of web security. Authentication is basically used to identify the user. It verifies the user is the same user that he is supposed to be. Authorization is used to verify what the user can do. What access he is having.

Here, I am going to discuss about the Authorization. In AWS, authorization can be implemented in 3 ways:

  1. IAM Auth
  2. Lambda authorizer
  3. Token authorizer
In this post, I am discussing mainly about IAM AUTH. You can go through my below Youtube video to get detailed idea.

My Youtube Video Link: https://youtu.be/QKouBNm_-BA


I have created an youtube video on IAM Auth. Here I have shown lambda function creation, API creation, Route Creation, attaching routes with corresponding lambda functions, associating IAM auth with routes, User group creation, User creation, Policy creation and passing signature version 4 token in postman to test authorization of these routes. Below are the steps:

STEPS:

  1. Create two lambda functions for handling two routes
  2. In API Gateway - Create two routes like /helloadmin and /hellouser with GET method
  3. Attach both routes with corresponding lambda functions
  4. Attach each route with IAM auth for authorization
  5. In IAM - Create two groups say Admin and Client
  6. Create two users named as admin_user and client_user under corresponding groups
  7. Create in line policy for both groups
            The admin_user should be able to access only /helloadmin NOT /hellouser 
         The client_user should be able to access only /hellouser NOT /helloadmin

     8.  Add authorization header in POSTMAN [SignatureV4]

            a) Find accesskey, secretkey, sessionToken of both users
    b) Pass these values in Authorization tab in POSTMAN

     9.  After Testing delete all Policies, Users, Groups, IAM APIs, Lambda functions

Please go through the above video where I have showed each steps in detail. It is very informative.







Sunday, November 3, 2024

PM2 vs Kubernetes : Do You Really Need Both for Your Node.js App

Today, I thought to discuss with you that Do we really need to use PM2 in Node APPLCIATION along with Kubernets. You can also go through the below recorded video on same topic in my Youtube channel:

Video link: https://youtu.be/dcJ5oBCEZ8I?si=vxo0xtqdIjbHz0LY


PM2 provides features like
  • Process management and monitoring
  • Automatic restart on failure
  • Load balancing
  • Graceful shutdown
  • Real time metrics and logging
All these features also provided by Kubernets along with many more. So, we can say that kubernetes is a kind of superset of PM2.

Now, it can be said that we can use PM2 in a particular pod for above mentioned feature before interference of kubernets. It's true but isn't it a kind of feature redundancy.

Again, it can be said that PM2 can be used to initiate multiple processes in a pod to perform cpu intensive work. But again here, we can use threadpool mechanism
in node js to handle it.

So, on the whole, I am not able to find a real value of using PM2 in Node JS application along with Kubernets. But yes, in absence of kubernets, PM2 is really very important and light weight process manager. This is my opinion. What's your thought. please mention in the comment box.

Tuesday, October 1, 2024

Master PM2: Ultimate Guide to Node.js Process Management & Optimization

Process Management is a very important aspect in any application configuration. There are several process management libraries. PM2 is one of them that is widely used. Here, I am showing how to use it in Windows system along with its different commands.

IMPORTANT NOTE: You can get full detail in my below Youtube video. Here is the link: https://youtu.be/mwGV0thGBfI?si=mC7hdFg--qmaA-XT


Benefits of Process Management libraries:

  • Automatic Restart: If your application crashes, PM2 automatically restarts it, ensuring minimal downtime.
  • Load balancing: PM2 can run your application in cluster mode, leveraging multi-core processors for better performance and scalability.
  • Process monitoring: It tracks resource consumption (CPU, memory) and provides insights through monitoring tools.
  • Log Management: PM2 aggregates logs from multiple instances of your application, providing centralized logging and an easy way to debug issues. It also allows you to view real-time logs and can be configured to send logs to external log services.
  • Performance Optimization: PM2 allows you to run multiple instances of your application (in cluster mode), distributing the load across multiple CPU cores, improving application throughput.
  • Environment Management: PM2 supports different environments (development, production) and allows you to define different configurations for each environment.
  • Memory Management: PM2 provides options to set memory limits for your applications. When memory consumption exceeds the limit, it will automatically restart the app, preventing memory leaks from causing issues.
  • Real-time Monitoring Dashboard: PM2 offers a real-time web dashboard to monitor application status, CPU, memory, and other metrics. This helps in identifying performance bottlenecks or issues in real time.
PM2 Installation: We can use npm command to install PM2 at global mode by using below command:
                    npm install pm2@latest -g

Start application using PM2: We can use below command to start our node js application named as Test1
 pm2 start C:\Personal\Jitendra\workspace\youtube\youtubeCode\app.js --name Test1


Similarly we can another node js application using PM2 on different port like:
pm2 start C:\Personal\Jitendra\workspace\youtube\youtubeCode2\app.js --name Test2

List all applications: We can list down all applications along with their different instances running under PM2.

pm2 list


Monitor application: We can use "pm2 monit" command to open a monitor window to get the real time metrics of the applications running in PM2



Watch logs: We can use below command to get the real time logs of our applications running under pm2


Stop applications: We can use below commands to stop applications running under PM2
                                pm2 stop Test1 - stops only application named as Test1
                                pm2 stop all - stops all applications running under PM2


Passing Environment variables: We can pass some secure data to our application at startup time in PM2 through environment variables using below command:

set PORT=3005 && pm2 start C:\Personal\Jitendra\workspace\youtube\youtubeCode\app.js --name Test1

Here, I am passing PORT data as an environment variable at the startup time. 

Ecosystem: we can add multiple sub-commands here for different purposes like instance handling, log handling, load balancing and thus the start command will become very complex. So, to solve this problem we can use ecosystem config file. We can automatically generate the file named as "ecosystem.config.js" using command like "pm2 ecosystem" and then we can modify the newly created file as per the application requirement:

module.exports = {
  apps : [{
    name: 'Test2',
    script: './app.js',
    env: {
      NODE_ENV: 'development',
      PORT: 3006
    },
    watch: '.'
  }],

  deploy : {
    production : {
      user : 'SSH_USERNAME',
      host : 'SSH_HOSTMACHINE',
      ref  : 'origin/master',
      repo : 'GIT_REPOSITORY',
      path : 'DESTINATION_PATH',
      'pre-deploy-local': '',
      'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
      'pre-setup': ''
    }
  }
};


In this file we are passing the port and Node Env as environment variables. Similarly we can pass other variables and config parameters.
To start the application using ecosystem.config.js, we need to use command like "pm2 start ecosystem.config.js"


Similarly, if we want to run another application by using ecosystem.config.js file, then we have to create a separate ecosystem.config.js file and run the command "pm2 start ecosystem.config.js" with respect to this file.

But, what if we have 100 microservices, then we have to create such 100 files for ecosystem.config.js and thus it becomes unmanageable.

To solve this issue, we can create a single ecosystem.config.js file and we can define all the required metrics for each of the microservices in this single file and when we start it through PM2 then all microservices will start. The example of such ecosystem.config.js file is as follows:

module.exports = {
    apps: [
        {
            name: 'Test1',
            script: '../youtube/youtubeCode/app.js',
            instances: 2,
            max_memory_restart: "300M",
            // Logging
            out_file: "./test1.out.log",
            error_file: "./test1.error.log",
            merge_logs: true,
            log_date_format: "DD-MM HH:mm:ss Z",
            log_type: "json",
            watch: true,
            ignore_watch: [
                "../youtube/youtubeCode/node_modules",
                "../youtube/youtubeCode/package.json"
            ],
            // Env Specific Config          
            env: {
                NODE_ENV: 'development',
                PORT: 3005
            }
        },
        {
            name: 'Test2',
            script: '../youtube/youtubeCode2/app.js',
            instances: "1",
            exec_mode: "cluster",
            out_file: "./test2.out.log",
            error_file: "./test2.error.log",
            watch: true,
            ignore_watch: [
                "../youtube/youtubeCode2/node_modules",
                "../youtube/youtubeCode2/package.json"
            ],
            env: {
                NODE_ENV: 'development',
                PORT: 3006
            }
        }
    ],

    deploy: {
        production: {
            user: 'SSH_USERNAME',
            host: 'SSH_HOSTMACHINE',
            ref: 'origin/master',
            repo: 'GIT_REPOSITORY',
            path: 'DESTINATION_PATH',
            'pre-deploy-local': '',
            'post-deploy': 'npm install && pm2 reload ecosystem.config.js --env production',
            'pre-setup': ''
        }
    }
};


Please ping in the comment section if you have any question or suggestion.