Add HTTP headers configuration for webhook (#13106)
Co-authored-by: yinyijun <yinyijun6@mgtv.com>
This commit is contained in:
parent
97f0f0be67
commit
d838277f4b
|
|
@ -84,6 +84,7 @@
|
|||
* Bump Armeria to 1.32.0 and some transitive dependencies.
|
||||
* Skip persisting metrics/record data that have been expired.
|
||||
* Fix the issue of missing Last Ping data.
|
||||
* Add HTTP headers configuration for the alarm webhook.
|
||||
|
||||
#### UI
|
||||
|
||||
|
|
|
|||
|
|
@ -189,6 +189,25 @@ webhook:
|
|||
urls:
|
||||
- http://ip:port/xxx
|
||||
- http://ip:port/yyy
|
||||
custom1:
|
||||
urls:
|
||||
- http://127.0.0.1/custom1
|
||||
# headers config is provided to add custom configurations or authentications that are required from the server side.
|
||||
headers:
|
||||
Authorization: Bearer bearer_token
|
||||
custom2:
|
||||
urls:
|
||||
- http://127.0.0.1/custom2
|
||||
# headers config is provided to add custom configurations or authentications that are required from the server
|
||||
headers:
|
||||
Authorization: Basic basic_token
|
||||
custom3:
|
||||
urls:
|
||||
- http://127.0.0.1/internal-hook
|
||||
# headers config is provided to add custom configurations or authentications that are required from the server
|
||||
headers:
|
||||
x-company-token: whatever-token-defined-internally-within-the-company
|
||||
x-company-header: arbitrary-additional-http-headers
|
||||
```
|
||||
|
||||
The JSON format is based on `List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>` with the following key information:
|
||||
|
|
|
|||
|
|
@ -157,11 +157,12 @@ public class RulesReader {
|
|||
Map<String, Object> config = (Map<String, Object>) v;
|
||||
WebhookSettings settings = new WebhookSettings(
|
||||
k.toString(), AlarmHooksType.webhook, (Boolean) config.getOrDefault("is-default", false));
|
||||
|
||||
List<String> urls = (List<String>) config.get("urls");
|
||||
if (urls != null) {
|
||||
settings.getUrls().addAll(urls);
|
||||
}
|
||||
Map<String, String> headers = (Map<String, String>) config.getOrDefault("headers", new HashMap<>());
|
||||
settings.setHeaders(headers);
|
||||
rules.getWebhookSettingsMap().put(settings.getFormattedName(), settings);
|
||||
if (settings.isDefault()) {
|
||||
this.defaultHooks.add(settings.getFormattedName());
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class WebhookCallback extends HttpAlarmCallback {
|
|||
}
|
||||
for (final var url : setting.getUrls()) {
|
||||
try {
|
||||
post(URI.create(url), gson.toJson(messages), Map.of());
|
||||
post(URI.create(url), gson.toJson(messages), setting.getHeaders());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to send alarm message to Webhook: {}", url, e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@
|
|||
package org.apache.skywalking.oap.server.core.alarm.provider.webhook;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
|
@ -31,6 +34,7 @@ import org.apache.skywalking.oap.server.core.alarm.provider.AlarmHooksType;
|
|||
@ToString
|
||||
public class WebhookSettings extends AlarmHookSettings {
|
||||
private List<String> urls = new ArrayList<>();
|
||||
private Map<String, String> headers = new HashMap<>();
|
||||
|
||||
public WebhookSettings(final String name,
|
||||
final AlarmHooksType type,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ public class RulesReaderTest {
|
|||
WebhookSettings rulesWebhooks = rules.getWebhookSettingsMap().get(AlarmHooksType.webhook.name() + ".default");
|
||||
Assertions.assertEquals(2, rulesWebhooks.getUrls().size());
|
||||
Assertions.assertEquals("http://127.0.0.1/go-wechat/", rulesWebhooks.getUrls().get(1));
|
||||
WebhookSettings rulesWebhooks2 = rules.getWebhookSettingsMap().get(AlarmHooksType.webhook.name() + ".custom1");
|
||||
Assertions.assertEquals(2, rulesWebhooks2.getHeaders().size());
|
||||
Assertions.assertEquals("Bearer bearer_token", rulesWebhooks2.getHeaders().get("Authorization"));
|
||||
Assertions.assertEquals("arbitrary-additional-http-headers", rulesWebhooks2.getHeaders().get("x-company-header"));
|
||||
|
||||
GRPCAlarmSetting grpcAlarmSetting = rules.getGrpcAlarmSettingMap().get(AlarmHooksType.gRPC.name() + ".default");
|
||||
assertNotNull(grpcAlarmSetting);
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.core.alarm.provider.webhook;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.linecorp.armeria.common.HttpResponse;
|
||||
import com.linecorp.armeria.common.HttpStatus;
|
||||
import com.linecorp.armeria.common.RequestHeaders;
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
|
||||
import org.apache.skywalking.oap.server.core.alarm.provider.AlarmHooksType;
|
||||
import org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher;
|
||||
|
|
@ -33,9 +33,13 @@ import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
|
|||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class WebhookCallbackTest {
|
||||
private static final AtomicBoolean IS_SUCCESS = new AtomicBoolean();
|
||||
|
|
@ -45,19 +49,30 @@ public class WebhookCallbackTest {
|
|||
public static final ServerExtension SERVER = new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) {
|
||||
sb.service("/webhook/receiveAlarm", (ctx, req) -> HttpResponse.from(
|
||||
req.aggregate().thenApply(r -> {
|
||||
final String content = r.content().toStringUtf8();
|
||||
final JsonArray elements = new Gson().fromJson(content, JsonArray.class);
|
||||
if (elements.size() == 1) {
|
||||
COUNTER.getAndIncrement();
|
||||
sb.service("/webhook/receiveAlarm", (ctx, req) -> HttpResponse.from(req.aggregate().thenApply(r -> {
|
||||
final String content = r.content().toStringUtf8();
|
||||
final RequestHeaders headers = r.headers();
|
||||
List<AlarmMessage> alarmMessages = new Gson().fromJson(content, new TypeToken<ArrayList<AlarmMessage>>() {
|
||||
}.getType());
|
||||
if (alarmMessages.size() != 1) {
|
||||
IS_SUCCESS.set(false);
|
||||
return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
if (Objects.equals(alarmMessages.get(0).getId0(), "1")) {
|
||||
IS_SUCCESS.set(true);
|
||||
COUNTER.incrementAndGet();
|
||||
return HttpResponse.of(HttpStatus.OK);
|
||||
} else if (Objects.equals(alarmMessages.get(0).getId0(), "2")) {
|
||||
if (Objects.equals(headers.get("Authorization"), "Bearer bearer_token")
|
||||
&& Objects.equals(headers.get("x-company-header"), "arbitrary-additional-http-headers")) {
|
||||
IS_SUCCESS.set(true);
|
||||
COUNTER.incrementAndGet();
|
||||
return HttpResponse.of(HttpStatus.OK);
|
||||
}
|
||||
|
||||
return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}))
|
||||
);
|
||||
}
|
||||
IS_SUCCESS.set(false);
|
||||
return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
})));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -72,16 +87,19 @@ public class WebhookCallbackTest {
|
|||
setting2.setUrls(remoteEndpoints);
|
||||
rules.getWebhookSettingsMap().put(setting1.getFormattedName(), setting1);
|
||||
rules.getWebhookSettingsMap().put(setting2.getFormattedName(), setting2);
|
||||
setting2.setHeaders(ImmutableMap.of("Authorization", " Bearer bearer_token", "x-company-header", "arbitrary-additional-http-headers"));
|
||||
AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
|
||||
WebhookCallback webhookCallback = new WebhookCallback(alarmRulesWatcher);
|
||||
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
|
||||
AlarmMessage alarmMessage = new AlarmMessage();
|
||||
alarmMessage.setId0("1");
|
||||
alarmMessage.setScopeId(DefaultScopeDefine.SERVICE);
|
||||
alarmMessage.setRuleName("service_resp_time_rule");
|
||||
alarmMessage.setAlarmMessage("alarmMessage with [DefaultScopeDefine.All]");
|
||||
alarmMessage.getHooks().add(setting1.getFormattedName());
|
||||
alarmMessages.add(alarmMessage);
|
||||
AlarmMessage anotherAlarmMessage = new AlarmMessage();
|
||||
anotherAlarmMessage.setId0("2");
|
||||
anotherAlarmMessage.setRuleName("service_resp_time_rule_2");
|
||||
anotherAlarmMessage.setScopeId(DefaultScopeDefine.ENDPOINT);
|
||||
anotherAlarmMessage.setAlarmMessage("anotherAlarmMessage with [DefaultScopeDefine.Endpoint]");
|
||||
|
|
@ -92,4 +110,4 @@ public class WebhookCallbackTest {
|
|||
Assertions.assertTrue(IS_SUCCESS.get());
|
||||
Assertions.assertEquals(2, COUNTER.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +66,12 @@ hooks:
|
|||
urls:
|
||||
- http://127.0.0.1/notify/
|
||||
- http://127.0.0.1/go-wechat/
|
||||
custom1:
|
||||
urls:
|
||||
- http://127.0.0.1/custom1
|
||||
headers:
|
||||
Authorization: Bearer bearer_token
|
||||
x-company-header: arbitrary-additional-http-headers
|
||||
|
||||
gRPC:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -47,6 +47,22 @@ hooks:
|
|||
# urls:
|
||||
# - http://127.0.0.1/notify/
|
||||
# - http://127.0.0.1/go-wechat/
|
||||
# custom1:
|
||||
# urls:
|
||||
# - http://127.0.0.1/custom1
|
||||
# headers:
|
||||
# Authorization: Bearer bearer_token
|
||||
# custom2:
|
||||
# urls:
|
||||
# - http://127.0.0.1/custom2
|
||||
# headers:
|
||||
# Authorization: Basic basic_token
|
||||
# custom3:
|
||||
# urls:
|
||||
# - http://127.0.0.1/internal-hook
|
||||
# headers:
|
||||
# x-company-token: whatever-token-defined-internally-within-the-company
|
||||
# x-company-header: arbitrary-additional-http-headers
|
||||
#
|
||||
# gRPC:
|
||||
# default:
|
||||
|
|
|
|||
Loading…
Reference in New Issue