Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 37 additions & 0 deletions integration-tests/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,43 @@ services:
networks:
- integration-tests

mysql:
image: mysql:8.0
container_name: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: testdb
volumes:
- ./tests/database-observability-mysql/init_mysql.sh:/docker-entrypoint-initdb.d/init_mysql.sh
networks:
- integration-tests

postgres:
image: postgres:16
Comment thread
matthewnolf marked this conversation as resolved.
container_name: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: rootpassword
POSTGRES_DB: testdb
command: ["postgres", "-c", "shared_preload_libraries=pg_stat_statements", "-c", "pg_stat_statements.track=all"]
networks:
- integration-tests

postgres-init:
image: postgres:16
depends_on:
- postgres
volumes:
- ./tests/database-observability-postgres/init_postgres.sh:/init_postgres.sh
command: sh /init_postgres.sh
restart: "no"
networks:
- integration-tests

networks:
integration-tests:
driver: bridge
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// WARNING: This configuration is for integration testing only.
// It is not intended to represent a recommended production configuration.

prometheus.exporter.mysql "mysql" {
Comment thread
cristiangreco marked this conversation as resolved.
data_source_name = "root:rootpassword@tcp(mysql:3306)/testdb"
}

database_observability.mysql "test" {
data_source_name = "root:rootpassword@tcp(mysql:3306)/testdb"
forward_to = [loki.write.default.receiver]
targets = prometheus.exporter.mysql.mysql.targets

query_samples {
collect_interval = "1s"
}

query_details {
collect_interval = "1s"
}

schema_details {
collect_interval = "1s"
}

explain_plans {
collect_interval = "1s"
}

health_check {
collect_interval = "1s"
}
}

prometheus.scrape "mysql" {
targets = database_observability.mysql.test.targets
forward_to = [prometheus.remote_write.default.receiver]
}

prometheus.remote_write "default" {
endpoint {
url = "http://mimir:9009/api/v1/push"
}
external_labels = {
test_name = "database_observability_mysql",
}
}

