Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 36 additions & 25 deletions internal/api/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,35 +150,46 @@ func (ai *accessInfo) canChangeMetricByName(create bool, old format.MetricMetaVa
(ai.bitEditDefault && !ai.protectedMetric(oldName) && !ai.protectedMetric(newName))
}

func (ai *accessInfo) CanEditMetric(create bool, old format.MetricMetaValue, new_ format.MetricMetaValue) bool {
if ai.canChangeMetricByName(create, old, new_) {
if ai.bitAdmin {
return true
}
if old.Weight != new_.Weight && !(old.Weight == 0 && new_.Weight == 1) {
return false
}
if preKey(old) != preKey(new_) {
return false
func (ai *accessInfo) CanEditMetric(create bool, old format.MetricMetaValue, new_ format.MetricMetaValue) error {
if !ai.canChangeMetricByName(create, old, new_) {
return fmt.Errorf("access forbidden")
}
if ai.bitAdmin {
return nil
}
if old.Weight != new_.Weight && !(old.Weight == 0 && new_.Weight == 1) {
return fmt.Errorf("access control prevents changing weight")
}
if old.PreKeyFrom != new_.PreKeyFrom {
return fmt.Errorf("access control prevents changing 'presort tag'")
}
if old.PreKeyOnly != new_.PreKeyOnly {
return fmt.Errorf("access control prevents changing 'presort tag only'")
}
if skips(old) != skips(new_) {
return fmt.Errorf("access control prevents changing 'max host', 'min host' or 'sum square'")
}
if old.ShardStrategy != new_.ShardStrategy {
return fmt.Errorf("access control prevents changing sharding strategy")
}
if old.ShardNum != new_.ShardNum {
return fmt.Errorf("access control prevents changing sharding strategy shard")
}
for i := 0; i < max(len(old.Tags), len(new_.Tags)); i++ {
// reducing # of tags implicitly clears RawKind
newRaw := false
if i < len(new_.Tags) {
newRaw = new_.Tags[i].RawKind != ""
}
if preKeyOnly(old) != preKeyOnly(new_) {
return false
oldRaw := false
if i < len(old.Tags) {
oldRaw = old.Tags[i].RawKind != ""
}
if skips(old) != skips(new_) {
return false
if newRaw != oldRaw {
return fmt.Errorf("access control prevents modifying Raw Tag attribute")
}

return true
}
return false
}

func preKey(m format.MetricMetaValue) uint32 {
return m.PreKeyFrom
}

func preKeyOnly(m format.MetricMetaValue) bool {
return m.PreKeyOnly
return nil
}

func skips(m format.MetricMetaValue) [3]bool {
Expand Down
12 changes: 6 additions & 6 deletions internal/api/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ func TestAccessInfo(t *testing.T) {
ai := accessInfo{
bitEditPrefix: map[string]bool{"foo_": true},
}
require.False(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "abc"}, format.MetricMetaValue{Name: "foo_bar"}))
require.False(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "foo_bar"}, format.MetricMetaValue{Name: "abc"}))
require.True(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "foo_buzz"}, format.MetricMetaValue{Name: "foo_bar"}))
require.False(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "abc"}, format.MetricMetaValue{Name: "foo_bar"}) == nil)
require.False(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "foo_bar"}, format.MetricMetaValue{Name: "abc"}) == nil)
require.True(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "foo_buzz"}, format.MetricMetaValue{Name: "foo_bar"}) == nil)
ai.bitAdmin = true
require.True(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "abc"}, format.MetricMetaValue{Name: "foo_bar"}))
require.True(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "foo_bar"}, format.MetricMetaValue{Name: "abc"}))
require.True(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "abc"}, format.MetricMetaValue{Name: "foo_bar"}) == nil)
require.True(t, ai.CanEditMetric(false, format.MetricMetaValue{Name: "foo_bar"}, format.MetricMetaValue{Name: "abc"}) == nil)
})
})
}
Expand All @@ -141,5 +141,5 @@ func canViewMetricNamespaced(ai *accessInfo, metric, namespace string) bool {
}

