My Quotes


When U were born , you cried and the world rejoiced
Live U'r life in such a way that when you go
THE WORLD SHOULD CRY






Tuesday, December 23, 2025

Implement advanced monitoring for Azure OpenAI in Foundry Models through a gateway

Azure GenAI architecture



Things which we can enhance on this are 
  • Layers of governance (data,apps,compute,network and storage) that eould be great
  • Plus integration of "piprline" and " quality gates testing" to make it more robust and self-healing

Tuesday, June 6, 2023

Microsoft Cybersecurity Reference Architectures

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟏 - 𝐈𝐝𝐞𝐧𝐭𝐢𝐭𝐲 𝐚𝐧𝐝 𝐀𝐜𝐜𝐞𝐬𝐬 

o   Azure Active Directory: Password-less & MFA, Hello for Business, Authenticator App, FIDO2 Keys, Azure AD PIM, B2B & B2C. https://lnkd.in/grPgTT4R

o   Identity Protection: Leaked Credential Protection. https://lnkd.in/gdgMJZNF

o   Identity Governance: Identity, Access, and Privileged Access Lifecycle, Entitlement Management, Access Requests, Workflow, Policy and Role Management, Governance Enforcement. https://lnkd.in/gbVEWcQs

o   Defender for Identity: User Behavior and Activities, Investigate Alerts, AD FS Protection, Lateral Movement Detection. https://lnkd.in/g53ave8s

 

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟐 - 𝐒𝐞𝐜𝐮𝐫𝐢𝐭𝐲 𝐎𝐩𝐞𝐫𝐚𝐭𝐢𝐨𝐧𝐬

