Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/32089 generic sql enchancement #32293

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
4c62bba
x-pack/filebeat/module/cisco: remove invalid values from ECS fields (…
agithomas May 16, 2022
3c39232
Merge branch 'elastic:main' into main
agithomas May 19, 2022
d1c97af
Merge branch 'elastic:main' into main
agithomas May 27, 2022
aa4f464
Merge branch 'elastic:main' into main
agithomas May 31, 2022
d9e070c
Merge branch 'elastic:main' into main
agithomas Jun 3, 2022
a089576
Merge branch 'elastic:main' into main
agithomas Jun 5, 2022
5173fda
Merge branch 'elastic:main' into main
agithomas Jun 6, 2022
f429eaf
Merge branch 'elastic:main' into main
agithomas Jul 1, 2022
4640072
Merge branch 'elastic:main' into main
agithomas Jul 6, 2022
c795711
Merge branch 'elastic:main' into main
agithomas Jul 7, 2022
ea7b9cf
Merge branch 'elastic:main' into main
agithomas Jul 11, 2022
978a3fe
Upgrade Generic SQL to support new connection string and special char…
agithomas Jul 11, 2022
395d974
Code formatted
agithomas Jul 11, 2022
9ee53a5
Changes to support Oracle for integration testing
agithomas Jul 11, 2022
746a767
Merge branch 'elastic:main' into main
agithomas Jul 12, 2022
6d1fe61
Merge remote-tracking branch 'upstream/main' into feature/32089-gener…
agithomas Jul 12, 2022
702ee4c
Improved the change log entry
agithomas Jul 12, 2022
901a010
Modified the documentation
agithomas Jul 19, 2022
e2fcedc
Revert "Modified the documentation"
agithomas Jul 19, 2022
053ca1d
Improved the change log entry
agithomas Jul 19, 2022
50bfaee
Added oracle connectiions pre-requesites
agithomas Jul 20, 2022
aba3c57
Improved the documentation
agithomas Jul 20, 2022
f75a9ab
Merge branch 'elastic:main' into main
agithomas Jul 20, 2022
2b1e322
Merge branch 'feature/32089-generic-sql-enchancement' of github.com:a…
agithomas Jul 20, 2022
bcd5153
Fixed the documentation issue
agithomas Jul 20, 2022
3a8d405
Documention rollback to solve cicd issues
agithomas Jul 20, 2022
bcddf95
Documentation rollback
agithomas Jul 20, 2022
c848643
Revert "Improved the change log entry"
agithomas Jul 20, 2022
e424e9b
Added oracle documentation
agithomas Jul 20, 2022
27bacae
Oracle documentation updated
agithomas Jul 20, 2022
7723142
Merge branch 'elastic:main' into main
agithomas Sep 23, 2022
1bad1ac
Merge branch 'elastic:main' into main
agithomas Oct 20, 2022
be6298a
Merge branch 'elastic:main' into main
agithomas Oct 21, 2022
047a198
Merge branch 'elastic:main' into main
agithomas Nov 3, 2022
7a5c22b
Changes made as per review comments
agithomas Nov 10, 2022
1007f68
Minor documentation corrections
agithomas Nov 10, 2022
85a89d8
Merge branch 'elastic:main' into main
agithomas Nov 10, 2022
fcc225d
Minor corrections to changelog
agithomas Nov 10, 2022
5de710b
Resolving conflicts
agithomas Nov 10, 2022
6b08991
Merge branch 'main' into feature/32089-generic-sql-enchancement
agithomas Nov 10, 2022
877ca6f
Resolved typo
agithomas Nov 10, 2022
451dd8f
Merge branch 'feature/32089-generic-sql-enchancement' of https://gith…
agithomas Nov 10, 2022
3da67a8
Rearranged doc section
agithomas Nov 10, 2022
a1ec6ab
Rolling back changes
agithomas Nov 10, 2022
33c7da4
Document updated
agithomas Nov 10, 2022
8c4908d
Updated ORACLE_SID reference from doc
agithomas Nov 10, 2022
84dfa27
Changes as per review comments addded
agithomas Nov 14, 2022
b32336e
Changes as per review comments addded
agithomas Nov 14, 2022
c0ee4ac
Merge branch 'main' of https://github.com/agithomas/beats into featur…
agithomas Nov 14, 2022
0e05f65
Merge branch 'main' of https://github.com/elastic/beats into feature/…
agithomas Nov 14, 2022
79acb88
Update changelog
agithomas Nov 14, 2022
f26385b
Change log corrected
agithomas Nov 14, 2022
f5ce180
Update metricbeat/docs/modules/sql.asciidoc
agithomas Nov 15, 2022
a011101
Update metricbeat/docs/modules/sql.asciidoc
agithomas Nov 15, 2022
22d2848
Update metricbeat/docs/modules/sql.asciidoc
agithomas Nov 15, 2022
a8a8b7f
Update metricbeat/docs/modules/sql.asciidoc
agithomas Nov 15, 2022
f7d2c99
Updated sql.asciidoc
agithomas Nov 15, 2022
c575d05
Merge branch 'main' into feature/32089-generic-sql-enchancement
agithomas Nov 15, 2022
190a8dc
Updated the sql.asciidoc
agithomas Nov 15, 2022
c15232e
Merge branch 'feature/32089-generic-sql-enchancement' of https://gith…
agithomas Nov 15, 2022
d8d20f6
Updated the sql.asciidoc
agithomas Nov 15, 2022
9d36cc1
Updated generated doc
agithomas Nov 15, 2022
5a2c984
Merge branch 'main' into feature/32089-generic-sql-enchancement
agithomas Nov 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ https://github.com/elastic/beats/compare/v8.2.0\...main[Check the HEAD diff]
- Enhance Oracle Module: Connection string for Oracle does not handle special characters properly {issue}24609[24609] {pull}31368[#31368]
- Enhance Oracle Module: New sysmetric metricset {issue}30946[30946] {pull}31462[#31462]
- Upgrade Mongodb library in Beats to v5 {pull}31185[31185]
- Upgrade Generic SQL to support new connection string and special character support {issue}32089[32089]
agithomas marked this conversation as resolved.
Show resolved Hide resolved

*Packetbeat*

Expand Down
5 changes: 5 additions & 0 deletions x-pack/metricbeat/module/sql/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ services:
extends:
file: ../../../../metricbeat/module/postgresql/docker-compose.yml
service: postgresql

oracle:
extends:
file: ../../../../x-pack/metricbeat/module/oracle/docker-compose.yml
service: oracle
37 changes: 37 additions & 0 deletions x-pack/metricbeat/module/sql/query/dsn.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,54 @@
package query

import (
"fmt"
"net/url"

"github.com/go-sql-driver/mysql"
"github.com/godror/godror"
"github.com/godror/godror/dsn"

"github.com/elastic/beats/v7/metricbeat/mb"
)

// ConnectionDetails contains all possible data that can be used to create a connection with
// an Oracle db
type ConnectionDetails struct {
Username string `config:"username"`
Password string `config:"password"`
Driver string `config:"driver"`
}

// ParseDSN tries to parse the host
func ParseDSN(mod mb.Module, host string) (mb.HostData, error) {
// TODO: Add support for `username` and `password` as module options
config := ConnectionDetails{}
if err := mod.UnpackConfig(&config); err != nil {
return mb.HostData{}, fmt.Errorf("error parsing config file: %w", err)
}

if config.Driver == "oracle" {
params, err := godror.ParseDSN(host)
if err != nil {
return mb.HostData{}, fmt.Errorf("error trying to parse connection string in field 'hosts': %w", err)
}

if params.Username == "" {
params.Username = config.Username
}

if params.Password.Secret() == "" {
params.StandaloneConnection = true
params.Password = dsn.NewPassword(config.Password)
}
return mb.HostData{
URI: params.StringWithPassword(),
SanitizedURI: params.ConnectString,
agithomas marked this conversation as resolved.
Show resolved Hide resolved
Host: params.String(),
User: params.Username,
Password: params.Password.Secret(),
}, nil
}
agithomas marked this conversation as resolved.
Show resolved Hide resolved
sanitized := sanitize(host)

return mb.HostData{
Expand Down
78 changes: 77 additions & 1 deletion x-pack/metricbeat/module/sql/query/query_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ package query
import (
"fmt"
"net"
"os"
"testing"
"time"

"github.com/godror/godror"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -48,7 +51,6 @@ func TestMySQL(t *testing.T) {
Host: mysql.GetMySQLEnvDSN(service.Host()),
Assertion: assertFieldNotContains("service.address", ":test@"),
}

t.Run("fetch", func(t *testing.T) {
testFetch(t, cfg)
})
Expand Down Expand Up @@ -186,6 +188,27 @@ func TestPostgreSQL(t *testing.T) {
})
}

func TestOracle(t *testing.T) {
service := compose.EnsureUp(t, "oracle")
host, port, _ := net.SplitHostPort(service.Host())
cfg := testFetchConfig{
config: config{
Driver: "oracle",
Query: `SELECT name, physical_reads, db_block_gets, consistent_gets, 1 - (physical_reads / (db_block_gets + consistent_gets)) "Hit_Ratio" FROM V$BUFFER_POOL_STATISTICS`,
ResponseFormat: tableResponseFormat,

RawData: rawData{
Enabled: true,
},
},
Host: GetOracleConnectionDetails(host, port),
Assertion: assertFieldContainsFloat64("Hit_Ratio", 0.0),
}
t.Run("fetch", func(t *testing.T) {
testFetch(t, cfg)
})
}

func testFetch(t *testing.T, cfg testFetchConfig) {
m := mbtest.NewFetcher(t, getConfig(cfg))
events, errs := m.FetchEvents()
Expand Down Expand Up @@ -230,3 +253,56 @@ func assertFieldNotContains(field, s string) func(t *testing.T, event beat.Event
require.NotContains(t, value.(string), s)
}
}

func assertFieldContainsFloat64(field string, limit float64) func(t *testing.T, event beat.Event) {
return func(t *testing.T, event beat.Event) {
value, err := event.GetValue("sql.metrics.hit_ratio")
assert.NoError(t, err)
require.GreaterOrEqual(t, value.(float64), limit)
}
}

func GetOracleConnectionDetails(host string, port string) string {

agithomas marked this conversation as resolved.
Show resolved Hide resolved
params, _ := godror.ParseDSN(GetOracleConnectString(host, port))
agithomas marked this conversation as resolved.
Show resolved Hide resolved
return params.StringWithPassword()
}

// GetOracleEnvServiceName returns the service name to use with Oracle testing server or the value of the environment variable ORACLE_SERVICE_NAME if not empty
func GetOracleEnvServiceName() string {
serviceName := os.Getenv("ORACLE_SERVICE_NAME")

if len(serviceName) == 0 {
serviceName = "ORCLCDB.localdomain"
}
return serviceName
}

// GetOracleEnvUsername returns the username to use with Oracle testing server or the value of the environment variable ORACLE_USERNAME if not empty
func GetOracleEnvUsername() string {
username := os.Getenv("ORACLE_USERNAME")

if len(username) == 0 {
username = "sys"
}
return username
}

// GetOracleEnvUsername returns the port of the Oracle server or the value of the environment variable ORACLE_PASSWORD if not empty
func GetOracleEnvPassword() string {
password := os.Getenv("ORACLE_PASSWORD")

if len(password) == 0 {
password = "Oradoc_db1" // #nosec
}
return password
}

func GetOracleConnectString(host string, port string) string {
time.Sleep(300 * time.Second)
connectString := os.Getenv("ORACLE_CONNECT_STRING")
if len(connectString) == 0 {
connectString = fmt.Sprintf("%s/%s@%s:%s/%s as sysdba", GetOracleEnvUsername(), GetOracleEnvPassword(), host, port, GetOracleEnvServiceName())
}
return connectString
}
50 changes: 50 additions & 0 deletions x-pack/metricbeat/module/sql/query/test_sql_oracle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
import sys
import unittest
import time
from xpack_metricbeat import XPackTest, metricbeat


class Test(XPackTest):

COMPOSE_SERVICES = ['oracle']

@unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test")
def test_query(self):
"""
sql oracle custom query test
"""
self.render_config_template(modules=[{
"name": "sql",
"metricsets": ["query"],
"hosts": self.get_hosts(),
"period": "5s",
"additional_content": """
driver: oracle
sql_query: 'SELECT name, physical_reads, db_block_gets, consistent_gets, 1 - (physical_reads / (db_block_gets + consistent_gets)) FROM V$BUFFER_POOL_STATISTICS'
sql_response_format: table"""
}])
proc = self.start_beat(home=self.beat_path)
self.wait_until(lambda: self.output_lines() > 0)
self.wait_until(lambda: self.check_for_events(), max_timeout=300)
proc.check_kill_and_wait()
self.assert_no_logged_warnings()

output = self.read_output_json()
self.assertGreater(len(output), 0)

event_valid_counter = False
for evt in output:
if evt.get("sql") and evt["sql"].get("query"):
event_valid_counter = True

def check_for_events(self):
output = self.read_output_json()
for evt in output:
if evt.get("sql") and evt["sql"].get("query"):
return True

return False

def get_hosts(self):
return ['user="sys" password="Oradoc_db1" connectString="{}/ORCLPDB1.localdomain" sysdba=true'.format(self.compose_host())]