spec/elastic_apm/transaction_spec.rb (138 lines of code) (raw):
# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# frozen_string_literal: true
require 'spec_helper'
module ElasticAPM
RSpec.describe Transaction do
subject { described_class.new config: config }
let(:config) { Config.new }
describe '#initialize', :mock_time do
its(:id) { should_not be_nil }
its(:type) { should eq 'custom' }
it { should be_sampled }
its(:trace_context) { should be_a TraceContext }
its(:context) { should be_a Context }
its(:span_frames_min_duration) { should be_a Float }
its(:collect_metrics) { should be true }
its(:breakdown_metrics) { should be true }
its(:framework_name) { should be nil }
its(:transaction_max_spans) { should be_a Integer }
its(:started_spans) { should be 0 }
its(:dropped_spans) { should be 0 }
its(:notifications) { should be_empty }
its(:trace_id) { should be subject.trace_context.trace_id }
context 'with labels from context and config' do
let(:config) { Config.new(default_labels: { args: 'yes' }) }
it 'merges labels' do
context = Context.new(labels: { context: 'yes' })
subject = described_class.new(config: config, context: context)
expect(subject.context.labels).to match(args: 'yes', context: 'yes')
end
end
context 'trace context' do
context 'when sampled' do
it 'is `recorded?\' and has sample_rate > 0' do
t = Transaction.new(config: config)
expect(t.trace_context.recorded?).to be true
expect(t.trace_context.tracestate.sample_rate).to be_between(0.1, 1)
end
end
context 'when NOT sampled' do
it 'is not `recorded?\' and has sample_rate == 0' do
t = Transaction.new(config: config, sampled: false)
expect(t.trace_context.recorded?).to be false
expect(t.trace_context.tracestate.sample_rate).to eq 0
end
end
end
end
describe '#start', :mock_time do
it 'sets timestamp' do
expect(subject.start.timestamp).to be Util.micros
end
end
describe '#stop', :mock_time do
it 'sets duration' do
subject.start
travel 100
expect(subject.stop.duration).to eq 100
expect(subject).to be_stopped
end
it 'calculates self_time' do
subject.start
travel 100
subject.stop
expect(subject.self_time).to eq 100
end
context 'with a child span' do
it 'calculates self_time' do
transaction = subject.start
travel 100
span = Span.new(
name: 'span',
transaction: transaction,
trace_context: nil,
parent: transaction
).start
travel 100
span.stop
travel 100
subject.stop
expect(subject.duration).to eq 300
expect(subject.self_time).to eq 200
end
end
end
describe '#done', :mock_time do
it 'it sets result, durations' do
subject.start
travel 100
subject.done('HTTP 200')
expect(subject).to be_stopped
expect(subject.duration).to be 100
expect(subject.result).to eq 'HTTP 200'
end
end
describe '#ensure_parent_id' do
it 'sets and returns a new parent id if missing' do
parent_id = subject.ensure_parent_id
expect(subject.parent_id).to_not be_nil
expect(subject.parent_id).to eq parent_id
end
it 'keeps and returns current parent id if set' do
trace_context = TraceContext.new
trace_context.traceparent.parent_id = 'things'
subject = Transaction.new config: config, trace_context: trace_context
parent_id = subject.ensure_parent_id
expect(parent_id).to eq 'things'
expect(subject.parent_id).to eq 'things'
end
end
describe '#inc_started_spans!' do
let!(:result) { subject.inc_started_spans! }
it 'increments started count' do
expect(subject.started_spans).to be(1)
end
it 'returns true' do
expect(result).to be true
end
context 'when max spans is reached' do
let(:config) { Config.new(transaction_max_spans: 3) }
let!(:result) do
3.times { subject.inc_started_spans! }
subject.inc_started_spans!
end
it 'increments dropped spans' do
expect(subject.dropped_spans).to be(1)
end
it 'returns false' do
expect(result).to be false
end
end
end
describe '#add_response' do
it 'adds http response to context' do
subject.add_response(200, headers: { 'Ok' => 'yes' })
expect(subject.context.response.status_code).to be 200
expect(subject.context.response.headers).to match('Ok' => 'yes')
end
end
end
end