func canBasicEdit(ai *accessInfo, metric string, create bool) bool {
return ai.CanEditMetric(create, format.MetricMetaValue{Name: metric}, format.MetricMetaValue{Name: metric})
return ai.CanEditMetric(create, format.MetricMetaValue{Name: metric}, format.MetricMetaValue{Name: metric}) == nil
}
8 changes: 4 additions & 4 deletions internal/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1811,8 +1811,8 @@ func (h *Handler) handlePostMetric(ctx context.Context, ai accessInfo, _ string,
}
}
if create {
if !ai.CanEditMetric(true, metric, metric) {
return format.MetricMetaValue{}, httpErr(http.StatusForbidden, fmt.Errorf("can't create metric %q", metric.Name))
if err := ai.CanEditMetric(true, metric, metric); err != nil {
return format.MetricMetaValue{}, httpErr(http.StatusForbidden, fmt.Errorf("can't create metric %q: %v", metric.Name, err))
}
if err = h.applyShardsOnCreate(&metric); err != nil {
return format.MetricMetaValue{}, httpErr(http.StatusBadRequest, err)
Expand All @@ -1835,9 +1835,9 @@ func (h *Handler) handlePostMetric(ctx context.Context, ai accessInfo, _ string,
return format.MetricMetaValue{},
httpErr(http.StatusNotFound, fmt.Errorf("metric %q not found (id %d)", metric.Name, metric.MetricID))
}
if !ai.CanEditMetric(false, *old, metric) {
if err := ai.CanEditMetric(false, *old, metric); err != nil {
return format.MetricMetaValue{},
httpErr(http.StatusForbidden, fmt.Errorf("can't edit metric %q", old.Name))
httpErr(http.StatusForbidden, fmt.Errorf("can't edit metric %q: %v", old.Name, err))
}
resp, err = h.metadataLoader.SaveMetric(ctx, metric, ai.toMetadata())
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions statshouse-ui/src/admin/pages/FormPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ export function EditForm(props: { isReadonly: boolean; adminMode: boolean; isHis
</div>
<div className="row mb-3">
<label htmlFor="resolution" className="col-sm-2 col-form-label">
Presort key
Presort tag
</label>
<div className="col-sm-auto d-flex align-items-center">
<select
Expand All @@ -496,7 +496,7 @@ export function EditForm(props: { isReadonly: boolean; adminMode: boolean; isHis
</div>
<div className="row align-items-baseline mb-3">
<label htmlFor="pre_key_only" className="col-sm-2 col-form-label">
Presort key only
Presort tag only
</label>
<div className="col-sm-auto pt-1">
<div className="form-check form-switch">
Expand Down Expand Up @@ -584,7 +584,7 @@ export function EditForm(props: { isReadonly: boolean; adminMode: boolean; isHis
</div>
<div className="row align-items-baseline mb-3">
<label htmlFor="fair_key_tag_ids" className="col-sm-2 col-form-label">
Fair key tags
Fair tags
</label>
<div className="col-sm-auto pt-1">
{
Expand Down
2 changes: 1 addition & 1 deletion website/docs/admin/manage-budgets.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,6 @@ This option is for administrators only.

## Enabling tag-level budgeting

[Enable the "Fair key tags" feature](../guides/edit-metrics.md#fair-key-tags) for a tag to allocate metric resources
[Enable the "Fair tags" feature](../guides/edit-metrics.md#fair-key-tags) for a tag to allocate metric resources
fairly accordingly to the tag values, e.g., different services writing data to the same metric.
Read more about [tag-level budgeting](../overview/concepts.md#tag-level-budgeting-fair-key-tags).
8 changes: 4 additions & 4 deletions website/docs/guides/edit-metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Learn [how to edit a metric](#how-to-edit-a-metric) and what the editing options
* [Map the draft tag names to the tag IDs](#map-the-draft-tag-names-to-the-tag-ids)
* [Disabling a metric](#disabling-a-metric)
* [Admin settings](#admin-settings)
* [Fair key tags](#fair-key-tags)
* [Fair tags](#fair-key-tags)
<!-- TOC -->

## How to edit a metric
Expand Down Expand Up @@ -254,13 +254,13 @@ These settings are for administrators only:

* _Weight_
* _Mapping Flood Counter_
* _Presort key_
* _Presort key only_
* _Presort tag_
* _Presort tag only_
* _Enable max host_
* _Enable min host_
* _Enable sum square_

### Fair key tags
### Fair tags

Choose the tag to [enable the tag-level budgeting](../overview/concepts.md#tag-level-budgeting-fair-key-tags) for it:

Expand Down
10 changes: 5 additions & 5 deletions website/docs/overview/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ To understand StatsHouse deeply, learn the basic metric-related concepts:
* [Fair resource sharing](#fair-resource-sharing)
* [Sampling "mainstays"](#sampling-mainstays)
* [User-guided sampling](#user-guided-sampling)
* [Tag-level budgeting ("Fair key tags")](#tag-level-budgeting-fair-key-tags)
* [Tag-level budgeting ("Fair tags")](#tag-level-budgeting-fair-key-tags)
* [Tag-level budgeting: disabled](#tag-level-budgeting-disabled)
* [Tag-level budgeting: enabled](#tag-level-budgeting-enabled)
<!-- TOC -->
Expand Down Expand Up @@ -412,10 +412,10 @@ In this case, you can explicitly specify `counter` for the `value` metric:
This means that the number of events is 6, and the values are sampled—as if the original `value`
was `[1, 1, 2, 2, 3, 3]`

### Tag-level budgeting ("Fair key tags")
### Tag-level budgeting ("Fair tags")

Tag-level budgeting ("Fair key tags") is for communal metrics that receive data from many services.
The ["Fair key tags" feature](../guides/edit-metrics.md#fair-key-tags) allows you to allocate metric resources
Tag-level budgeting ("Fair tags") is for communal metrics that receive data from many services.
The ["Fair tags" feature](../guides/edit-metrics.md#fair-key-tags) allows you to allocate metric resources
fairly — accordingly to the tag values, e.g., services.

#### Tag-level budgeting: disabled
Expand Down Expand Up @@ -448,7 +448,7 @@ Let's have a sampling factor (SF) = 10. It means that only one row out of 10 rem
You can assign the `service_id` tag to be a "fair key" — to fairly share the metric budget between two services.
:::

See how to [enable the "Fair key tags" feature](../guides/edit-metrics.md#fair-key-tags) for a tag. The metric budget
See how to [enable the "Fair tags" feature](../guides/edit-metrics.md#fair-key-tags) for a tag. The metric budget
will be fairly shared between the services:
* the rare events from the Service B improve their chances to appear on a StatsHouse graph;
* the intensively-generating Service A gets the reduced budget.
2 changes: 1 addition & 1 deletion website/docs/tldr.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Categorize hosts by a _datacenter_, a _cluster_, etc. — not by their names.
specific metrics (as well as groups and namespaces). Use this option sparingly.

:::tip
You can [enable the "Fair key tags" feature](./guides/edit-metrics.md#fair-key-tags) to share the budget fairly
You can [enable the "Fair tags" feature](./guides/edit-metrics.md#fair-key-tags) to share the budget fairly
between the services sending data to the same metric.
Read more about [tag-level budgeting](./overview/concepts.md#tag-level-budgeting-fair-key-tags).
:::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ StatsHouse обеспечивает справедливое распредел

## Настройка бюджетирования на уровне тегов

[Включите опцию "Fair key tags"](../guides/edit-metrics.md#fair-key-tags),
[Включите опцию "Fair tags"](../guides/edit-metrics.md#fair-key-tags),
чтобы поровну поделить бюджет метрики в соответствии со значениями тега, например между сервисами, которые отправляют
данные в одну и ту же метрику.
Узнайте больше о [бюджетировании на уровне тегов](../overview/concepts.md#бюджетирование-на-уровне-тегов-fair-key-tags).
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import FairKey from '../img/fair-key.png'
* [Драфт-теги](#драфт-теги)
* [Отключение метрики](#отключение-метрики)
* [Настройки для администраторов](#настройки-для-администраторов)
* [Fair key tags](#fair-key-tags)
* [Fair tags](#fair-key-tags)
<!-- TOC -->

## Какие параметры метрики можно редактировать
Expand Down Expand Up @@ -258,13 +258,13 @@ StatsHouse извлекает "неизвестные" названия тего

* _Weight_
* _Mapping Flood Counter_
* _Presort key_
* _Presort key only_
* _Presort tag_
* _Presort tag only_
* _Enable max host_
* _Enable min host_
* _Enable sum square_

### Fair key tags
### Fair tags

Чтобы [включить бюджетирование на уровне тега](../overview/concepts.md#бюджетирование-на-уровне-тегов-fair-key-tags),
выберите нужный тег из списка:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import TagLevelSampling from '../img/tag-level-sampling.png'
* [Справедливое распределение ресурсов](#справедливое-распределение-ресурсов)
* [Семплирование "китов"](#семплирование-китов)
* [Пользовательское семплирование](#пользовательское-семплирование)
* [Бюджетирование на уровне тегов ("Fair key tags")](#бюджетирование-на-уровне-тегов-fair-key-tags)
* [Бюджетирование на уровне тегов ("Fair tags")](#бюджетирование-на-уровне-тегов-fair-key-tags)
* [Если НЕ включать бюджетирование на уровне тегов](#если-не-включать-бюджетирование-на-уровне-тегов)
* [Если включить бюджетирование на уровне тегов](#если-включить-бюджетирование-на-уровне-тегов)
<!-- TOC -->
Expand Down Expand Up @@ -410,10 +410,10 @@ _Например:_
Такой вариант отправки означает, что количество событий равно `6`, а значения семплируются так, как если бы `value`
исходно было таким: `[1, 1, 2, 2, 3, 3]`.

### Бюджетирование на уровне тегов ("Fair key tags")
### Бюджетирование на уровне тегов ("Fair tags")

Бюджетирование на уровне тегов ("Fair key tags") предназначено для _коммунальных_ метрик — таких, в которые отправляют
данные сразу несколько сервисов. [Опция "Fair key tags"](../guides/edit-metrics.md#fair-key-tags) позволяет поровну
Бюджетирование на уровне тегов ("Fair tags") предназначено для _коммунальных_ метрик — таких, в которые отправляют
данные сразу несколько сервисов. [Опция "Fair tags"](../guides/edit-metrics.md#fair-key-tags) позволяет поровну
распределять бюджет метрики — в соответствии со значениями тега, например между разными сервисами.

#### Если НЕ включать бюджетирование на уровне тегов
Expand Down Expand Up @@ -446,7 +446,7 @@ _Например:_
Тег `service_id` можно выбрать в качестве "ключа с честным семплированием", чтобы поделить бюджет метрики между сервисами поровну.
:::

Узнайте больше о том, как включить [опцию "Fair key tags"](../guides/edit-metrics.md#fair-key-tags) для конкретного
Узнайте больше о том, как включить [опцию "Fair tags"](../guides/edit-metrics.md#fair-key-tags) для конкретного
тега.
Бюджет метрики распределится между двумя сервисами поровну:
* у редких событий из Service B появится больше шансов попасть на график StatsHouse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ _count_, _sum_, _min_, _max_) за временной интервал.

:::tip
Чтобы поровну распределить бюджет между сервисами, которые отправляют данные в одну и ту же метрику, можно
[включить опцию "Fair key tags"](./guides/edit-metrics.md#fair-key-tags).
[включить опцию "Fair tags"](./guides/edit-metrics.md#fair-key-tags).
Узнайте больше о [бюджетировании на уровне тегов](./overview/concepts.md#бюджетирование-на-уровне-тегов-fair-key-tags).
:::

Expand Down
Loading