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

test: add jaeger docker image with HANA trace information #1008

Merged
merged 2 commits into from
Feb 5, 2025
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
25 changes: 12 additions & 13 deletions hana/lib/drivers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class HANADriver {
* @returns {import('@cap-js/db-service/lib/SQLService').PreparedStatement}
*/
async prepare(sql) {
const prep = prom(
const prep = module.exports.prom(
this._native,
'prepare',
)(sql).then(stmt => {
Expand All @@ -29,22 +29,22 @@ class HANADriver {
run: async params => {
const { values, streams } = this._extractStreams(params)
const stmt = await prep
let changes = await prom(stmt, 'exec')(values)
let changes = await module.exports.prom(stmt, 'exec')(values)
await this._sendStreams(stmt, streams)
return { changes }
},
runBatch: async params => {
const stmt = await prep
const changes = await prom(stmt, 'exec')(params)
const changes = await module.exports.prom(stmt, 'exec')(params)
return { changes: !Array.isArray(changes) ? changes : changes.reduce((l, c) => l + c, 0) }
},
get: async params => {
const stmt = await prep
return (await prom(stmt, 'exec')(params))[0]
return (await module.exports.prom(stmt, 'exec')(params))[0]
},
all: async params => {
const stmt = await prep
return prom(stmt, 'exec')(params)
return module.exports.prom(stmt, 'exec')(params)
},
drop: async () => {
const stmt = await prep
Expand Down Expand Up @@ -85,12 +85,11 @@ class HANADriver {
*/
async exec(sql) {
await this.connected
return prom(this._native, 'exec')(sql)
return module.exports.prom(this._native, 'exec')(sql)
}

set(variables) {
variables
throw new Error('Implementation missing "set"')
this._native.set(variables)
}

/**
Expand All @@ -105,25 +104,25 @@ class HANADriver {
*/
async commit() {
await this.connected
return prom(this._native, 'commit')()
return module.exports.prom(this._native, 'commit')()
}

/**
* Rolls back the current transaction
*/
async rollback() {
await this.connected
return prom(this._native, 'rollback')()
return module.exports.prom(this._native, 'rollback')()
}

/**
* Connects the driver using the provided credentials
* @returns {Promise<any>}
*/
async connect() {
this.connected = prom(this._native, 'connect')(this._creds)
this.connected = module.exports.prom(this._native, 'connect')(this._creds)
return this.connected.then(async () => {
const version = await prom(this._native, 'exec')('SELECT VERSION FROM "SYS"."M_DATABASE"')
const version = await module.exports.prom(this._native, 'exec')('SELECT VERSION FROM "SYS"."M_DATABASE"')
const split = version[0].VERSION.split('.')
this.server = {
major: split[0],
Expand All @@ -141,7 +140,7 @@ class HANADriver {
if (this.connected) {
await this.connected
this.connected = false
return prom(this._native, 'disconnect')()
return module.exports.prom(this._native, 'disconnect')()
}
}

Expand Down
11 changes: 5 additions & 6 deletions hana/lib/drivers/hana-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,12 @@ class HANAClientDriver extends driver {
super(creds)
this._native = hdb.createConnection(creds)
this._native = wrap_client(this._native, creds, creds.tenant)
this._native.setAutoCommit(false)
}

set(variables) {
for (const key in variables) {
this._native.setClientInfo(key, variables[key])
this._native.set = function (variables) {
for (const key in variables) {
this.setClientInfo(key, variables[key])
}
}
this._native.setAutoCommit(false)
}

async prepare(sql, hasBlobs) {
Expand Down
14 changes: 7 additions & 7 deletions hana/lib/drivers/hdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,16 @@
this._native = wrap_client(this._native, creds, creds.tenant)
this._native.setAutoCommit(false)
this._native.on('close', () => this.destroy?.())
this._native.set = function(variables) {
const clientInfo = this._connection.getClientInfo()
for (const key in variables) {
clientInfo.setProperty(key, variables[key])
}
}

this.connected = false
}

set(variables) {
const clientInfo = this._native._connection.getClientInfo()
for (const key in variables) {
clientInfo.setProperty(key, variables[key])
}
}

async validate() {
return this._native.readyState === 'connected'
}
Expand Down Expand Up @@ -438,6 +437,7 @@
}

const { readInt64LE } = require('hdb/lib/util/bignum.js')
const { func } = require('@sap/cds/lib/ql/cds-ql')

Check warning on line 440 in hana/lib/drivers/hdb.js

View workflow job for this annotation

GitHub Actions / Tests (22)

'func' is assigned a value but never used
const readBlob = function (state, encoding) {
// Check if the blob is null
let ens = state.ensure(2)
Expand Down
30 changes: 30 additions & 0 deletions hana/tools/docker/hce/hana.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ services:
image: hana-master:current
restart: always
hostname: hcehost
networks:
- backend
command:
- --init
- role=worker:services=indexserver,dpserver,diserver:database=H00:create
Expand All @@ -20,3 +22,31 @@ services:
# - '30040:30040'
# - '30042:30042'
# - '30043:30043'

jaeger:
networks:
backend:
# This is the host name used in Prometheus scrape configuration.
aliases: [ spm_metrics_source ]
image: jaegertracing/jaeger:${JAEGER_VERSION:-latest}
volumes:
- "./jaeger.yaml:/etc/jaeger/config.yml"
command: ["--config", "/etc/jaeger/config.yml"]
ports:
- "16686:16686"
- "8888:8888"
- "8889:8889"
- "4317:4317"
- "4318:4318"

prometheus:
networks:
- backend
image: prom/prometheus:v3.1.0
volumes:
- "./prometheus.yml:/etc/prometheus/prometheus.yml"
ports:
- "9090:9090"

networks:
backend:
55 changes: 55 additions & 0 deletions hana/tools/docker/hce/jaeger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
service:
extensions: [jaeger_storage, jaeger_query]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [jaeger_storage_exporter, spanmetrics]
metrics/spanmetrics:
receivers: [spanmetrics]
exporters: [prometheus]
telemetry:
resource:
service.name: jaeger
metrics:
level: detailed
address: 0.0.0.0:8888
logs:
level: DEBUG

extensions:
jaeger_query:
max_clock_skew_adjust: 30s
storage:
traces: some_storage
metrics: some_metrics_storage
jaeger_storage:
backends:
some_storage:
memory:
max_traces: 100000
metric_backends:
some_metrics_storage:
prometheus:
endpoint: http://prometheus:9090
normalize_calls: true
normalize_duration: true

connectors:
spanmetrics:

receivers:
otlp:
protocols:
grpc:
http:
endpoint: "0.0.0.0:4318"

processors:
batch:

exporters:
jaeger_storage_exporter:
trace_storage: some_storage
prometheus:
endpoint: "0.0.0.0:8889"
64 changes: 64 additions & 0 deletions hana/tools/docker/hce/otel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash

# Directory containing the trace files
TRACE_DIR="/hana/mounts/trace/hana/DB_H00"

# OpenTelemetry endpoint
OTEL_ENDPOINT="http://jaeger:4318/v1/traces"

# Function to process a trace file
process_trace_file() {
local trace_file="$1"
tail -F "$trace_file" | awk -v RS='\n\n' 'function generate_span_id() {
cmd = "cat /proc/sys/kernel/random/uuid | tr -d \"-\" | cut -c1-16 | tr -d \"\n\""
cmd | getline span_id
close(cmd)
return span_id
}
{
split($0, fields, ";");
traceId=fields[22];
spanId=generate_span_id();
parentSpanId=substr(fields[24], 17);
startTime=fields[6] "000"; # Convert to nanoseconds
duration=fields[7] "000"; # Convert to nanoseconds
endTime=startTime + duration;
operation=fields[9];
statementString=fields[54];
memSize=fields[19];
cpuTime=fields[21];
gsub(/^#/, "", statementString);
gsub(/\n/, " ", statementString);
gsub(/"/, "\\\"", statementString);

# Prepare the JSON payload according to OpenTelemetry API structure
print sprintf("{\"resourceSpans\":[{\"resource\":{\"attributes\":[{\"key\":\"service.name\",\"value\":{\"stringValue\":\"@sap/hana-cloud\"}}]},\"scopeSpans\":[{\"spans\":[{\"traceId\":\"%s\",\"spanId\":\"%s\",\"parentSpanId\":\"%s\",\"name\":\"%s\",\"kind\":2,\"startTimeUnixNano\":\"%s\",\"endTimeUnixNano\":\"%s\",\"attributes\":[{\"key\":\"db.statement\",\"value\":{\"stringValue\":\"%s\"}},{\"key\":\"db.operation\",\"value\":{\"stringValue\":\"%s\"}},{\"key\":\"db.mem_size\",\"value\":{\"intValue\":%s}},{\"key\":\"db.cpu_time\",\"value\":{\"intValue\":%s}}]}]}]}]}", traceId, spanId, parentSpanId, operation, startTime, endTime, statementString, operation, memSize, cpuTime);
}' | while read -r json_payload; do
echo "$json_payload"
echo "$json_payload" | curl -X POST "$OTEL_ENDPOINT" -H "Content-Type: application/json" -d @-
done
}

# Function to handle script termination
cleanup() {
echo "Cleaning up..."
pkill -P $$
exit 0
}

# Trap signals to ensure cleanup
trap cleanup SIGINT SIGTERM

# Monitor the directory for new trace files and changes
declare -A processed_files

while true; do
for trace_file in "$TRACE_DIR"/*.expensive_statements.*.trc; do
if [ -f "$trace_file" ] && [ -z "${processed_files[$trace_file]}" ]; then
echo "Listening to $trace_file..."
process_trace_file "$trace_file" &
processed_files["$trace_file"]=1
fi
done
sleep 10
done
9 changes: 9 additions & 0 deletions hana/tools/docker/hce/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).

scrape_configs:
- job_name: aggregated-trace-metrics
static_configs:
- targets: ['spm_metrics_source:8889']
11 changes: 10 additions & 1 deletion hana/tools/docker/hce/ready.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
docker exec hce-hana-1 /bin/bash -c "while ! ./check_hana_health ; do sleep 10 ; done;"
until docker cp ./otel.sh hce-hana-1:/otel.sh
do
sleep 1
done

docker exec hce-hana-1 /bin/bash -c "while ! ./check_hana_health ; do sleep 10 ; done;/otel.sh &;"
docker exec -it hce-hana-1 /bin/bash -c "\
cd /usr/sap/H00/HDB00;\
. ./hdbenv.sh;\
hdbuserstore -i SET SYSDBKEY localhost:30013@SYSTEMDB SYSTEM Manager1;\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"SELECT COUNT(ACTIVE_STATUS) FROM SYS_DATABASES.M_SERVICES WHERE ACTIVE_STATUS='YES'\";\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"ALTER SYSTEM ALTER CONFIGURATION ('indexserver.ini', 'DATABASE', 'H00') SET ('session', 'enable_proxy_protocol') = 'false' WITH RECONFIGURE;\";\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"ALTER SYSTEM ALTER CONFIGURATION ('global.ini', 'System') SET ('public_hostname_resolution', 'use_default_route') = 'name' WITH RECONFIGURE;\";\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"ALTER SYSTEM ALTER CONFIGURATION ('global.ini', 'System') SET ('expensive_statement', 'enable') = 'TRUE' WITH RECONFIGURE;\";\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"ALTER SYSTEM ALTER CONFIGURATION ('global.ini', 'System') SET ('expensive_statement', 'threshold_duration') = '0' WITH RECONFIGURE;\";\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"ALTER SYSTEM ALTER CONFIGURATION ('global.ini', 'System') SET ('expensive_statement', 'trace_parameter_values') = 'FALSE' WITH RECONFIGURE;\";\
hdbsql -U \"SYSDBKEY\" -e -ssltrustcert \"ALTER SYSTEM ALTER CONFIGURATION ('global.ini', 'System') SET ('expensive_statement', 'use_in_memory_tracing') = 'FALSE' WITH RECONFIGURE;\";\
"