Commit 0ec5d3f1 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 874daf71 28a64adf
......@@ -5,7 +5,7 @@
$secondary: $gray-light;
$input-disabled-bg: $gray-light;
$input-border-color: $gray-100;
$input-border-color: $gray-400;
$input-color: $gl-text-color;
$input-font-size: $gl-font-size;
$font-family-sans-serif: $regular-font;
......
......@@ -140,7 +140,7 @@ h1 {
color: #fafafa;
background-color: #333;
background-clip: padding-box;
border: 1px solid #404040;
border: 1px solid #868686;
border-radius: 0.25rem;
}
@media (prefers-reduced-motion: reduce) {
......
......@@ -121,7 +121,7 @@ h1 {
color: #303030;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #dbdbdb;
border: 1px solid #868686;
border-radius: 0.25rem;
}
@media (prefers-reduced-motion: reduce) {
......
......@@ -189,7 +189,7 @@ hr {
color: #303030;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #dbdbdb;
border: 1px solid #868686;
border-radius: 0.25rem;
}
@media (prefers-reduced-motion: reduce) {
......
......@@ -118,3 +118,4 @@
= render 'admin/application_settings/snowplow'
= render 'admin/application_settings/eks'
= render 'admin/application_settings/floc'
= render_if_exists 'admin/application_settings/license_file'
......@@ -36,7 +36,9 @@ Rails.application.configure do
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# Include generic and useful information about system operation, but avoid logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII).
# Note: This configuration does not affect the log level of `Gitlab::Logger` and its subclasses.
config.log_level = :info
# Suppress 'Rendered template ...' messages in the log
......
......@@ -20,6 +20,54 @@ including adjusting log retention, log forwarding,
switching logs from JSON to plain text logging, and more.
- [How to parse and analyze JSON logs](troubleshooting/log_parsing.md).
## Log Levels
Each log message has an assigned log level that indicates its importance and verbosity.
Each logger has an assigned minimum log level.
A logger emits a log message only if its log level is equal to or above the minimum log level.
The following log levels are supported:
| Level | Name |
|-------|---------|
| 0 | DEBUG |
| 1 | INFO |
| 2 | WARN |
| 3 | ERROR |
| 4 | FATAL |
| 5 | UNKNOWN |
GitLab loggers emit all log messages because they are set to `DEBUG` by default.
### Override default log level
You can override the minimum log level for GitLab loggers using the `GITLAB_LOG_LEVEL` environment variable.
Valid values are either a value of `0` to `5`, or the name of the log level.
Example:
```shell
GITLAB_LOG_LEVEL=info
```
For some services, other log levels are in place that are not affected by this setting.
Some of these services have their own environment variables to override the log level. For example:
| Service | Log Level | Environment variable |
|----------------------|-----------|----------------------|
| GitLab API | `INFO` | |
| GitLab Cleanup | `INFO` | `DEBUG` |
| GitLab Doctor | `INFO` | `VERBOSE` |
| GitLab Export | `INFO` | `EXPORT_DEBUG` |
| GitLab Geo | `INFO` | |
| GitLab Import | `INFO` | `IMPORT_DEBUG` |
| GitLab QA Runtime | `ERROR` | `QA_DEBUG` |
| Google APIs | `INFO` | |
| Rack Timeout | `ERROR` | |
| Sidekiq (server) | `INFO` | |
| Snowplow Tracker | `FATAL` | |
| gRPC Client (Gitaly) | `WARN` | `GRPC_LOG_LEVEL` |
## Log Rotation
The logs for a given service may be managed and rotated by:
......
......@@ -50,13 +50,14 @@ If you receive a license file from GitLab (for example a new trial), you can upl
The first time you visit your GitLab EE installation signed in as an administrator,
you should see a note urging you to upload a license with a link that takes you
to the **Subscription** area.
to the **Upload license** page.
Otherwise, to manually go to the **Subscription** area:
Otherwise, to manually go to the **Upload license** page:
1. Sign in to your GitLab self-managed instance.
1. From the top menu, select the Admin Area **{admin}**.
1. From the left sidebar, select **Subscription**, and select **Upload a license file**.
1. On the left sidebar, select **Settings**.
1. In the **License file** section, select **Upload a license**.
- *If you've received a `.gitlab-license` file:*
1. Download the license file to your local machine.
......
......@@ -6,36 +6,33 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Repository Analytics **(FREE)**
Get high-level overview of the project's Git repository.
Use Repository Analytics to view information about a project's Git repository:
![Repository Analytics](img/repository_analytics_v13_0.png)
## Availability
- Programming languages used in the repository.
- Code coverage history from last 3 months ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33743) in GitLab 13.1).
- Commit statistics (last month).
- Commits per day of month.
- Commits per weekday.
- Commits per day hour (UTC).
Repository Analytics is part of [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss). It's available to anyone who has permission to clone the repository.
The feature requires:
Repository Analytics requires:
- An initialized Git repository.
- At least one commit in the default branch (`master` by default).
## Overview
You can find Repository Analytics in the project's sidebar. To access the page, go to **{chart}** **Analytics > Repository**.
NOTE:
Without a Git commit in the default branch, the menu item won't be visible.
Commits in a project's [wiki](../project/wiki/index.md#track-wiki-events) are not included in the analysis.
### Charts
## View Repository Analytics
To review Repository Analytics for a project:
The data in the charts are queued. Background workers update the charts 10 minutes after each commit in the default branch. Depending on the size of the GitLab installation, it may take longer for data to refresh due to variations in the size of background job queues.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Repository**.
Available charts:
## How Repository Analytics chart data is updated
- Programming languages used in the repository
- Code coverage history (last 3 months) ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33743) in GitLab 13.1)
- Commit statistics (last month)
- Commits per day of month
- Commits per weekday
- Commits per day hour (UTC)
Data in the charts are queued. Background workers update the charts 10 minutes after each commit in the default branch. Depending on the size of the GitLab installation, it may take longer for data to refresh due to variations in the size of background job queues.
......@@ -4,7 +4,6 @@ import { helpPagePath } from '~/helpers/help_page_helper';
import {
activateSubscription,
howToActivateSubscription,
uploadLicenseFile,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from '../constants';
......@@ -20,7 +19,6 @@ export default {
i18n: {
activateSubscription,
howToActivateSubscription,
uploadLicenseFile,
},
components: {
GlCard,
......@@ -29,7 +27,6 @@ export default {
SubscriptionActivationErrors,
SubscriptionActivationForm,
},
inject: ['licenseUploadPath'],
links: {
activateSubscriptionUrl,
},
......@@ -79,14 +76,5 @@ export default {
</gl-sprintf>
</p>
<subscription-activation-form class="gl-p-5" v-on="$options.activationListeners" />
<template #footer>
<gl-link
v-if="licenseUploadPath"
data-testid="upload-license-link"
data-qa-selector="license_upload_link"
:href="licenseUploadPath"
>{{ $options.i18n.uploadLicenseFile }}
</gl-link>
</template>
</gl-card>
</template>
......@@ -12,7 +12,6 @@ import {
subscriptionDetailsHeaderText,
subscriptionTypes,
syncSubscriptionButtonText,
uploadLicense,
} from '../constants';
import SubscriptionActivationBanner from './subscription_activation_banner.vue';
import SubscriptionActivationModal from './subscription_activation_modal.vue';
......@@ -33,7 +32,6 @@ export default {
removeLicenseConfirm,
subscriptionDetailsHeaderText,
syncSubscriptionButtonText,
uploadLicense,
},
modal: {
id: modalId,
......@@ -55,7 +53,6 @@ export default {
inject: [
'customersPortalUrl',
'licenseRemovePath',
'licenseUploadPath',
'subscriptionSyncPath',
'subscriptionActivationBannerCalloutName',
],
......@@ -89,9 +86,6 @@ export default {
canSyncSubscription() {
return this.subscriptionSyncPath && this.isCloudType;
},
canUploadLicense() {
return this.licenseUploadPath && this.isLicenseFileType;
},
canRemoveLicense() {
return this.licenseRemovePath;
},
......@@ -112,8 +106,7 @@ export default {
this.canActivateSubscription ||
this.canRemoveLicense ||
this.canManageSubscription ||
this.canSyncSubscription ||
this.canUploadLicense
this.canSyncSubscription
);
},
subscriptionHistory() {
......@@ -207,16 +200,6 @@ export default {
>
{{ $options.i18n.activateCloudLicense }}
</gl-button>
<gl-button
v-if="canUploadLicense"
:href="licenseUploadPath"
category="secondary"
variant="confirm"
data-testid="license-upload-action"
data-qa-selector="license_upload_link"
>
{{ $options.i18n.uploadLicense }}
</gl-button>
<gl-button
v-if="canManageSubscription"
:href="customersPortalUrl"
......
......@@ -25,7 +25,6 @@ export default () => {
freeTrialPath,
hasActiveLicense,
licenseRemovePath,
licenseUploadPath,
subscriptionActivationBannerCalloutName,
subscriptionSyncPath,
licenseUsageFilePath,
......@@ -44,7 +43,6 @@ export default () => {
customersPortalUrl,
freeTrialPath,
licenseRemovePath,
licenseUploadPath,
subscriptionActivationBannerCalloutName,
subscriptionSyncPath,
},
......
......@@ -140,7 +140,7 @@ h1 {
color: #fafafa;
background-color: #333;
background-clip: padding-box;
border: 1px solid #404040;
border: 1px solid #868686;
border-radius: 0.25rem;
}
@media (prefers-reduced-motion: reduce) {
......
......@@ -121,7 +121,7 @@ h1 {
color: #303030;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #dbdbdb;
border: 1px solid #868686;
border-radius: 0.25rem;
}
@media (prefers-reduced-motion: reduce) {
......
......@@ -189,7 +189,7 @@ hr {
color: #303030;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #dbdbdb;
border: 1px solid #868686;
border-radius: 0.25rem;
}
@media (prefers-reduced-motion: reduce) {
......
......@@ -14,6 +14,8 @@ class Groups::AuditEventsController < Groups::ApplicationController
feature_category :audit_events
urgency :low
def index
@is_last_page = events.last_page?
@events = AuditEventSerializer.new.represent(events)
......
......@@ -13,6 +13,8 @@ class Projects::AuditEventsController < Projects::ApplicationController
feature_category :audit_events
urgency :low
def index
@is_last_page = events.last_page?
@events = AuditEventSerializer.new.represent(events)
......
......@@ -60,7 +60,6 @@ module LicenseHelper
customers_portal_url: ::EE::SUBSCRIPTIONS_MANAGE_URL,
free_trial_path: new_trial_url,
has_active_license: (has_active_license? ? 'true' : 'false'),
license_upload_path: new_admin_license_path,
license_remove_path: admin_license_path,
subscription_sync_path: sync_seat_link_admin_license_path,
congratulation_svg_path: image_path('illustrations/illustration-congratulation-purchase.svg'),
......
%section.settings.expanded
.settings-header
%h4
= _('License file')
.settings-content
- link_start = '<a href="%{url}" data-qa-selector="license_upload_link">'.html_safe % { url: new_admin_license_path }
%p
= s_('%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
......@@ -4,6 +4,8 @@ module API
class AuditEvents < ::API::Base
include ::API::PaginationParams
urgency :low
feature_category :audit_events
before do
......
......@@ -407,6 +407,12 @@ RSpec.describe 'Admin updates EE-only settings' do
end
end
end
context 'License file link' do
it 'provides a link to upload License file' do
expect(page).to have_link(text: 'Upload a license', href: new_admin_license_path)
end
end
end
def current_settings
......
......@@ -216,9 +216,9 @@ RSpec.describe 'Admin views Subscription', :js do
end
context 'when uploading a license file' do
it 'shows a link to upload a license file' do
it 'does not show a link to upload a license file' do
page.within(find('#content-body', match: :first)) do
expect(page).to have_link('Upload a license file', href: new_admin_license_path)
expect(page).not_to have_link('Upload a license file', href: new_admin_license_path)
end
end
end
......
import { GlCard, GlSprintf } from '@gitlab/ui';
import { GlCard } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import SubscriptionActivationCard, {
activateSubscriptionUrl,
} from 'ee/admin/subscriptions/show/components/subscription_activation_card.vue';
import SubscriptionActivationCard from 'ee/admin/subscriptions/show/components/subscription_activation_card.vue';
import SubscriptionActivationErrors from 'ee/admin/subscriptions/show/components/subscription_activation_errors.vue';
import SubscriptionActivationForm from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue';
import {
CONNECTIVITY_ERROR,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
uploadLicenseFile,
} from 'ee/admin/subscriptions/show/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license } from '../mock_data';
......@@ -17,11 +14,9 @@ import { license } from '../mock_data';
describe('CloudLicenseApp', () => {
let wrapper;
const licenseUploadPath = 'license/upload';
const findSubscriptionActivationForm = () => wrapper.findComponent(SubscriptionActivationForm);
const findSubscriptionActivationErrors = () =>
wrapper.findComponent(SubscriptionActivationErrors);
const findActivateSubscriptionLink = () => wrapper.findByTestId('activate-subscription-link');
const findUploadLink = () => wrapper.findByTestId('upload-license-link');
const createComponent = ({ props = {}, stubs = {}, provide = {} } = {}) => {
......@@ -30,10 +25,7 @@ describe('CloudLicenseApp', () => {
propsData: {
...props,
},
provide: {
licenseUploadPath,
...provide,
},
provide,
stubs,
}),
);
......@@ -55,30 +47,13 @@ describe('CloudLicenseApp', () => {
expect(findSubscriptionActivationErrors().exists()).toBe(false);
});
describe('with an upload legacy license link', () => {
beforeEach(() => {
createComponent({ stubs: { GlCard, GlSprintf } });
});
it('shows a link when provided', () => {
expect(findUploadLink().text()).toBe(uploadLicenseFile);
});
it('shows an help link', () => {
expect(findActivateSubscriptionLink().attributes('href')).toBe(activateSubscriptionUrl);
});
it('provides the correct path', () => {
expect(findUploadLink().attributes('href')).toBe(licenseUploadPath);
});
it('does not show upload legacy license link', () => {
expect(findUploadLink().exists()).toBe(false);
});
it('does not show a link when legacy license link is not provided', () => {
createComponent({
stubs: { GlCard },
provide: {
licenseUploadPath: '',
},
});
expect(findUploadLink().exists()).toBe(false);
......
......@@ -40,7 +40,6 @@ describe('Subscription Breakdown', () => {
const connectivityHelpURL = 'connectivity/help/url';
const customersPortalUrl = 'customers.dot';
const licenseRemovePath = '/license/remove/';
const licenseUploadPath = '/license/upload/';
const subscriptionActivationBannerCalloutName = 'banner_callout_name';
const subscriptionSyncPath = '/sync/path/';
......@@ -82,7 +81,6 @@ describe('Subscription Breakdown', () => {
congratulationSvgPath,
connectivityHelpURL,
customersPortalUrl,
licenseUploadPath,
licenseRemovePath,
subscriptionActivationBannerCalloutName,
subscriptionSyncPath,
......@@ -195,7 +193,6 @@ describe('Subscription Breakdown', () => {
const provide = {
connectivityHelpURL: '',
customersPortalUrl: '',
licenseUploadPath: '',
licenseRemovePath: '',
subscriptionSyncPath: url,
};
......@@ -207,31 +204,11 @@ describe('Subscription Breakdown', () => {
},
);
it.each`
url | type | shouldShow
${licenseUploadPath} | ${subscriptionTypes.LICENSE_FILE} | ${true}
${licenseUploadPath} | ${subscriptionTypes.CLOUD} | ${false}
${''} | ${subscriptionTypes.LICENSE_FILE} | ${false}
${''} | ${subscriptionTypes.CLOUD} | ${false}
${undefined} | ${subscriptionTypes.LICENSE_FILE} | ${false}
${undefined} | ${subscriptionTypes.CLOUD} | ${false}
`(
'with url is $url and type is $type the upload button is shown: $shouldShow',
({ url, type, shouldShow }) => {
const provide = {
connectivityHelpURL: '',
customersPortalUrl: '',
licenseRemovePath: '',
subscriptionSyncPath: '',
licenseUploadPath: url,
};
const props = { subscription: { ...license.ULTIMATE, type } };
const stubs = { GlCard, SubscriptionDetailsCard };
createComponent({ props, provide, stubs });
it('does not show upload legacy license button', () => {
createComponent();
expect(findLicenseUploadAction().exists()).toBe(shouldShow);
},
);
expect(findLicenseUploadAction().exists()).toBe(false);
});
it.each`
url | shouldShow
......@@ -241,7 +218,6 @@ describe('Subscription Breakdown', () => {
`('with url is $url the manage button is shown: $shouldShow', ({ url, shouldShow }) => {
const provide = {
connectivityHelpURL: '',
licenseUploadPath: '',
licenseRemovePath: '',
subscriptionSyncPath: '',
customersPortalUrl: url,
......@@ -266,7 +242,6 @@ describe('Subscription Breakdown', () => {
const provide = {
connectivityHelpURL: '',
customersPortalUrl: '',
licenseUploadPath: '',
subscriptionSyncPath: '',
licenseRemovePath: url,
};
......
......@@ -98,7 +98,6 @@ RSpec.describe LicenseHelper do
free_trial_path: 'new_trial_url',
buy_subscription_path: 'subscriptions_plans_url',
subscription_sync_path: sync_seat_link_admin_license_path,
license_upload_path: new_admin_license_path,
license_remove_path: admin_license_path,
congratulation_svg_path: helper.image_path('illustrations/illustration-congratulation-purchase.svg'),
subscription_activation_banner_callout_name: ::EE::Users::CalloutsHelper::CL_SUBSCRIPTION_ACTIVATION,
......@@ -115,7 +114,6 @@ RSpec.describe LicenseHelper do
free_trial_path: 'new_trial_url',
buy_subscription_path: 'subscriptions_plans_url',
subscription_sync_path: sync_seat_link_admin_license_path,
license_upload_path: new_admin_license_path,
license_remove_path: admin_license_path,
congratulation_svg_path: helper.image_path('illustrations/illustration-congratulation-purchase.svg'),
subscription_activation_banner_callout_name: ::EE::Users::CalloutsHelper::CL_SUBSCRIPTION_ACTIVATION,
......
......@@ -33,7 +33,11 @@ module Gitlab
def self.build
Gitlab::SafeRequestStore[self.cache_key] ||=
new(self.full_log_path, level: ::Logger::DEBUG)
new(self.full_log_path, level: log_level)
end
def self.log_level(fallback: ::Logger::DEBUG)
ENV.fetch('GITLAB_LOG_LEVEL', fallback)
end
def self.full_log_path
......
......@@ -731,6 +731,9 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}Upload a license%{link_end} file or enter the license key you have received from GitLab Inc."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
......
......@@ -5,7 +5,7 @@ module QA
module Page
module Admin
class License < QA::Page::Base
view 'ee/app/assets/javascripts/admin/subscriptions/show/components/subscription_activation_card.vue' do
view 'ee/app/views/admin/application_settings/_license_file.html.haml' do
element :license_upload_link
end
......
......@@ -10,7 +10,11 @@ module QA
QA::Page::Admin::Menu.perform(&:click_subscription_menu_link)
EE::Page::Admin::License.perform do |license_page|
license_page.add_new_license(license) unless license_page.license?
unless license_page.license?
QA::Page::Admin::Menu.perform(&:go_to_general_settings)
license_page.add_new_license(license)
end
end
QA::Page::Main::Menu.perform(&:sign_out_if_signed_in)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Logger do
describe '.build' do
before do
allow(described_class).to receive(:file_name_noext).and_return('log')
end
subject { described_class.build }
it 'builds logger using Gitlab::Logger.log_level' do
expect(described_class).to receive(:log_level).and_return(:warn)
expect(subject.level).to eq(described_class::WARN)
end
it 'raises ArgumentError if invalid log level' do
allow(described_class).to receive(:log_level).and_return(:invalid)
expect { subject.level }.to raise_error(ArgumentError, 'invalid log level: invalid')
end
using RSpec::Parameterized::TableSyntax
where(:env_value, :resulting_level) do
0 | described_class::DEBUG
:debug | described_class::DEBUG
'debug' | described_class::DEBUG
'DEBUG' | described_class::DEBUG
'DeBuG' | described_class::DEBUG
1 | described_class::INFO
:info | described_class::INFO
'info' | described_class::INFO
'INFO' | described_class::INFO
'InFo' | described_class::INFO
2 | described_class::WARN
:warn | described_class::WARN
'warn' | described_class::WARN
'WARN' | described_class::WARN
'WaRn' | described_class::WARN
3 | described_class::ERROR
:error | described_class::ERROR
'error' | described_class::ERROR
'ERROR' | described_class::ERROR
'ErRoR' | described_class::ERROR
4 | described_class::FATAL
:fatal | described_class::FATAL
'fatal' | described_class::FATAL
'FATAL' | described_class::FATAL
'FaTaL' | described_class::FATAL
5 | described_class::UNKNOWN
:unknown | described_class::UNKNOWN
'unknown' | described_class::UNKNOWN
'UNKNOWN' | described_class::UNKNOWN
'UnKnOwN' | described_class::UNKNOWN
end
with_them do
it 'builds logger if valid log level' do
stub_env('GITLAB_LOG_LEVEL', env_value)
expect(subject.level).to eq(resulting_level)
end
end
end
describe '.log_level' do
context 'if GITLAB_LOG_LEVEL is set' do
before do
stub_env('GITLAB_LOG_LEVEL', described_class::ERROR)
end
it 'returns value of GITLAB_LOG_LEVEL' do
expect(described_class.log_level).to eq(described_class::ERROR)
end
it 'ignores fallback' do
expect(described_class.log_level(fallback: described_class::FATAL)).to eq(described_class::ERROR)
end
end
context 'if GITLAB_LOG_LEVEL is not set' do
it 'returns default fallback DEBUG' do
expect(described_class.log_level).to eq(described_class::DEBUG)
end
it 'returns passed fallback' do
expect(described_class.log_level(fallback: described_class::FATAL)).to eq(described_class::FATAL)
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