loki.write "default" {
endpoint {
url = "http://loki:3100/loki/api/v1/push"
}
external_labels = {
test_name = "database_observability_mysql",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash
set -e

echo "Creating test tables..."

mysql -u root -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" <<EOF
-- Create products table
CREATE TABLE IF NOT EXISTS products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
quantity INT DEFAULT 0
);

-- Create orders table
CREATE TABLE IF NOT EXISTS orders (
id INT PRIMARY KEY AUTO_INCREMENT,
product_id INT,
quantity INT NOT NULL,
total DECIMAL(10, 2) NOT NULL,
status VARCHAR(50) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Insert test data into products
INSERT INTO products (name, price, quantity) VALUES
('Widget', 19.99, 100),
('Gadget', 29.99, 50),
('Gizmo', 39.99, 25);

-- Insert test data into orders
INSERT INTO orders (product_id, quantity, total, status) VALUES
(1, 2, 39.98, 'completed'),
(2, 1, 29.99, 'pending'),
(3, 3, 119.97, 'shipped');

-- Run some queries to populate performance_schema
SELECT * FROM products WHERE id = 1;
SELECT * FROM products WHERE price > 20;
SELECT * FROM orders WHERE status = 'pending';
SELECT p.name, o.total FROM products p JOIN orders o ON p.id = o.product_id;
EOF

echo "Test tables and data created successfully!"
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//go:build alloyintegrationtests

package main

import (
"testing"

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

"github.com/grafana/alloy/integration-tests/docker/common"
)

const testName = "database_observability_mysql"

func TestDatabaseObservabilityMySQLMetrics(t *testing.T) {
var metrics = []string{
"database_observability_connection_info",
}
common.MimirMetricsTest(t, metrics, []string{}, testName)
}

func TestDatabaseObservabilityMySQLLogs(t *testing.T) {
common.AssertStatefulTestEnv(t)

expectedOps := []string{
"health_status",
"query_association",
"query_parsed_table_name",
"schema_detection",
"table_detection",
"create_statement",
}

var logResponse common.LogResponse

require.EventuallyWithT(t, func(c *assert.CollectT) {
_, err := common.FetchDataFromURL(common.LogQuery(testName, 100), &logResponse)
assert.NoError(c, err)

ops := make(map[string]bool)
for _, result := range logResponse.Data.Result {
if op, ok := result.Stream["op"]; ok {
ops[op] = true
}
}

for _, op := range expectedOps {
assert.True(c, ops[op], "expected %s logs", op)
}
}, common.TestTimeoutEnv(t), common.DefaultRetryInterval)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// WARNING: This configuration is for integration testing only.
// It is not intended to represent a recommended production configuration.

prometheus.exporter.postgres "postgres" {
data_source_names = ["postgresql://root:rootpassword@postgres:5432/testdb?sslmode=disable"]
}

database_observability.postgres "test" {
data_source_name = "postgresql://root:rootpassword@postgres:5432/testdb?sslmode=disable"
forward_to = [loki.write.default.receiver]
targets = prometheus.exporter.postgres.postgres.targets

query_samples {
collect_interval = "1s"
}

query_details {
collect_interval = "1s"
}

schema_details {
collect_interval = "1s"
}

explain_plans {
collect_interval = "1s"
}

health_check {
collect_interval = "1s"
}
}

prometheus.scrape "postgres" {
targets = database_observability.postgres.test.targets
forward_to = [prometheus.remote_write.default.receiver]
}

prometheus.remote_write "default" {
endpoint {
url = "http://mimir:9009/api/v1/push"
}
external_labels = {
test_name = "database_observability_postgres",
}
}

loki.write "default" {
endpoint {
url = "http://loki:3100/loki/api/v1/push"
}
external_labels = {
test_name = "database_observability_postgres",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash
set -e

# Wait for PostgreSQL to be ready
echo "Waiting for PostgreSQL to be ready..."
until PGPASSWORD=rootpassword psql -h postgres -U root -d testdb -c "SELECT 1" > /dev/null 2>&1; do
sleep 1
done

echo "PostgreSQL is ready. Enabling pg_stat_statements and creating test tables..."

PGPASSWORD=rootpassword psql -h postgres -U root -d testdb <<EOF
-- Enable pg_stat_statements extension
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

-- Create products table
CREATE TABLE IF NOT EXISTS products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
quantity INT DEFAULT 0
);

-- Create orders table
CREATE TABLE IF NOT EXISTS orders (
id SERIAL PRIMARY KEY,
product_id INT,
quantity INT NOT NULL,
total DECIMAL(10, 2) NOT NULL,
status VARCHAR(50) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Insert test data into products
INSERT INTO products (name, price, quantity) VALUES
('Widget', 19.99, 100),
('Gadget', 29.99, 50),
('Gizmo', 39.99, 25);

-- Insert test data into orders
INSERT INTO orders (product_id, quantity, total, status) VALUES
(1, 2, 39.98, 'completed'),
(2, 1, 29.99, 'pending'),
(3, 3, 119.97, 'shipped');

-- Run some queries to populate pg_stat_statements
SELECT * FROM products WHERE id = 1;
SELECT * FROM products WHERE price > 20;
SELECT * FROM orders WHERE status = 'pending';
SELECT p.name, o.total FROM products p JOIN orders o ON p.id = o.product_id;
EOF

echo "Test tables and data created successfully!"
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//go:build alloyintegrationtests

package main

import (
"testing"

"github.com/grafana/alloy/integration-tests/docker/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const testName = "database_observability_postgres"

func TestDatabaseObservabilityPostgresMetrics(t *testing.T) {
var metrics = []string{
"database_observability_connection_info",
}
common.MimirMetricsTest(t, metrics, []string{}, testName)
}

func TestDatabaseObservabilityPostgresLogs(t *testing.T) {
common.AssertStatefulTestEnv(t)

expectedOps := []string{
"health_status",
"query_association",
"query_parsed_table_name",
"schema_detection",
"table_detection",
"create_statement",
}

var logResponse common.LogResponse

require.EventuallyWithT(t, func(c *assert.CollectT) {
_, err := common.FetchDataFromURL(common.LogQuery(testName, 100), &logResponse)
assert.NoError(c, err)

ops := make(map[string]bool)
for _, result := range logResponse.Data.Result {
if op, ok := result.Stream["op"]; ok {
ops[op] = true
}
}

for _, op := range expectedOps {
assert.True(c, ops[op], "expected %s logs", op)
}
}, common.TestTimeoutEnv(t), common.DefaultRetryInterval)
}
Loading