Completed
Push — master ( 745652...12c1ef )
by Egor
01:12
created

CrashAdmin.sentry_link_field()   B

Complexity

Conditions 6

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 13
rs 8
cc 6
1
# coding: utf8
2
3
"""
4
This software is licensed under the Apache 2 license, quoted below.
5
6
Copyright 2014 Crystalnix Limited
7
8
Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
use this file except in compliance with the License. You may obtain a copy of
10
the License at
11
12
    http://www.apache.org/licenses/LICENSE-2.0
13
14
Unless required by applicable law or agreed to in writing, software
15
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
License for the specific language governing permissions and limitations under
18
the License.
19
"""
20
21
from django.contrib import admin
22
from django.core.exceptions import ObjectDoesNotExist
23
from django.conf import settings
24
from django.utils.html import format_html
25
26
from celery import signature
27
28
from crash.forms import SymbolsAdminForm, CrashFrom
29
from crash.models import Crash, CrashDescription, Symbols
30
from crash.forms import TextInputForm
31
32
SENTRY_DOMAIN = getattr(settings, 'SENTRY_STACKTRACE_DOMAIN', None)
33
SENTRY_ORG_SLUG = getattr(settings, 'SENTRY_STACKTRACE_ORG_SLUG', None)
34
SENTRY_PROJ_SLUG = getattr(settings, 'SENTRY_STACKTRACE_PROJ_SLUG', None)
35
36
37
class BooleanFilter(admin.SimpleListFilter):
38
    title = None
39
    parameter_name = None
40
41
    def lookups(self, request, model_admin):
42
        return (
43
            ('yes', 'Yes'),
44
            ('no', 'No'),
45
        )
46
47
    def queryset(self, request, queryset):
48
        d = {self.parameter_name: ''}
49
        if self.value() == 'yes':
50
            return queryset.exclude(**d)
51
        if self.value() == 'no':
52
            return queryset.filter(**d)
53
54
55
class TextInputFilter(admin.filters.FieldListFilter):
56
    template = 'admin/textinput_filter.html'
57
58
    def __init__(self, field, request, params, model, model_admin, field_path):
59
        self.lookup_kwarg_equal = '%s' % field_path
60
        super(TextInputFilter, self).__init__(
61
            field, request, params, model, model_admin, field_path)
62
        self.form = self.get_form()
63
64
    def choices(self, cl):
65
        return []
66
67
    def expected_parameters(self):
68
        return [self.lookup_kwarg_equal]
69
70
    def get_form(self):
71
        return TextInputForm(data=self.used_parameters,
72
                             field_name=self.field_path)
73
74
    def queryset(self, request, queryset):
75
        if self.form.is_valid():
76
            filter_params = dict(filter(lambda x: bool(x[1]),
77
                                        self.form.cleaned_data.items()))
78
            return queryset.filter(**filter_params)
79
        else:
80
            return queryset
81
82
83
class CrashArchiveFilter(BooleanFilter):
84
    title = 'Instrumental file'
85
    parameter_name = 'archive'
86
87
88
@admin.register(CrashDescription)
89
class CrashDescriptionAdmin(admin.ModelAdmin):
90
    readonly_fields = ('created', 'modified')
91
    list_display = ('created', 'modified', 'summary')
92
    list_display_links = ('created', 'modified', 'summary')
93
94
95
class CrashDescriptionInline(admin.StackedInline):
96
    model = CrashDescription
97
98
99
@admin.register(Crash)
100
class CrashAdmin(admin.ModelAdmin):
101
    list_display = ('id', 'created', 'modified', 'archive_field', 'signature', 'appid', 'userid', 'summary_field', 'os_field', 'cpu_architecture_field',)
102
    list_select_related = ['crash_description']
103
    list_display_links = ('id', 'created', 'modified', 'signature', 'appid', 'userid', 'os_field', 'cpu_architecture_field',)
104
    list_filter = (('id', TextInputFilter,), 'created', CrashArchiveFilter)
105
    search_fields = ('appid', 'userid',)
106
    form = CrashFrom
107
    readonly_fields = ('sentry_link_field',)
108
    exclude = ('groupid', 'eventid', )
109
    actions = ('regenerate_stacktrace',)
110
    inlines = [CrashDescriptionInline]
111
112
    def archive_field(self, obj):
113
        return bool(obj.archive)
114
    archive_field.short_description = 'Instrumental file'
115
116
    def os_field(self, obj):
117
        return obj.stacktrace_json['system_info']['os'] if obj.stacktrace_json else ''
118
    os_field.short_description = 'OS'
119
120
    def cpu_architecture_field(self, obj):
121
        return obj.stacktrace_json['system_info']['cpu_arch'] if obj.stacktrace_json else ''
122
    cpu_architecture_field.short_description = "CPU Architecture"
123
124
    def sentry_link_field(self, obj):
125
        if not SENTRY_DOMAIN or not SENTRY_ORG_SLUG or not SENTRY_PROJ_SLUG:
126
            return "Sentry variables are not set"
127
        if not obj.groupid or not obj.eventid:
128
            return "No sentry link"
129
        link = "http://{}/{}/{}/group/{}/events/{}/".format(
130
            SENTRY_DOMAIN,
131
            SENTRY_ORG_SLUG,
132
            SENTRY_PROJ_SLUG,
133
            obj.groupid,
134
            obj.eventid
135
        )
136
        return format_html("<a href='{link}'>{link}</a>".format(link=link))
137
138
    sentry_link_field.short_description = "Sentry link"
139
    sentry_link_field.allow_tags = True
140
141
    def summary_field(self, obj):
142
        try:
143
            return obj.crash_description.summary
144
        except ObjectDoesNotExist:
145
            return None
146
    summary_field.short_description = 'Summary'
147
148
    def regenerate_stacktrace(self, request, queryset):
149
        for i in queryset:
150
            signature("tasks.processing_crash_dump", args=(i.pk,)).apply_async(queue='default')
151
    regenerate_stacktrace.short_description = 'Regenerate stacktrace'
152
153
154
155
@admin.register(Symbols)
156
class SymbolsAdmin(admin.ModelAdmin):
157
    readonly_fields = ('created', 'modified', )
158
    list_display = ('created', 'modified', 'debug_file', 'debug_id',)
159
    list_display_links = ('created', 'modified', 'debug_file', 'debug_id',)
160
    form = SymbolsAdminForm
161
162