o   Microsoft 365 Defender: Extended Detection and Response (#XDR). Endpoint, Office365, Identity, and more https://lnkd.in/gXFnX2PQ

o   Defender for Cloud: Cross Cloud XDR. https://lnkd.in/gZfP3QdF

o   Microsoft Sentinel: Cloud Native SIEM, SOAR. https://lnkd.in/gnd-6c-u

 

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟑 - 𝐄𝐧𝐝𝐩𝐨𝐢𝐧𝐭 𝐚𝐧𝐝 𝐃𝐞𝐯𝐢𝐜𝐞 𝐒𝐞𝐜𝐮𝐫𝐢𝐭𝐲

o   Microsoft Endpoint Manager: Intune and Configuration Manager. https://lnkd.in/g4Vdfej2

o   Microsoft Defender for Endpoint: https://lnkd.in/g3KPMPCx

 

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟒 - 𝐇𝐲𝐛𝐫𝐢𝐝 𝐈𝐧𝐟𝐫𝐚𝐬𝐭𝐫𝐮𝐜𝐭𝐮𝐫𝐞

o   Defender for Cloud: Cross Cloud XDR. https://lnkd.in/gZfP3QdF

o   Azure AD App Proxy: Secure Remote Access. https://lnkd.in/g2DDNYUy

o   Azure Arc: Hybrid and Multicloud Management. https://lnkd.in/gtaiiPgM

o   Azure Stack: Hybrid and Edge Computing. https://lnkd.in/gvKNyKQD

o   Azure Firewall: https://lnkd.in/gVnVNJbB

o   Azure WAF: https://lnkd.in/gpQCgdNc

o   DDoS Protection: https://lnkd.in/gF796HMv

o   Azure Key Vault: https://lnkd.in/gqMuSJ4S  

o   Azure Bastion: Secure RDP/SSH, Secure VM. https://lnkd.in/gmdyEb5W

o   Azure Lighthouse: https://lnkd.in/gHHUVyJn

o   Azure Backup: https://lnkd.in/gzBpjFXs  

o   Express Route: https://lnkd.in/gGBtuq5m

o   Private Link: https://lnkd.in/gzZVJ_gY

 

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟓 - 𝐈𝐧𝐟𝐨𝐫𝐦𝐚𝐭𝐢𝐨𝐧 𝐏𝐫𝐨𝐭𝐞𝐜𝐭𝐢𝐨𝐧

o   Microsoft Purview: https://lnkd.in/g289yg_D

o   Compliance Manager: https://lnkd.in/gprm3xD4

 

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟔 - 𝐏𝐞𝐨𝐩𝐥𝐞 𝐒𝐞𝐜𝐮𝐫𝐢𝐭𝐲

o   Attack Simulator: Simulation Training Platform. https://lnkd.in/g3xyhZff 

o   Insider Risk Management: https://lnkd.in/gfhxQEti

o   Communication Compliance: https://lnkd.in/gKJd4HRm

 

·       𝐃𝐨𝐦𝐚𝐢𝐧 #𝟕 - 𝐈𝐨𝐓 𝐚𝐧𝐝 𝐎𝐩𝐞𝐫𝐚𝐭𝐢𝐨𝐧𝐚𝐥 𝐓𝐞𝐜𝐡𝐧𝐨𝐥𝐨𝐠𝐲

Azure Sphere: IoT and OT Security Services. https://lnkd.in/gFMQRZB6 

Azure Tips

Useful resources for Azure developers and architects! Microsoft Azure has unveiled the App Service Landing Zone Accelerator, an open-source collection of architectural guidance and reference implementation to accelerate the deployment of Azure App Service at scale. Whether you're building new applications in the cloud or looking to modernize your existing web apps, this accelerator provides a simple and robust starting point!

  • 𝐒𝐞𝐜𝐮𝐫𝐞 𝐃𝐞𝐬𝐢𝐠𝐧 𝐏𝐫𝐢𝐧𝐜𝐢𝐩𝐥𝐞𝐬
    • With the App Service Landing Zone Accelerator, you can implement a range of secure design principles to protect your apps and data.
    • Use isolated network layers for the different components
    • Use protected Azure Active Directory-based access via Managed Identity
    • Use private endpoints for Azure services
    • Use Network Security Groups to control inbound and outbound traffic at the subnet level
    • Enable Standard DDoS Protection for the SPOKE

  • 𝐂𝐨𝐦𝐩𝐫𝐞𝐡𝐞𝐧𝐬𝐢𝐯𝐞 𝐃𝐞𝐬𝐢𝐠𝐧 𝐀𝐫𝐞𝐚𝐬
The accelerator encompasses various design areas, covering critical aspects of your app's architecture.

  • 𝐀𝐳𝐮𝐫𝐞 𝐅𝐞𝐚𝐭𝐮𝐫𝐞𝐬 𝐚𝐧𝐝 𝐒𝐞𝐫𝐯𝐢𝐜𝐞𝐬
Within the App Service Landing Zone Accelerator, you'll leverage a range of Azure features and services to enhance your app development process.


Read More:

I hope you find these resources helpful. Happy learning!

Saturday, October 22, 2022

An Event Aggregator acts as a single source of events for many objects. It registers for all the events of the many objects allowing clients to register with just the aggregator.

Benefits. Producers and consumers are decoupled. No point-to-point integrations. It's easy to add new consumers to the system

Here is the overall solution




How to Organize Events Flow in a Microservices Architecture



Numerous enterprise solutions based on the microservices architecture have an issue with generalizing event flow from different sources. A lot of solutions also have various providers, for example:

  • Azure Service Bus
  • Apache Kafka
  • RabbitMQ

Here we need a component with the ability to join event publishers and event subscribers

Another example that follows this principle is Azure Event Grid

 With the Event-Grid, you can join cloud resources that produce events (publishers) and resources that handle the events (subscribers).






Thursday, April 2, 2020

Trace the API call in Kibana (https://www.elastic.co/kibana)


  1.  Once you log in to Kibana, there are 5 important sections:
  2. Filter: Enter your API URI  ex:  /rest/getstock
  3. Filter by Time: Filter search to a particular time or date range
  4. Filter by Time: Filter search to a particular time or date range
  5. Add Filter
  6. Different API Fields are useful for searching purposes
  7.  Usecase 1: Search by http_status code
    • Step 1: Select the correct time on the top right.
    • Step  2: Left pan select the "Http_status_code" and press "Search Icon". It will automatically be added to the Add Filter   

  8. Use case 2: Search by API_KE
  9. Step 1: Select the correct time on the top right.
  10. Step 2: Left pan select the "api_key" and press "Search Icon". It will automatically be added to the Add Filter
  11. Use case 3: After setting all the filters needed, you want to check more details of the API: 
  12. Use Case 4: Want to show a visual representation of the error code. Let select http_status_code from the left pan and press "Visualize"


Saturday, January 25, 2020

API Proxy versus API Gateways

  • API Proxy

A proxy, in its most basic form, is an intermediary acting on behalf of something else. Similar to the legal concept of a proxy, an API Proxy acts on behalf of the API instead of an individual. In more technical terms, an API Proxy decouples the frontend of the API from the backend services and filters all incoming and outgoing traffic. The decoupling of front-end and back-end services allows for changes to be made to backend services without disrupting the production API. The filtering of incoming and outgoing traffic allows for monitoring, basic forms of security, request routing, and protocol translation.

  • Important Note

It is important to note that API Proxies require an existing API while some API Gateways can assist in building a new API.

  • API Gateway


API Gateways function in a similar way but have a much more robust set of features. Gateways perform the same functions as API Proxies, decoupling the frontend and backend of the API, monitoring, basic security, request routing, and protocol translation, but can also provide:


  • Advanced Security
  • Composition
  • Custom API
  • Load Balancing
  • Caching
  • Request Shaping and Management
  • Static Response Handling
  • Throttling



  • API Proxy versus API Gateway?

The use case for an API Proxy versus an API Gateway depends on what kinds of capabilities you require and where you are in the API Lifecycle. If you already have an existing API that doesn’t require the advanced capabilities that an API Gateway can offer than an API Proxy would be a recommended route. You can save valuable engineering bandwidth because proxies are much easier to maintain and you won’t suffer any negligible performance loss. If you need specific capabilities that a proxy doesn’t offer you could also develop an in-house layer to accommodate your use case. If you are earlier in the API lifecycle or need the extra features that an API Gateway can provide, then investing in one would pay dividends

API Proxy versus API Gateway


  • Notable API Gateways


https://www.axway.com/en/products/api-management/gateway
https://konghq.com/solutions/gateway/
https://aws.amazon.com/api-gateway/
https://azure.microsoft.com/en-us/services/api-management/
https://apigee.com/api-management/
https://github.com/Netflix/zuul
https://github.com/TykTechnologies/tyk

Tuesday, July 23, 2019

How to Prevent POODLE Attacks on AWS ELB And CloudFront

    What is POODLE?
  1. To maintain compatibility with legacy servers, many TLS clients implement a downgrade dance: in a first handshake attempt, offer the highest protocol version supported by the client;
  2. if this handshake fails, they retry (possibly repeatedly) with earlier protocol versions.
  3. Unlike proper protocol version negotiation (if the client offers TLS 1.2, the server may respond with, say, TLS 1.0), this downgrade can also be triggered by network glitches, or by active attackers.
  4. So if an attacker that controls the network between the client and the server interferes with any attempted handshake offering TLS 1.0 or later, such clients will readily confine themselves to SSL 3.0.
  5. Encryption in SSL 3.0 uses either the RC4 stream cipher or a block cipher in CBC mode.
  6. RC4 is well known to have biases, meaning that if the same secret (such as a password or HTTP cookie) is sent over many connections and thus encrypted with many RC4 streams, more and more information about it will leak.
  7. Unlike with the BEAST and Lucky 13 attacks, there is no reasonable workaround.
  8. This leaves us with no secure SSL 3.0 cipher suites at all: to achieve secure encryption, SSL 3.0 must be avoided entirely.
    Disable the SSLv3 Protocol to handle POODLE attacks on Cloud Front
  1. Similarly to Amazon ELB, Amazon AWS has taken care of the issue disabling SSLv3 for the customers who use the default SSL settings.
  2. Nevertheless, customers who are using custom SSL certificates with Amazon Cloud Front should disable the SSLv3 protocol manually by following the steps below in the Amazon CloudFront Management Console:
  3. Select your distribution, then click “Distribution Settings”.
  4. Click the “Edit” button on the “General” tab.
  5. In the “Custom SSL Client Support” section, select the option that says: “Only Clients that Support Server Name Indication (SNI)”.
  6. Click “Yes, Edit” to save these revised settings.
    Disable the SSLV3 Protocol to handle POODLE on Amazon AWS ELB
  1. All the ELBs which are created after 10/14/2014 5:00 PM PDT will use a new SSL Negotiation Policy that will by default no longer enable SSLv3.
  2. For the existing ELBs, it’s necessary to manually disable SSLv3 via the AWS Management console:
  3. Select your load balancer (EC2 -> Load Balancers) in the appropriate region
  4. In the Listeners tab, click “Change” in the Cipher column.|
  5. Ensure that the radio button for “Predefined Security Policy” is selected, in the dropdown select the “ELBSecurityPolicy-2014-10” policy.
  6. You can see the Protocol-SSLV3 is unchecked after selecting the policy.
  7. Click “Save” to apply the settings to the listener
  8. Repeat these steps for each listener that is using HTTPS or SSL for each LoadBalancer.

Thursday, January 3, 2019

Azure Dev Ops - Variable Group


  1. ADO you may want use variables which might be used across many jobs in the pipeline
  2. Rather than defining them in each and every pipeline job, ADO gives the option to define them as Variables Groups
  3. Once defined these variables can be linked to any job in the pipeline
  4. Manage Variables Groups --> Create
  5. Make sure to Allow access to all pipelines is ENABLED
  6. From the Builds --> Variables --> Variable Groups --> Link Variable Groups
  7. Select the Group and Click on Link
  8. You should be able to get the variables declared in the group

Azure Dev Ops- Invoke Agent Demands


  1. ADO you may want to force the pipeline builds to run against a specific agent in an agent pool.
  2. This is possible via “Demands” in the Pipeline builds as shown below
  3. The scenario check to run the TASK against a specific agent name
  4. If the agent name matches from the agent pool, then the job will run else the job will switch to the next agent and then condition will be checked against that agent in that pool.
  5. Until the condition is met the agents in the pool will be round robinly selected by the JOB
  6. This mechanism is used to check the conditions for running a job in a pipeline during runtime

Azure Dev Ops - Personal Access Tokens

In My previous post , I mentioned that in order for using REST API calls in ADO you need to use TOKENS to invoke the REST CALLS.

Here is a mechanism to generate the Personal Access Tokens

  1. Click on the AZURE DEV OPS



  2. Click on your Profile


  3. Click on Personal Access Token



  4. Copy the TOKEN from the SUCCESS screen into the REST API call

Capture last TEST Run results AZURE DevOps

You could retrieve the list of test runs, the sort descending the result on ID, since the most recent test run has the greatest ID. Then get the first item of the result. All of this shown below in powershell:

$testingBaseUrl = "https://dev.azure.com/cbre/Research%20Engine/_apis/test/runs"
$testingUrl = $testingBaseUrl + "?api-version=5.0"
$testingUrl = $testingUrl + "-preview.2"

write-host $testingUrl


#create auth header to use for REST calls
$username = "RKesavana"
$token = "your token"  Refer to my blog of how to create Personal access tokens  

#create auth header to use for REST calls 
$accessToken = ("{0}:{1}" -f $username,$token) 
$accessToken = [System.Text.Encoding]::UTF8.GetBytes($accessToken) 
$accessToken = [System.Convert]::ToBase64String($accessToken) 
$headers = @{Authorization=("Basic {0}" -f $accessToken)} 


try{
# write-host "To fetch LIST all the Test ID's information"
$testRuns=Invoke-RestMethod -Uri $testingUrl -Method Get -Headers $headers
$testRunsIdSorted = $testRuns.value | sort-object id -Descending
# write-host $testRunsIdSorted

$testURLByRunID= $testingBaseUrl+"/"+$($testRunsIdSorted[0].id)
$testURLByRunID= $testURLByRunID+ "?api-version=5.0"
$testURLByRunID = $testURLByRunID + "-preview.2"

write-host "To fetch the MOST RECENT run Test RUN ID"
write-host $testURLByRunID
$mostRecentTestRun = Invoke-RestMethod -Uri  $testURLByRunID -Headers $headers -Method Get | Select-Object id,name,url,build,isAutomated,iteration,owner,project,startedDate,completedDate,state,totalTests,incompleteTests,notApplicableTests,passedTests,unanalyzedTests,revision,webAccessUrl

#PRINT the values from the  REST calls 

write-host  "owner" $mostRecentTestRun.owner
write-host "startedDate" $mostRecentTestRun.startedDate
write-host "completedDate" $mostRecentTestRun.completedDate
write-host "totalTests" $mostRecentTestRun.totalTests
write-host "incompleteTests" $mostRecentTestRun.incompleteTests
write-host "notApplicableTests" $mostRecentTestRun.notApplicableTests
write-host "passedTests" $mostRecentTestRun.passedTests
write-host "unanalyzedTests" $mostRecentTestRun.unanalyzedTests
write-host "revision" $mostRecentTestRun.revision
write-host "webAccessUrl" $mostRecentTestRun.webAccessUrl


write-Host "##vso[task.setvariable variable=mostRecentRun;]$mostRecentTestRun


}  Catch  { $exception = $_.Exception
  $respstream = $exception.Response.GetResponseStream()
  $sr = new-object System.IO.StreamReader $respstream
  $ErrorResult = $sr.ReadToEnd()
  write-host $ErrorResult 
}

Tuesday, March 13, 2018

JPA Static Meta Model

  1. When you write a criteria query or create a dynamic entity graph, you need to reference the entity classes and their attributes.
  2. The quickest and easiest way is to provide the required names as Strings.
  3. But this has several drawbacks, e.g. you have to remember or look-up all the names of the entity attributes when you write the query.
  4. But it will also cause even greater issues at later phases of the project, if you have to refactor your entities and change the names of some attributes.
  5. In that case you have to use the search function of your IDE and try to find all Strings that reference the changed attributes.
  6. This is a tedious and error prone activity which will easily take up the most time of the refactoring
  7. Use the static metamodel to write criteria queries and dynamic entity graphs.
  8. This is a small feature defined by the JPA specification which provides a type-safe way to reference the entities and their properties.
  1. The Metamodel Generator also takes into consideration xml configuration specified in orm.xml or mapping files specified in persistence.xml. However, if all configuration is in XML you need to add in at least on of the mapping file the following persistence unit metadata:
    
      
    
    
  2. Maven dependency: The jar file for the annotation processor can be found as below.
    
        org.hibernate
        hibernate-jpamodelgen
        1.0.0
    
    
  3. Maven compiler plugin configuration - direct execution

    
        maven-compiler-plugin
        
            1.6
            1.6
            
                org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
            
        
    
    
  4. Maven compiler plugin configuration - indirect execution
    
        maven-compiler-plugin
        
            1.6
            1.6
            -proc:none
        
    
    

  5. Configuration with maven-processor-plugin
    
        org.bsc.maven
        maven-processor-plugin
        2.0.5
        
            
                process
                
                    process
                
                generate-sources
                
                                                    
                        org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
                    
                
            
        
        
            
                org.hibernate
                hibernate-jpamodelgen
                1.2.0.Final
            
        
    
    
  6. Javac Task configuration
    As mentioned before, the annotation processor will run automatically each time the Java compiler is called, provided the jar file is on the classpath.


    
        
    
    
  7. IDE Configuration
  1. A simple entity for this example.
    @Entity
    @Table(name="ALERT")
    public class AlertEO implements java.io.Serializable{
    
     private static final long serialVersionUID = 1L;
     private Integer id;
     private String name;
     private String description;
     /**
      * method to get serial Id
      * 
      * @return id
      */
     @Id
     @Column(name="id")
     @GeneratedValue(strategy = GenerationType.AUTO)
     public Integer getId() {
      return id;
     }
     
     /**
      * Functions to get id
      * @return id
      */
     public void setId(Integer id){
      this.id = id;
     }
    
     /**
      * Functions to get name
      * @return name
      */
     @Column(name = "name")
     public String getName(){
      return name;
     }
     
     /**
      * Functions to set name
      * @return name
      */
     public void setName(String name){
      this.name = name;
     }
    
     /**
      * Functions to get description
      * @return description
      */
     @Column(name = "description")
     public String getDescription(){
      return description;
     }
    
     /**
      * Functions to set description
      * @return description
      */
     public void setDescription(String description){
      this.description=description;
     }
      /* (non-Javadoc)
      * @see java.lang.Object#toString()
      */
     @Override
     public String toString() {
      return "AlertEO [id=" + id + ", name=" + name + ", description=" + description + "]";
     }
    



  2. The class of the static metamodel looks similar to the entity.
    Based on the JPA specification, there is a corresponding metamodel class for every managed class in the persistence unit.
    You can find it in the same package and it has the same name as the corresponding managed class with an added ‘_’ at the end

    @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
    @StaticMetamodel(AlertEO.class)
    public abstract class AlertEO_{
     public static volatile SingularAttribute<AlertEO, String>firstName;
     public static volatile SingularAttribute<AlertEO, String> lastName;
     public static volatile SetAttribute<AlertEO, Book> books;
     public static volatile SingularAttribute<AlertEO, Long> id;
     public static volatile SingularAttribute<AlertEO, Integer> version;
    }
    

  3. Using metamodel classes
  4. You can use the metamodel classes in the same way as you use the String reference to the entities and attributes.
  5. The APIs for criteria queries and dynamic entity graphs provide overloaded methods that accept Strings and implementations of the Attribute interface.

    CriteriaBuilder cb = this.em.getCriteriaBuilder();
    // create the query
    CriteriaQuey<AlertEO> q = cb.createQuery(AlertEO.class);
    // set the root class
    Root<AlertEO> a = q.from(AlertEO.class);
    // use metadata class to define the where clause
    q.where(cb.like(a.get(AlertEO_.name), "J%"));
    // perform query
    this.em.createQuery(q).getResultList();
    

Wednesday, January 10, 2018

ELK - Elastic, LogStash and Amazon Kibana - alternative for SPLUNK

ELK - Architecture

For more information on Kibana here is a nice article
 KIBANA SEARCH 

  1. Step 1- Install Elasticsearch
    1. Download elasticsearch zip file from https://www.elastic.co/downloads/elasticsearch
    2. Extract it to a directory (unzip it)
    3. Run it (bin/elasticsearch or bin/elasticsearch.bat on Windows)
    4. Check that it runs using curl -XGET http://localhost:9200
    5. Here's how to do it (steps are written for OS X but should be similar on other systems):
wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.1.zip
unzip elasticsearch-1.7.1.zip
cd elasticsearch-1.7.1
bin/elasticsearch
  1. Elasticsearch should be running now. You can verify it's running using curl. In a separate terminal window execute a GET request to Elasticsearch's status page:
curl -XGET http://localhost:9200
  1. If all is well, you should get the following result:
{
  "status" : 200,
  "name" : "Tartarus",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "1.7.1",
    "build_hash" : "b88f43fc40b0bcd7f173a1f9ee2e97816de80b19",
    "build_timestamp" : "2015-07-29T09:54:16Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}
  1. Step 2 - Install Kibana 4
  2. Download Kibana archive from https://www.elastic.co/downloads/kibana
  3. Please note that you need to download appropriate distribution for your OS, URL given in examples below is for OS X
  4. Extract the archive
  5. Run it (bin/kibana)
  6. Check that it runs by pointing the browser to the Kibana's WebUI
wget https://download.elastic.co/kibana/kibana/kibana-4.1.1-darwin-x64.tar.gz
tar xvzf kibana-4.1.1-darwin-x64.tar.gz
cd kibana-4.1.1-darwin-x64
bin/kibana
  1. Point your browser to http://localhost:5601 (if Kibana page shows up, we're good - we'll configure it later)
  1. Step 3) Install Logstash
  2. Download Logstash zip from https://www.elastic.co/downloads/logstash
  3. Extract it (unzip it)
wget https://download.elastic.co/logstash/logstash/logstash-1.5.3.zip
unzip logstash-1.5.3.zip
  1. Step 4) Configure Spring Boot's Log File
  2. In order to have Logstash ship log files to Elasticsearch, we must first configure Spring Boot to store log entries into a file.
  3. We will establish the following pipeline: Spring Boot App --> Log File --> Logstash --> Elasticsearch.
  4. There are other ways of accomplishing the same thing, such as configuring logback to use TCP appender to send logs to a remote Logstash instance via TCP, and many other configurations.
  5. Anyhow, let's configure Spring Boot's log file.
  6. The simplest way to do this is to configure log file name in application.properties.
  7. It's enough to add the following line:
logging.file=application.log
Spring Boot will now log ERROR, WARN and INFO level messages in the application.log log file and will also rotate it as it reaches 10 Mb.
  1. Step 5) Configure Logstash to Understand Spring Boot's Log File Format
  2. Typical Logstash config file consists of three main sections: input, filter and output.
  3. Each section contains plugins that do relevant part of the processing
  4. such as file input plugin that reads log events from a file or elasticsearch output plugin which sends log events to Elasticsearch.
  5. Input section defines from where Logstash will read input data
  6. in our case it will be a file hence we will use a file plugin with multiline codec, which basically means that our input file may have multiple lines per log entry.
input {
  file {
    type => "java"
    path => "/path/to/application.log"
    codec => multiline {
      pattern => "^%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}.*"
      negate => "true"
      what => "previous"
    }
  }
}
  1. Explanation
  2. We're using file plugin.
  3. type is set to java - it's just additional piece of metadata in case you will use multiple types of log files in the future.
  4. path is the absolute path to the log file. It must be absolute - Logstash is picky about this.
  5. We're using multiline codec which means that multiple lines may correspond to a single log event,
  6. In order to detect lines that should logically be grouped with a previous line we use a detection pattern:
  7. pattern => "^%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}.*" ? Each new log event needs to start with date.
  8. negate => "true" ? if it doesn't start with a date ...
  9. what => "previous" ? ... then it should be grouped with a previous line.
  10. File input plugin, as configured, will tail the log file (e.g. only read new entries at the end of the file). Therefore, when testing, in order for Logstash to read something you will need to generate new log entries.
  1. Filter Section
  2. Filter section contains plugins that perform intermediary processing on an a log event.
  3. In our case, event will either be a single log line or multiline log event grouped according to the rules described above.
  4. In the filter section we will do several things:
  5. Tag a log event if it contains a stacktrace. This will be useful when searching for exceptions later on.
  6. Parse out (or grok, in logstash terminology) timestamp, log level, pid, thread, class name (logger actually) and log message.
  7. Specified timestamp field and format - Kibana will use that later for time based searches.
  8. Filter section for Spring Boot's log format that aforementioned things looks like this:
filter {
  #If log line contains tab character followed by 'at' then we will tag that entry as stacktrace
  if [message] =~ "\tat" {
    grok {
      match => ["message", "^(\tat)"]
      add_tag => ["stacktrace"]
    }
  }

  #Grokking Spring Boot's default log format
  grok {
    match => [ "message", 
               "(?%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME})  %{LOGLEVEL:level} %{NUMBER:pid} --- \[(?[A-Za-z0-9-]+)\] [A-Za-z0-9.]*\.(?[A-Za-z0-9#_]+)\s*:\s+(?.*)",
               "message",
               "(?%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME})  %{LOGLEVEL:level} %{NUMBER:pid} --- .+? :\s+(?.*)"
             ]
  }

  #Parsing out timestamps which are in timestamp field thanks to previous grok section
  date {
    match => [ "timestamp" , "yyyy-MM-dd HH:mm:ss.SSS" ]
  }
}
  1. Explanation:
  2. if [message] =~ "\tat" ? If message contains tab character followed by at (this is ruby syntax) then...
  3. se the grok plugin to tag stacktraces:
  4. match => ["message", "^(\tat)"] ? when message matches beginning of the line followed by tab followed by at then..
  5. add_tag => ["stacktrace"] ? ... tag the event with stacktrace tag.
  6. Use the grok plugin for regular Spring Boot log message parsing:
  7. First pattern extracts timestamp, level, pid, thread, class name (this is actually logger name) and the log message.
  8. Unfortunately, some log messages don't have logger name that resembles a class name (for example, Tomcat logs) hence the second pattern that will skip the logger/class field and parse out timestamp, level, pid, thread and the log message.
  9. Use date plugin to parse and set the event date:
  10. match => [ "timestamp" , "yyyy-MM-dd HH:mm:ss.SSS" ] ? timestamp field (grokked earlier) contains the timestamp in the specified format
  1. Output Section
  2. Output section contains output plugins that send event data to a particular destination.
  3. Outputs are the final stage in the event pipeline.
  4. We will be sending our log events to stdout (console output, for debugging) and to Elasticsearch.
  5. Compared to filter section, output section is rather straightforward:
output {
  # Print each event to stdout, useful for debugging. Should be commented out in production.
  # Enabling 'rubydebug' codec on the stdout output will make logstash
  # pretty-print the entire event as something similar to a JSON representation.
  stdout {
    codec => rubydebug
  }

  # Sending properly parsed log events to elasticsearch
  elasticsearch {
   hosts => ["127.0.0.1"]  #  takes an array of hosts (e.g. elasticsearch cluster) as value. 
  }
}
  1. Putting it all together
  2. Finally, the three parts - input, filter and output - need to be copy pasted together and saved into logstash.conf config file.
  3. Once the config file is in place and Elasticsearch is running, we can run Logstash:
  4. /path/to/logstash/bin/logstash -f logstash.conf
  5. If everything went well, Logstash is now shipping log events to Elasticsearch.
  1. Step 6) Configure Kibana
  2. Ok, now it's time to visit the Kibana web UI again.
  3. We have started it in step 2 and it should be running at http://localhost:5601.
  4. First, you need to point Kibana to Elasticsearch index(s) of your choice.
  5. Logstash creates indices with the name pattern of logstash-YYYY.MM.DD.
  6. In Kibana Settings --> Indices configure the indices:
  7. Index contains time-based events (select this option)
  8. Use event times to create index names (select this option)
  9. Index pattern interval: Daily
  10. Index name or pattern: [logstash-]YYYY.MM.DD
  11. Click on "Create Index"
  12. Now click on "Discover" tab.
  13. It is the places for "Search" because it allows you to perform new searches and also to save/manage them.
  14. Log events should be showing up now in the main window.
  15. If they're not, then double check the time period filter in to right corner of the screen.
  16. Default table will have 2 columns by default: Time and _source.
  17. In order to make the listing more useful, we can configure the displayed columns.
  18. From the menu on the left select level, class and logmessage.
 Here is a sample output screent shot of the kibana console