Commit d2145063 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch 'dz-error-tracking-backend-models' into 'master'

Add Error tracking models

See merge request gitlab-org/gitlab!64712
parents f1c2d885 2d1c197a
# frozen_string_literal: true
module ErrorTracking
def self.table_name_prefix
'error_tracking_'
end
end
# frozen_string_literal: true
class ErrorTracking::Error < ApplicationRecord
belongs_to :project
has_many :events, class_name: 'ErrorTracking::ErrorEvent'
validates :project, presence: true
validates :name, presence: true
validates :description, presence: true
validates :actor, presence: true
end
# frozen_string_literal: true
class ErrorTracking::ErrorEvent < ApplicationRecord
belongs_to :error
validates :payload, json_schema: { filename: 'error_tracking_event_payload' }
validates :error, presence: true
validates :description, presence: true
validates :occurred_at, presence: true
end
......@@ -24,6 +24,8 @@ module ErrorTracking
self.reactive_cache_key = ->(setting) { [setting.class.model_name.singular, setting.project_id] }
self.reactive_cache_work_type = :external_dependency
self.table_name = 'project_error_tracking_settings'
belongs_to :project
validates :api_url, length: { maximum: 255 }, public_url: { enforce_sanitization: true, ascii_only: true }, allow_nil: true
......
{
"description": "Error tracking event payload",
"type": "object",
"required": [],
"properties": {
"event_id": {
"type": "string"
},
"level": {
"type": "string"
},
"timestamp": {
"type": "string"
},
"release": {
"type": "string"
},
"environment": {
"type": "string"
},
"server_name": {
"type": "string"
},
"message": {
"type": "string"
},
"user": {
"type": "object",
"required": [],
"properties": {}
},
"tags": {
"type": "object",
"required": [],
"properties": {
"request_id": {
"type": "string"
}
}
},
"contexts": {
"type": "object",
"required": [],
"properties": {
"os": {
"type": "object",
"required": [],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"build": {
"type": "string"
},
"kernel_version": {
"type": "string"
}
}
},
"runtime": {
"type": "object",
"required": [],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"trace": {
"type": "object",
"required": [],
"properties": {
"trace_id": {
"type": "string"
},
"span_id": {
"type": "string"
},
"parent_span_id": {
"type": "string"
},
"description": {
"type": "string"
},
"op": {
"type": "string"
},
"status": {
"type": "string"
}
}
}
}
},
"fingerprint": {
"type": "array",
"items": {
"type": "string"
}
},
"breadcrumbs": {
"type": "object",
"required": [],
"properties": {
"values": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"category": {
"type": "string"
},
"data": {
"type": "object",
"required": [],
"properties": {
"controller": {
"type": "string"
},
"action": {
"type": "string"
},
"params": {
"type": "object",
"required": [],
"properties": {
"controller": {
"type": "string"
},
"action": {
"type": "string"
}
}
},
"format": {
"type": "string"
},
"method": {
"type": "string"
},
"path": {
"type": "string"
},
"start_timestamp": {
"type": "number"
}
}
},
"level": {
"type": "string"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "number"
},
"type": {
"type": "string"
}
}
}
}
}
},
"transaction": {
"type": "string"
},
"platform": {
"type": "string"
},
"sdk": {
"type": "object",
"required": [],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"request": {
"type": "object",
"required": [],
"properties": {
"url": {
"type": "string"
},
"method": {
"type": "string"
},
"headers": {
"type": "object",
"required": [],
"properties": {
"Host": {
"type": "string"
},
"User-Agent": {
"type": "string"
},
"Accept": {
"type": "string"
},
"Accept-Language": {
"type": "string"
},
"Accept-Encoding": {
"type": "string"
},
"Referer": {
"type": "string"
},
"Turbolinks-Referrer": {
"type": "string"
},
"Connection": {
"type": "string"
},
"X-Request-Id": {
"type": "string"
}
}
},
"env": {
"type": "object",
"required": [],
"properties": {
"SERVER_NAME": {
"type": "string"
},
"SERVER_PORT": {
"type": "string"
}
}
}
}
},
"exception": {
"type": "object",
"required": [],
"properties": {
"values": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"type": {
"type": "string"
},
"value": {
"type": "string"
},
"module": {
"type": "string"
},
"thread_id": {
"type": "number"
},
"stacktrace": {
"type": "object",
"required": [],
"properties": {
"frames": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"project_root": {
"type": "string"
},
"abs_path": {
"type": "string"
},
"function": {
"type": "string"
},
"lineno": {
"type": "number"
},
"in_app": {
"type": "string"
},
"filename": {
"type": "string"
},
"pre_context": {
"type": "array",
"items": {
"type": "string"
}
},
"context_line": {
"type": "string"
},
"post_context": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
# frozen_string_literal: true
class CreateErrorTrackingErrors < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
def up
create_table_with_constraints :error_tracking_errors do |t|
t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }
t.text :name, null: false
t.text :description, null: false
t.text :actor, null: false
t.datetime_with_timezone :first_seen_at, null: false, default: -> { 'NOW()' }
t.datetime_with_timezone :last_seen_at, null: false, default: -> { 'NOW()' }
t.text :platform
t.text_limit :name, 255
t.text_limit :description, 1024
t.text_limit :actor, 255
t.text_limit :platform, 255
t.timestamps_with_timezone
end
end
def down
drop_table :error_tracking_errors
end
end
# frozen_string_literal: true
class CreateErrorTrackingErrorEvents < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
def up
create_table_with_constraints :error_tracking_error_events do |t|
t.references :error,
index: true,
null: false,
foreign_key: { on_delete: :cascade, to_table: :error_tracking_errors }
t.text :description, null: false
t.text :environment
t.text :level
t.datetime_with_timezone :occurred_at, null: false
t.jsonb :payload, null: false, default: {}
t.text_limit :description, 255
t.text_limit :environment, 255
t.text_limit :level, 255
t.timestamps_with_timezone
end
end
def down
drop_table :error_tracking_error_events
end
end
1a930fec524c91c5d382c40514d0d1943e59514f5dbd8588595363c24819b8d0
\ No newline at end of file
df9e976b0f294284ad9e9b617da42310c83cb1acc6db6ea00ea93c49c2310a1c
\ No newline at end of file
......@@ -12732,6 +12732,56 @@ CREATE SEQUENCE epics_id_seq
ALTER SEQUENCE epics_id_seq OWNED BY epics.id;
CREATE TABLE error_tracking_error_events (
id bigint NOT NULL,
error_id bigint NOT NULL,
description text NOT NULL,
environment text,
level text,
occurred_at timestamp with time zone NOT NULL,
payload jsonb DEFAULT '{}'::jsonb NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
CONSTRAINT check_92ecc3077b CHECK ((char_length(description) <= 255)),
CONSTRAINT check_c67d5b8007 CHECK ((char_length(level) <= 255)),
CONSTRAINT check_f4b52474ad CHECK ((char_length(environment) <= 255))
);
CREATE SEQUENCE error_tracking_error_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE error_tracking_error_events_id_seq OWNED BY error_tracking_error_events.id;
CREATE TABLE error_tracking_errors (
id bigint NOT NULL,
project_id bigint NOT NULL,
name text NOT NULL,
description text NOT NULL,
actor text NOT NULL,
first_seen_at timestamp with time zone DEFAULT now() NOT NULL,
last_seen_at timestamp with time zone DEFAULT now() NOT NULL,
platform text,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
CONSTRAINT check_18a758e537 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_b5cb4d3888 CHECK ((char_length(actor) <= 255)),
CONSTRAINT check_c739788b12 CHECK ((char_length(description) <= 1024)),
CONSTRAINT check_fe99886883 CHECK ((char_length(platform) <= 255))
);
CREATE SEQUENCE error_tracking_errors_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE error_tracking_errors_id_seq OWNED BY error_tracking_errors.id;
CREATE TABLE events (
id integer NOT NULL,
project_id integer,
......@@ -19887,6 +19937,10 @@ ALTER TABLE ONLY epic_user_mentions ALTER COLUMN id SET DEFAULT nextval('epic_us
ALTER TABLE ONLY epics ALTER COLUMN id SET DEFAULT nextval('epics_id_seq'::regclass);
ALTER TABLE ONLY error_tracking_error_events ALTER COLUMN id SET DEFAULT nextval('error_tracking_error_events_id_seq'::regclass);
ALTER TABLE ONLY error_tracking_errors ALTER COLUMN id SET DEFAULT nextval('error_tracking_errors_id_seq'::regclass);
ALTER TABLE ONLY events ALTER COLUMN id SET DEFAULT nextval('events_id_seq'::regclass);
ALTER TABLE ONLY evidences ALTER COLUMN id SET DEFAULT nextval('evidences_id_seq'::regclass);
......@@ -21197,6 +21251,12 @@ ALTER TABLE ONLY epic_user_mentions
ALTER TABLE ONLY epics
ADD CONSTRAINT epics_pkey PRIMARY KEY (id);
ALTER TABLE ONLY error_tracking_error_events
ADD CONSTRAINT error_tracking_error_events_pkey PRIMARY KEY (id);
ALTER TABLE ONLY error_tracking_errors
ADD CONSTRAINT error_tracking_errors_pkey PRIMARY KEY (id);
ALTER TABLE ONLY events
ADD CONSTRAINT events_pkey PRIMARY KEY (id);
......@@ -23343,6 +23403,10 @@ CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON epics USING btree (st
CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btree (start_date_sourcing_milestone_id);
CREATE INDEX index_error_tracking_error_events_on_error_id ON error_tracking_error_events USING btree (error_id);
CREATE INDEX index_error_tracking_errors_on_project_id ON error_tracking_errors USING btree (project_id);
CREATE INDEX index_esc_protected_branches_on_external_status_check_id ON external_status_checks_protected_branches USING btree (external_status_check_id);
CREATE INDEX index_esc_protected_branches_on_protected_branch_id ON external_status_checks_protected_branches USING btree (protected_branch_id);
......@@ -26560,6 +26624,9 @@ ALTER TABLE ONLY packages_debian_group_component_files
ALTER TABLE ONLY boards_epic_board_labels
ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
ALTER TABLE ONLY error_tracking_error_events
ADD CONSTRAINT fk_rails_2c096c0076 FOREIGN KEY (error_id) REFERENCES error_tracking_errors(id) ON DELETE CASCADE;
ALTER TABLE ONLY onboarding_progresses
ADD CONSTRAINT fk_rails_2ccfd420cc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
......@@ -26968,6 +27035,9 @@ ALTER TABLE ONLY plan_limits
ALTER TABLE ONLY operations_feature_flags_issues
ADD CONSTRAINT fk_rails_6a8856ca4f FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
ALTER TABLE ONLY error_tracking_errors
ADD CONSTRAINT fk_rails_6b41f837ba FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY prometheus_alerts
ADD CONSTRAINT fk_rails_6d9b283465 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ErrorTracking::ErrorEvent, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:error) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:description) }
it { is_expected.to validate_presence_of(:occurred_at) }
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ErrorTracking::Error, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:events) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_presence_of(:description) }
it { is_expected.to validate_presence_of(:actor) }
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