Commit 9395be32 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents d06de98f 2a93b6af
......@@ -55,6 +55,12 @@ zcat @400000006026b71d1a7af804.s | (head -1; tail -1) | jq '.time'
zcat some_json.log.25.gz | (head -1; tail -1) | jq '.time'
```
#### Get activity for correlation ID across multiple JSON logs in chronological order
```shell
grep -hR <correlationID> | jq -c -R 'fromjson?' | jq -C -s 'sort_by(.time)' | less -R
```
### Parsing `production_json.log` and `api_json.log`
#### Find all requests with a 5XX status code
......
export function removeTrialSuffix(planName) {
return planName.replace(/ trial\b/i, '');
}
......@@ -3,5 +3,3 @@ export const TABLE_TYPE_FREE = 'free';
export const TABLE_TYPE_TRIAL = 'trial';
export const DAYS_FOR_RENEWAL = 15;
export const PLAN_TITLE_TRIAL_TEXT = ' Trial';
......@@ -2,12 +2,12 @@
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import { removeTrialSuffix } from 'ee/billings/billings_util';
import {
TABLE_TYPE_DEFAULT,
TABLE_TYPE_FREE,
TABLE_TYPE_TRIAL,
DAYS_FOR_RENEWAL,
PLAN_TITLE_TRIAL_TEXT,
} from 'ee/billings/constants';
import ExtendReactivateTrialButton from 'ee/trials/extend_reactivate_trial/components/extend_reactivate_trial_button.vue';
import createFlash from '~/flash';
......@@ -79,7 +79,7 @@ export default {
subscriptionHeader() {
const planName = this.isFreePlan
? s__('SubscriptionTable|Free')
: escape(this.planName.replace(PLAN_TITLE_TRIAL_TEXT, ''));
: escape(removeTrialSuffix(this.planName));
const suffix = this.isSubscription && this.plan.trial ? s__('SubscriptionTable|Trial') : '';
return `${this.namespaceName}: ${planName} ${suffix}`;
......
......@@ -2,6 +2,7 @@
import { GlButton, GlPopover, GlSprintf } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { debounce } from 'lodash';
import { removeTrialSuffix } from 'ee/billings/billings_util';
import axios from '~/lib/utils/axios_utils';
import { formatDate } from '~/lib/utils/datetime_utility';
import { sprintf } from '~/locale';
......@@ -56,10 +57,13 @@ export default {
formattedTrialEndDate() {
return formatDate(this.trialEndDate, trialEndDateFormatString);
},
planNameWithoutTrial() {
return removeTrialSuffix(this.planName);
},
upgradeButtonTitle() {
return sprintf(this.$options.i18n.upgradeButtonTitle, {
groupName: this.groupName,
planName: this.planName,
planName: removeTrialSuffix(this.planName),
});
},
},
......@@ -162,7 +166,7 @@ export default {
<template #bold="{ content }">
<b>{{ sprintf(content, { trialEndDate: formattedTrialEndDate }) }}</b>
</template>
<template #planName>{{ planName }}</template>
<template #planName>{{ planNameWithoutTrial }}</template>
</gl-sprintf>
<div class="gl-mt-5">
......
<script>
import { GlLink, GlProgressBar } from '@gitlab/ui';
import { removeTrialSuffix } from 'ee/billings/billings_util';
import { sprintf } from '~/locale';
import Tracking from '~/tracking';
import { EXPERIMENT_KEY, WIDGET } from './constants';
......@@ -26,7 +27,7 @@ export default {
const i18nWidgetTitle = i18n.widgetTitle.countableTranslator(this.daysRemaining);
return sprintf(i18nWidgetTitle, {
planName: this.planName,
planName: removeTrialSuffix(this.planName),
enDash: '',
num: this.daysRemaining,
});
......
......@@ -86,6 +86,15 @@ describe('TrialStatusPopover component', () => {
expectTracking(trackingEvents.compareBtnClick);
});
it('does not include the word "Trial" if the plan name includes it', () => {
wrapper = createComponent({ planName: 'Ultimate Trial' }, mount);
const popoverText = wrapper.text();
expect(popoverText).toContain('We hope you’re enjoying the features of GitLab Ultimate.');
expect(popoverText).toMatch(/Upgrade Some Test Group to Ultimate(?! Trial)/);
});
describe('startInitiallyShown', () => {
const userCalloutProviders = {
userCalloutsPath: 'user_callouts/path',
......
......@@ -64,6 +64,12 @@ describe('TrialStatusWidget component', () => {
unmockTracking();
});
it('does not render Trial twice if the plan name includes "Trial"', () => {
wrapper = createComponent({ planName: 'Ultimate Trial' });
expect(wrapper.text()).toEqual('Ultimate Trial – 20 days left');
});
});
describe('with the optional containerId prop', () => {
......
# frozen_string_literal: true
module Gitlab
module Pagination
module Keyset
class CursorBasedRequestContext
attr_reader :request
delegate :params, :header, to: :request
def initialize(request)
@request = request
end
def per_page
params[:per_page]
end
def cursor
params[:cursor]
end
def apply_headers(cursor_for_next_page)
Gitlab::Pagination::Keyset::HeaderBuilder
.new(self)
.add_next_page_header({ cursor: cursor_for_next_page })
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module Pagination
module Keyset
class CursorPager < Gitlab::Pagination::Base
attr_reader :cursor_based_request_context, :paginator
def initialize(cursor_based_request_context)
@cursor_based_request_context = cursor_based_request_context
end
def paginate(relation)
@paginator ||= relation.keyset_paginate(
per_page: cursor_based_request_context.per_page,
cursor: cursor_based_request_context.cursor
)
paginator.records
end
def finalize(_records = [])
# can be called only after executing `paginate(relation)`
apply_headers
end
private
def apply_headers
return unless paginator.has_next_page?
cursor_based_request_context
.apply_headers(paginator.cursor_for_next_page)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Pagination::Keyset::CursorBasedRequestContext do
let(:params) { { per_page: 2, cursor: 'eyJuYW1lIjoiR2l0TGFiIEluc3RhbmNlIiwiaWQiOiI1MiIsIl9rZCI6Im4ifQ==' } }
let(:request) { double('request', params: params) }
describe '#per_page' do
subject(:per_page) { described_class.new(request).per_page }
it { is_expected.to eq 2 }
end
describe '#cursor' do
subject(:cursor) { described_class.new(request).cursor }
it { is_expected.to eq 'eyJuYW1lIjoiR2l0TGFiIEluc3RhbmNlIiwiaWQiOiI1MiIsIl9rZCI6Im4ifQ==' }
end
describe '#apply_headers' do
let(:request) { double('request', url: "http://#{Gitlab.config.gitlab.host}/api/v4/projects?per_page=3", params: params) }
let(:params) { { per_page: 3 } }
let(:cursor_for_next_page) { 'eyJuYW1lIjoiSDVicCIsImlkIjoiMjgiLCJfa2QiOiJuIn0=' }
subject(:apply_headers) { described_class.new(request).apply_headers(cursor_for_next_page) }
it 'sets Link header with same host/path as the original request' do
orig_uri = URI.parse(request.url)
expect(request).to receive(:header).once do |name, header|
first_link, _ = /<([^>]+)>; rel="next"/.match(header).captures
uri = URI.parse(first_link)
expect(name).to eq('Link')
expect(uri.host).to eq(orig_uri.host)
expect(uri.path).to eq(orig_uri.path)
end
apply_headers
end
it 'sets Link header with a cursor to the next page' do
orig_uri = URI.parse(request.url)
expect(request).to receive(:header).once do |name, header|
first_link, _ = /<([^>]+)>; rel="next"/.match(header).captures
query = CGI.parse(URI.parse(first_link).query)
expect(name).to eq('Link')
expect(query.except('cursor')).to eq(CGI.parse(orig_uri.query).except('cursor'))
expect(query['cursor']).to eq([cursor_for_next_page])
end
apply_headers
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Pagination::Keyset::CursorPager do
let(:relation) { Group.all.order(:name, :id) }
let(:per_page) { 3 }
let(:params) { { cursor: nil, per_page: per_page } }
let(:request) { double('request', params: params) }
let(:cursor_based_request_context) { Gitlab::Pagination::Keyset::CursorBasedRequestContext.new(request) }
before_all do
create_list(:group, 7)
end
describe '#paginate' do
subject(:paginated_result) { described_class.new(cursor_based_request_context).paginate(relation) }
it 'returns the limited relation' do
expect(paginated_result).to eq(relation.limit(per_page))
end
end
describe '#finalize' do
subject(:finalize) do
service = described_class.new(cursor_based_request_context)
# we need to do this because `finalize` can only be called
# after `paginate` is called. Otherwise the `paginator` object won't be set.
service.paginate(relation)
service.finalize
end
it 'passes information about next page to request' do
cursor_for_next_page = relation.keyset_paginate(**params).cursor_for_next_page
expect_next_instance_of(Gitlab::Pagination::Keyset::HeaderBuilder, cursor_based_request_context) do |builder|
expect(builder).to receive(:add_next_page_header).with({ cursor: cursor_for_next_page })
end
finalize
end
context 'when retrieving the last page' do
let(:relation) { Group.where('id > ?', Group.maximum(:id) - per_page).order(:name, :id) }
it 'does not build information about the next page' do
expect(Gitlab::Pagination::Keyset::HeaderBuilder).not_to receive(:new)
finalize
end
end
context 'when retrieving an empty page' do
let(:relation) { Group.where('id > ?', Group.maximum(:id) + 1).order(:name, :id) }
it 'does not build information about the next page' do
expect(Gitlab::Pagination::Keyset::HeaderBuilder).not_to receive(:new)
finalize
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment