This is an automated email from the ASF dual-hosted git repository.
kezhenxu94 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new de6a731 Save Envoy http access logs when error occurs (#6322)
de6a731 is described below
commit de6a731d72fb87dd574da1d9b42495fdd29b4311
Author: Zhenxu Ke <[email protected]>
AuthorDate: Tue Mar 2 22:40:30 2021 +0800
Save Envoy http access logs when error occurs (#6322)
---
CHANGES.md | 1 +
docs/en/setup/backend/configuration-vocabulary.md | 4 +
docs/en/setup/envoy/als_setting.md | 24 ++++-
.../analyzer/dsl/spec/extractor/ExtractorSpec.java | 14 ++-
.../log/analyzer/dsl/spec/sink/SamplerSpec.java | 25 +----
.../dsl/spec/sink/sampler/RateLimitingSampler.java | 6 +-
.../src/main/resources/lal/envoy-als.yaml | 47 +++++++++
.../oap/server/library/util/ProtoBufJsonUtils.java | 11 +-
.../envoy-metrics-receiver-plugin/pom.xml | 5 +
.../envoy/AccessLogServiceGRPCHandler.java | 11 +-
.../receiver/envoy/EnvoyMetricReceiverConfig.java | 6 ++
.../envoy/EnvoyMetricReceiverProvider.java | 2 +-
.../receiver/envoy/MetricServiceGRPCHandler.java | 7 +-
.../receiver/envoy/ServiceMetaInfoFactory.java | 42 ++++++++
.../receiver/envoy/ServiceMetaInfoFactoryImpl.java | 40 +++++++
.../server/receiver/envoy/als/ALSHTTPAnalysis.java | 18 +++-
.../receiver/envoy/als/AbstractALSAnalyzer.java | 4 +-
.../envoy/als/LogEntry2MetricsAdapter.java | 7 +-
.../als/k8s/K8sALSServiceMeshHTTPAnalysis.java | 11 +-
.../server/receiver/envoy/als/mx/FieldsHelper.java | 9 +-
.../envoy/als/mx/MetaExchangeALSHTTPAnalyzer.java | 26 +++--
.../envoy/als/mx/ServiceMetaInfoAdapter.java | 2 +-
.../envoy/persistence/LogsPersistence.java | 117 +++++++++++++++++++++
...g.oap.server.receiver.envoy.als.ALSHTTPAnalysis | 1 +
.../als/k8s/K8SALSServiceMeshHTTPAnalysisTest.java | 9 +-
.../resources/expected/als/endpoints-details.yml | 2 +-
.../expected/als/endpoints-productpage.yml | 2 +-
.../resources/expected/als/endpoints-ratings.yml | 2 +-
.../resources/expected/als/endpoints-reviews.yml | 2 +-
29 files changed, 390 insertions(+), 67 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 93d04ca..2ced45f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -39,6 +39,7 @@ Release Notes.
* Require Zipkin receiver must work with `zipkin-elasticsearch7` storage
option.
* Fix `DatabaseSlowStatementBuilder` statement maybe null.
* Remove fields of parent entity in the relation sources.
+* Save Envoy http access logs when error occurs.
#### UI
* Update selector scroller to show in all pages.
diff --git a/docs/en/setup/backend/configuration-vocabulary.md
b/docs/en/setup/backend/configuration-vocabulary.md
index 1e2b2d5..40955f6 100644
--- a/docs/en/setup/backend/configuration-vocabulary.md
+++ b/docs/en/setup/backend/configuration-vocabulary.md
@@ -173,6 +173,10 @@ core|default|role|Option values,
`Mixed/Receiver/Aggregator`. **Receiver** mode
| - | - | gRPCSslCertChainPath| The file path of gRPC SSL cert chain|
SW_RECEIVER_GRPC_SSL_CERT_CHAIN_PATH | - |
| - | - | maxConcurrentCallsPerConnection | The maximum number of concurrent
calls permitted for each incoming connection. Defaults to no limit. |
SW_RECEIVER_GRPC_MAX_CONCURRENT_CALL | - |
| - | - | authentication | The token text for the authentication. Work for
gRPC connection only. Once this is set, the client is required to use the same
token. | SW_AUTHENTICATION | - |
+| log-analyzer | default | Log Analyzer. | SW_LOG_ANALYZER | default |
+| - | - | lalFiles | The LAL configuration file names (without file extension)
to be activated. Read [LAL](../../concepts-and-designs/lal.md) for more
details. | SW_LOG_LAL_FILES | default |
+| - | - | malFiles | The MAL configuration file names (without file extension)
to be activated. Read [LAL](../../concepts-and-designs/lal.md) for more
details. | SW_LOG_MAL_FILES | "" |
+| event-analyzer | default | Event Analyzer. | SW_EVENT_ANALYZER | default |
| receiver-register|default| Read [receiver doc](backend-receivers.md) for
more details | - | - |
| receiver-trace|default| Read [receiver doc](backend-receivers.md) for more
details | - | - |
| receiver-jvm| default| Read [receiver doc](backend-receivers.md) for more
details | - | - |
diff --git a/docs/en/setup/envoy/als_setting.md
b/docs/en/setup/envoy/als_setting.md
index 287fb29..bc22a7a 100644
--- a/docs/en/setup/envoy/als_setting.md
+++ b/docs/en/setup/envoy/als_setting.md
@@ -70,9 +70,10 @@ You can use `kubectl -n istio-system logs -l app=skywalking
| grep "K8sALSServic
## SkyWalking ALS Analyzers
-There are two available analyzers, `k8s-mesh` and `mx-mesh`, you can specify
one or more analyzers to analyze the access logs.
-When multiple analyzers are specified, it acts as a fast-success mechanism:
SkyWalking loops over the analyzers and use it to analyze the logs, once
-there is an analyzer that is able to produce a result, it stops the loop.
+There are several available analyzers, `k8s-mesh`, `mx-mesh` and
`persistence`, you can specify one or more
+analyzers to analyze the access logs. When multiple analyzers are specified,
it acts as a fast-success mechanism:
+SkyWalking loops over the analyzers and use it to analyze the logs, once there
is an analyzer that is able to produce a
+result, it stops the loop.
### `k8s-mesh`
@@ -87,3 +88,20 @@ this analyzer requires Istio to enable the metadata exchange
plugin (you can ena
or if you're using Istio 1.7+ and installing it with profile `demo`/`preview`,
it should be enabled then).
The
[blog](https://skywalking.apache.org/blog/obs-service-mesh-vm-with-sw-and-als/)
illustrates the detail of how it works, and a step-by-step tutorial to apply it
into the [Online
Boutique](https://github.com/GoogleCloudPlatform/microservices-demo) system.
+
+### `persistence`
+
+`persistence` analyzer adapts the Envoy access log format to
+SkyWalking's [native log
format](https://github.com/apache/skywalking-data-collect-protocol/blob/master/logging/Logging.proto)
+, and forwards the formatted logs to [LAL](../../concepts-and-designs/lal.md),
where you can configure persistent
+conditions, such as `sampler`, only persist error logs, etc. SkyWalking
provides a default configuration
+file
[`envoy-als.yaml`](../../../../oap-server/server-bootstrap/src/main/resources/lal/envoy-als.yaml)
that you can
+adjust as per your needs. Please make sure to activate this rule via adding
the rule name `envoy-als`
+into config item `log-analyzer/default/lalFiles` (or environment variable
`SW_LOG_LAL_FILES`,
+e.g. `SW_LOG_LAL_FILES=envoy-als`).
+
+**Attention**: because `persistence` analyzer also needs a mechanism to map
the logs into responding services, hence,
+you need to configure at least one of `k8s-mesh` or `mx-mesh` as its
antecedent so that `persistence` analyzer knows
+which service the logs belong to. For example, you should set
`envoy-metric/default/alsHTTPAnalysis` (or environment
+variable `SW_ENVOY_METRIC_ALS_HTTP_ANALYSIS`) to something like
`k8s-mesh,persistence`, `mx-mesh,persistence`
+or `mx-mesh,k8s-mesh,persistence`.
diff --git
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/extractor/ExtractorSpec.java
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/extractor/ExtractorSpec.java
index 0d68fe2..49ea7d6 100644
---
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/extractor/ExtractorSpec.java
+++
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/extractor/ExtractorSpec.java
@@ -18,8 +18,10 @@
package org.apache.skywalking.oap.log.analyzer.dsl.spec.extractor;
+import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import groovy.lang.Closure;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -107,7 +109,17 @@ public class ExtractorSpec extends AbstractSpec {
.stream()
.filter(it -> isNotBlank(it.getKey()))
.filter(it -> nonNull(it.getValue()) &&
isNotBlank(Objects.toString(it.getValue())))
- .map(it ->
KeyStringValuePair.newBuilder().setKey(it.getKey()).setValue(Objects.toString(it.getValue())).build())
+ .map(it -> {
+ final Object val = it.getValue();
+ String valStr = Objects.toString(val);
+ if
(Collection.class.isAssignableFrom(val.getClass())) {
+ valStr =
Joiner.on(",").skipNulls().join((Collection<?>) val);
+ }
+ return KeyStringValuePair.newBuilder()
+ .setKey(it.getKey())
+ .setValue(valStr)
+ .build();
+ })
.collect(Collectors.toList())
)
);
diff --git
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/SamplerSpec.java
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/SamplerSpec.java
index 178fa06..e32f792 100644
---
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/SamplerSpec.java
+++
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/SamplerSpec.java
@@ -20,19 +20,14 @@ package
org.apache.skywalking.oap.log.analyzer.dsl.spec.sink;
import groovy.lang.Closure;
import java.util.Map;
-import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.skywalking.oap.log.analyzer.dsl.spec.AbstractSpec;
import
org.apache.skywalking.oap.log.analyzer.dsl.spec.sink.sampler.RateLimitingSampler;
import org.apache.skywalking.oap.log.analyzer.dsl.spec.sink.sampler.Sampler;
import org.apache.skywalking.oap.log.analyzer.provider.LogAnalyzerModuleConfig;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public class SamplerSpec extends AbstractSpec {
- private static final Logger LOGGER =
LoggerFactory.getLogger(SamplerSpec.class);
-
private final Map<String, Sampler> samplers;
private final RateLimitingSampler.ResetHandler rlsResetHandler;
@@ -49,25 +44,13 @@ public class SamplerSpec extends AbstractSpec {
if (BINDING.get().shouldAbort()) {
return;
}
- final RateLimitingSampler newSampler = new
RateLimitingSampler(rlsResetHandler);
- cl.setDelegate(newSampler);
- cl.call();
- final Sampler sampler = samplers.computeIfAbsent(id, $ ->
Sampler.NOOP);
- if (Objects.equals(sampler, newSampler)) { // Unchanged
- sampleWith(sampler);
- return;
- }
+ final Sampler sampler = samplers.computeIfAbsent(id, $ -> new
RateLimitingSampler(rlsResetHandler).start());
- try {
- sampler.close();
- } catch (final Exception e) {
- LOGGER.error("Failed to cancel old sampler: {}", sampler, e);
- }
-
- samplers.put(id, newSampler.start());
+ cl.setDelegate(sampler);
+ cl.call();
- sampleWith(newSampler);
+ sampleWith(sampler);
}
private void sampleWith(final Sampler sampler) {
diff --git
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/sampler/RateLimitingSampler.java
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/sampler/RateLimitingSampler.java
index 287fe24..c629f75 100644
---
a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/sampler/RateLimitingSampler.java
+++
b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/dsl/spec/sink/sampler/RateLimitingSampler.java
@@ -18,8 +18,8 @@
package org.apache.skywalking.oap.log.analyzer.dsl.spec.sink.sampler;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -69,7 +69,7 @@ public class RateLimitingSampler implements Sampler {
@Slf4j
public static class ResetHandler {
- private final Set<Sampler> samplers = new HashSet<>();
+ private final List<Sampler> samplers = new ArrayList<>();
private volatile ScheduledFuture<?> future;
diff --git a/oap-server/server-bootstrap/src/main/resources/lal/envoy-als.yaml
b/oap-server/server-bootstrap/src/main/resources/lal/envoy-als.yaml
new file mode 100644
index 0000000..4be3213
--- /dev/null
+++ b/oap-server/server-bootstrap/src/main/resources/lal/envoy-als.yaml
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+rules:
+ - name: envoy-als
+ dsl: |
+ filter {
+ json {
+ }
+ // only collect abnormal logs (http status code >= 300, or
commonProperties?.responseFlags is not empty)
+ if (parsed?.response?.responseCode < 400 &&
!parsed?.commonProperties?.responseFlags) {
+ abort {}
+ }
+ extractor {
+ tag 'status.code': parsed?.response?.responseCode as int
+ tag 'response.flag':
parsed?.commonProperties?.responseFlags?.keySet()
+ }
+ sink {
+ sampler {
+ if (parsed?.commonProperties?.responseFlags) {
+ // use service:errorCode as sampler id so that each
service:errorCode has its own sampler,
+ // e.g. checkoutservice:[upstreamConnectionFailure],
checkoutservice:[upstreamRetryLimitExceeded]
+
rateLimit("${log.service}:${parsed?.commonProperties?.responseFlags?.keySet()}")
{
+ qps 100
+ }
+ } else {
+ // use service:responseCode as sampler id so that each
service:responseCode has its own sampler,
+ // e.g. checkoutservice:500, checkoutservice:404.
+ rateLimit("${log.service}:${parsed?.response?.responseCode}") {
+ qps 100
+ }
+ }
+ }
+ }
+ }
diff --git
a/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ProtoBufJsonUtils.java
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ProtoBufJsonUtils.java
index 2f35d18..0bb837f 100644
---
a/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ProtoBufJsonUtils.java
+++
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/ProtoBufJsonUtils.java
@@ -18,6 +18,7 @@
package org.apache.skywalking.oap.server.library.util;
+import com.google.protobuf.BytesValue;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import java.io.IOException;
@@ -25,7 +26,15 @@ import java.io.IOException;
public class ProtoBufJsonUtils {
public static String toJSON(Message sourceMessage) throws IOException {
- return JsonFormat.printer().print(sourceMessage);
+ return JsonFormat.printer()
+ .usingTypeRegistry(
+ JsonFormat
+ .TypeRegistry
+ .newBuilder()
+ .add(BytesValue.getDescriptor())
+ .build()
+ )
+ .print(sourceMessage);
}
/**
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml
index e430882..43cfb53 100644
--- a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml
@@ -41,6 +41,11 @@
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
+ <artifactId>log-analyzer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
<artifactId>skywalking-mesh-receiver-plugin</artifactId>
<version>${project.version}</version>
</dependency>
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/AccessLogServiceGRPCHandler.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/AccessLogServiceGRPCHandler.java
index 4d47072..bce63fb 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/AccessLogServiceGRPCHandler.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/AccessLogServiceGRPCHandler.java
@@ -30,7 +30,6 @@ import
org.apache.skywalking.aop.server.receiver.mesh.TelemetryDataDispatcher;
import org.apache.skywalking.apm.network.servicemesh.v3.ServiceMeshMetric;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.ModuleStartException;
-import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.receiver.envoy.als.ALSHTTPAnalysis;
import org.apache.skywalking.oap.server.receiver.envoy.als.Role;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
@@ -117,15 +116,11 @@ public class AccessLogServiceGRPCHandler extends
AccessLogServiceGrpc.AccessLogS
List<ServiceMeshMetric.Builder> sourceResult = new
ArrayList<>();
for (final HTTPAccessLogEntry log :
logs.getLogEntryList()) {
+ List<ServiceMeshMetric.Builder> result = new
ArrayList<>();
for (ALSHTTPAnalysis analysis :
envoyHTTPAnalysisList) {
- final List<ServiceMeshMetric.Builder>
result =
- analysis.analysis(identifier, log,
role);
- if (CollectionUtils.isNotEmpty(result)) {
- // Once the analysis has results,
don't need to continue analysis in lower priority analyzers.
- sourceResult.addAll(result);
- break;
- }
+ result = analysis.analysis(result,
identifier, log, role);
}
+ sourceResult.addAll(result);
}
sourceDispatcherCounter.inc(sourceResult.size());
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverConfig.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverConfig.java
index fb029fb..94f8c45 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverConfig.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverConfig.java
@@ -36,6 +36,8 @@ public class EnvoyMetricReceiverConfig extends ModuleConfig {
@Getter
private String k8sServiceNameRule;
+ private final ServiceMetaInfoFactory serviceMetaInfoFactory = new
ServiceMetaInfoFactoryImpl();
+
public List<String> getAlsHTTPAnalysis() {
if (Strings.isNullOrEmpty(alsHTTPAnalysis)) {
return Collections.emptyList();
@@ -46,4 +48,8 @@ public class EnvoyMetricReceiverConfig extends ModuleConfig {
public List<Rule> rules() throws ModuleStartException {
return Rules.loadRules("envoy-metrics-rules",
Collections.singletonList("envoy"));
}
+
+ public ServiceMetaInfoFactory serviceMetaInfoFactory() {
+ return serviceMetaInfoFactory;
+ }
}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverProvider.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverProvider.java
index 1e3d8c0..4098cbf 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverProvider.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverProvider.java
@@ -57,7 +57,7 @@ public class EnvoyMetricReceiverProvider extends
ModuleProvider {
@Override
public void prepare() throws ServiceNotProvidedException,
ModuleStartException {
try {
- FieldsHelper.SINGLETON.init(fieldMappingFile);
+ FieldsHelper.SINGLETON.init(fieldMappingFile,
config.serviceMetaInfoFactory().clazz());
} catch (final Exception e) {
throw new ModuleStartException("Failed to load
metadata-service-mapping.yaml", e);
}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/MetricServiceGRPCHandler.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/MetricServiceGRPCHandler.java
index 38e4370..94f7704 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/MetricServiceGRPCHandler.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/MetricServiceGRPCHandler.java
@@ -36,7 +36,6 @@ import
org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.ModuleStartException;
import org.apache.skywalking.oap.server.library.util.prometheus.metrics.Metric;
import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo;
-import
org.apache.skywalking.oap.server.receiver.envoy.als.mx.ServiceMetaInfoAdapter;
import
org.apache.skywalking.oap.server.receiver.envoy.metrics.adapters.ProtoMetricFamily2MetricsAdapter;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics;
@@ -50,7 +49,11 @@ public class MetricServiceGRPCHandler extends
MetricsServiceGrpc.MetricsServiceI
private final HistogramMetrics histogram;
private final List<PrometheusMetricConverter> converters;
+ private final EnvoyMetricReceiverConfig config;
+
public MetricServiceGRPCHandler(final ModuleManager moduleManager, final
EnvoyMetricReceiverConfig config) throws ModuleStartException {
+ this.config = config;
+
MetricsCreator metricsCreator =
moduleManager.find(TelemetryModule.NAME)
.provider()
.getService(MetricsCreator.class);
@@ -86,7 +89,7 @@ public class MetricServiceGRPCHandler extends
MetricsServiceGrpc.MetricsServiceI
if (isFirst) {
isFirst = false;
- service = new
ServiceMetaInfoAdapter(message.getIdentifier().getNode().getMetadata());
+ service =
config.serviceMetaInfoFactory().fromStruct(message.getIdentifier().getNode().getMetadata());
}
if (log.isDebugEnabled()) {
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactory.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactory.java
new file mode 100644
index 0000000..5e865d7
--- /dev/null
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.receiver.envoy;
+
+import com.google.protobuf.Struct;
+import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo;
+
+/**
+ * Factory to create {@link ServiceMetaInfo} instances from Kubernetes Pods,
Envoy access log metadata, etc.
+ */
+public interface ServiceMetaInfoFactory {
+ /**
+ * @return the {@link Class} of the {@link ServiceMetaInfo} implementation.
+ */
+ Class<? extends ServiceMetaInfo> clazz();
+
+ /**
+ * @return an UNKNOWN instance of {@link ServiceMetaInfo}.
+ */
+ ServiceMetaInfo unknown();
+
+ /**
+ * Create an instance of {@link ServiceMetaInfo} from the given {@link
Struct protobuf struct}.
+ */
+ ServiceMetaInfo fromStruct(final Struct struct) throws Exception;
+}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java
new file mode 100644
index 0000000..a89a55b
--- /dev/null
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/ServiceMetaInfoFactoryImpl.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.receiver.envoy;
+
+import com.google.protobuf.Struct;
+import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo;
+import
org.apache.skywalking.oap.server.receiver.envoy.als.mx.ServiceMetaInfoAdapter;
+
+public class ServiceMetaInfoFactoryImpl implements ServiceMetaInfoFactory {
+ @Override
+ public Class<? extends ServiceMetaInfo> clazz() {
+ return ServiceMetaInfo.class;
+ }
+
+ @Override
+ public ServiceMetaInfo unknown() {
+ return new ServiceMetaInfo("UNKNOWN", "UNKNOWN");
+ }
+
+ @Override
+ public ServiceMetaInfo fromStruct(final Struct struct) throws Exception {
+ return new ServiceMetaInfoAdapter(struct);
+ }
+}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ALSHTTPAnalysis.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ALSHTTPAnalysis.java
index 3b51aa0..7058e30 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ALSHTTPAnalysis.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ALSHTTPAnalysis.java
@@ -34,7 +34,23 @@ public interface ALSHTTPAnalysis {
void init(ModuleManager manager, EnvoyMetricReceiverConfig config) throws
ModuleStartException;
- List<ServiceMeshMetric.Builder>
analysis(StreamAccessLogsMessage.Identifier identifier, HTTPAccessLogEntry
entry, Role role);
+ /**
+ * The method works as a chain of analyzers. Logs are processed
sequentially by analyzers one by one, the results of the previous analyzer are
passed into the current one.
+ *
+ * To do fast-success, the analyzer could simply check the results of the
previous analyzer and return if not empty.
+ *
+ * @param result of the previous analyzer.
+ * @param identifier of the Envoy node where the logs are emitted.
+ * @param entry the log entry.
+ * @param role the role of the Envoy node where the logs are emitted.
+ * @return the analysis results.
+ */
+ List<ServiceMeshMetric.Builder> analysis(
+ final List<ServiceMeshMetric.Builder> result,
+ final StreamAccessLogsMessage.Identifier identifier,
+ final HTTPAccessLogEntry entry,
+ final Role role
+ );
Role identify(StreamAccessLogsMessage.Identifier alsIdentifier, Role prev);
}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/AbstractALSAnalyzer.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/AbstractALSAnalyzer.java
index 462eeba..0ccc147 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/AbstractALSAnalyzer.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/AbstractALSAnalyzer.java
@@ -32,10 +32,10 @@ public abstract class AbstractALSAnalyzer implements
ALSHTTPAnalysis {
if (alsIdentifier == null) {
return defaultRole;
}
- final Node node = alsIdentifier.getNode();
- if (node == null) {
+ if (!alsIdentifier.hasNode()) {
return defaultRole;
}
+ final Node node = alsIdentifier.getNode();
final String id = node.getId();
if (id.startsWith("router~")) {
return Role.PROXY;
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/LogEntry2MetricsAdapter.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/LogEntry2MetricsAdapter.java
index 0317d77..accdf23 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/LogEntry2MetricsAdapter.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/LogEntry2MetricsAdapter.java
@@ -131,7 +131,12 @@ public class LogEntry2MetricsAdapter {
}
protected String endpoint() {
- return
ofNullable(entry.getRequest()).map(HTTPRequestProperties::getPath).orElse("/");
+ if (!entry.hasRequest()) {
+ return "/";
+ }
+ final HTTPRequestProperties request = entry.getRequest();
+ final String method = request.getRequestMethod().name();
+ return method + ":" + request.getPath();
}
protected static long formatAsLong(final Timestamp timestamp) {
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8sALSServiceMeshHTTPAnalysis.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8sALSServiceMeshHTTPAnalysis.java
index 976a790..2b99075 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8sALSServiceMeshHTTPAnalysis.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8sALSServiceMeshHTTPAnalysis.java
@@ -35,6 +35,7 @@ import
org.apache.skywalking.oap.server.receiver.envoy.als.AbstractALSAnalyzer;
import org.apache.skywalking.oap.server.receiver.envoy.als.Role;
import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo;
+import static
org.apache.skywalking.oap.server.library.util.CollectionUtils.isNotEmpty;
import static
org.apache.skywalking.oap.server.receiver.envoy.als.LogEntry2MetricsAdapter.NON_TLS;
/**
@@ -57,7 +58,15 @@ public class K8sALSServiceMeshHTTPAnalysis extends
AbstractALSAnalyzer {
}
@Override
- public List<ServiceMeshMetric.Builder>
analysis(StreamAccessLogsMessage.Identifier identifier, HTTPAccessLogEntry
entry, Role role) {
+ public List<ServiceMeshMetric.Builder> analysis(
+ final List<ServiceMeshMetric.Builder> result,
+ final StreamAccessLogsMessage.Identifier identifier,
+ final HTTPAccessLogEntry entry,
+ final Role role
+ ) {
+ if (isNotEmpty(result)) {
+ return result;
+ }
if (serviceRegistry.isEmpty()) {
return Collections.emptyList();
}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
index f3d2724..43737d7 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/FieldsHelper.java
@@ -54,10 +54,6 @@ public enum FieldsHelper {
*/
private Map<String, Method> fieldSetterMapping;
- public void init(final String file) throws Exception {
- init(ResourceUtils.readToStream(file), ServiceMetaInfo.class);
- }
-
public void init(final String file,
final Class<? extends ServiceMetaInfo> serviceInfoClass)
throws Exception {
init(ResourceUtils.readToStream(file), serviceInfoClass);
@@ -127,7 +123,10 @@ public enum FieldsHelper {
}
values[i] = value.getStringValue();
}
- fieldSetterMapping.get(entry.getKey()).invoke(serviceMetaInfo,
Strings.lenientFormat(serviceNameFormat.format, values));
+ final String value =
Strings.lenientFormat(serviceNameFormat.format, values);
+ if (!Strings.isNullOrEmpty(value)) {
+ fieldSetterMapping.get(entry.getKey()).invoke(serviceMetaInfo,
value);
+ }
}
}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/MetaExchangeALSHTTPAnalyzer.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/MetaExchangeALSHTTPAnalyzer.java
index a31cd0b..0cb752e 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/MetaExchangeALSHTTPAnalyzer.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/MetaExchangeALSHTTPAnalyzer.java
@@ -23,7 +23,6 @@ import com.google.protobuf.TextFormat;
import io.envoyproxy.envoy.data.accesslog.v3.AccessLogCommon;
import io.envoyproxy.envoy.data.accesslog.v3.HTTPAccessLogEntry;
import io.envoyproxy.envoy.service.accesslog.v3.StreamAccessLogsMessage;
-import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
@@ -38,6 +37,7 @@ import
org.apache.skywalking.oap.server.receiver.envoy.als.AbstractALSAnalyzer;
import org.apache.skywalking.oap.server.receiver.envoy.als.Role;
import org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo;
+import static
org.apache.skywalking.oap.server.library.util.CollectionUtils.isNotEmpty;
import static
org.apache.skywalking.oap.server.receiver.envoy.als.LogEntry2MetricsAdapter.NON_TLS;
import static
org.apache.skywalking.oap.server.receiver.envoy.als.ServiceMetaInfo.UNKNOWN;
@@ -50,6 +50,8 @@ public class MetaExchangeALSHTTPAnalyzer extends
AbstractALSAnalyzer {
protected String fieldMappingFile = "metadata-service-mapping.yaml";
+ protected EnvoyMetricReceiverConfig config;
+
@Override
public String name() {
return "mx-mesh";
@@ -57,21 +59,30 @@ public class MetaExchangeALSHTTPAnalyzer extends
AbstractALSAnalyzer {
@Override
public void init(ModuleManager manager, EnvoyMetricReceiverConfig config)
throws ModuleStartException {
+ this.config = config;
try {
- FieldsHelper.SINGLETON.init(fieldMappingFile);
+ FieldsHelper.SINGLETON.init(fieldMappingFile,
config.serviceMetaInfoFactory().clazz());
} catch (final Exception e) {
throw new ModuleStartException("Failed to load
metadata-service-mapping.yaml", e);
}
}
@Override
- public List<ServiceMeshMetric.Builder>
analysis(StreamAccessLogsMessage.Identifier identifier, HTTPAccessLogEntry
entry, Role role) {
- final AccessLogCommon properties = entry.getCommonProperties();
- if (properties == null) {
+ public List<ServiceMeshMetric.Builder> analysis(
+ final List<ServiceMeshMetric.Builder> result,
+ final StreamAccessLogsMessage.Identifier identifier,
+ final HTTPAccessLogEntry entry,
+ final Role role
+ ) {
+ if (isNotEmpty(result)) {
+ return result;
+ }
+ if (!entry.hasCommonProperties()) {
return Collections.emptyList();
}
+ final AccessLogCommon properties = entry.getCommonProperties();
final Map<String, Any> stateMap =
properties.getFilterStateObjectsMap();
- if (stateMap == null) {
+ if (stateMap.isEmpty()) {
return Collections.emptyList();
}
final ServiceMetaInfo currSvc;
@@ -82,7 +93,6 @@ public class MetaExchangeALSHTTPAnalyzer extends
AbstractALSAnalyzer {
return Collections.emptyList();
}
- final List<ServiceMeshMetric.Builder> result = new ArrayList<>();
final AtomicBoolean downstreamExists = new AtomicBoolean();
stateMap.forEach((key, value) -> {
if (!key.equals(UPSTREAM_KEY) && !key.equals(DOWNSTREAM_KEY)) {
@@ -129,7 +139,7 @@ public class MetaExchangeALSHTTPAnalyzer extends
AbstractALSAnalyzer {
}
protected ServiceMetaInfo adaptToServiceMetaInfo(final
StreamAccessLogsMessage.Identifier identifier) throws Exception {
- return new ServiceMetaInfoAdapter(identifier.getNode().getMetadata());
+ return
config.serviceMetaInfoFactory().fromStruct(identifier.getNode().getMetadata());
}
}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
index 099231d..df8e38b 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/mx/ServiceMetaInfoAdapter.java
@@ -83,7 +83,7 @@ public class ServiceMetaInfoAdapter extends ServiceMetaInfo {
* @param node the flat buffer node where to extract the metadata
* @return the metadata {@link Struct}
*/
- protected Struct extractStructFromNodeFlatBuffer(final FlatNode node) {
+ public static Struct extractStructFromNodeFlatBuffer(final FlatNode node) {
final Struct.Builder builder = Struct.newBuilder();
builder.putFields("NAME",
Value.newBuilder().setStringValue(nullToEmpty(node.name())).build());
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/persistence/LogsPersistence.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/persistence/LogsPersistence.java
new file mode 100644
index 0000000..132911b
--- /dev/null
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/persistence/LogsPersistence.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.receiver.envoy.persistence;
+
+import com.google.protobuf.TextFormat;
+import io.envoyproxy.envoy.data.accesslog.v3.HTTPAccessLogEntry;
+import io.envoyproxy.envoy.service.accesslog.v3.StreamAccessLogsMessage;
+import java.io.IOException;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.apm.network.common.v3.DetectPoint;
+import org.apache.skywalking.apm.network.logging.v3.JSONLog;
+import org.apache.skywalking.apm.network.logging.v3.LogData;
+import org.apache.skywalking.apm.network.logging.v3.LogDataBody;
+import org.apache.skywalking.apm.network.servicemesh.v3.ServiceMeshMetric;
+import org.apache.skywalking.oap.log.analyzer.module.LogAnalyzerModule;
+import org.apache.skywalking.oap.log.analyzer.provider.log.ILogAnalyzerService;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+import org.apache.skywalking.oap.server.library.module.ModuleStartException;
+import
org.apache.skywalking.oap.server.receiver.envoy.EnvoyMetricReceiverConfig;
+import org.apache.skywalking.oap.server.receiver.envoy.als.ALSHTTPAnalysis;
+import org.apache.skywalking.oap.server.receiver.envoy.als.Role;
+
+import static
org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils.toJSON;
+
+/**
+ * {@code LogsPersistence} analyzes the error logs and persists them to the
log system.
+ */
+@Slf4j
+public class LogsPersistence implements ALSHTTPAnalysis {
+ private ILogAnalyzerService logAnalyzerService;
+
+ @Override
+ public String name() {
+ return "persistence";
+ }
+
+ @Override
+ public void init(final ModuleManager manager, final
EnvoyMetricReceiverConfig config) throws ModuleStartException {
+ logAnalyzerService = manager.find(LogAnalyzerModule.NAME)
+ .provider()
+ .getService(ILogAnalyzerService.class);
+ }
+
+ @Override
+ public List<ServiceMeshMetric.Builder> analysis(
+ final List<ServiceMeshMetric.Builder> result,
+ final StreamAccessLogsMessage.Identifier identifier,
+ final HTTPAccessLogEntry entry,
+ final Role role
+ ) {
+ try {
+ result.stream()
+ .findFirst()
+ .ifPresent(metrics -> {
+ try {
+ final LogData logData = convertToLogData(entry,
metrics);
+ logAnalyzerService.doAnalysis(logData);
+ } catch (IOException e) {
+ log.error(
+ "Failed to parse error log entry to log data:
{}",
+ TextFormat.shortDebugString(entry),
+ e
+ );
+ }
+ });
+ } catch (final Exception e) {
+ log.error("Failed to persist Envoy access log", e);
+ }
+ return result;
+ }
+
+ @Override
+ public Role identify(final StreamAccessLogsMessage.Identifier
alsIdentifier, final Role prev) {
+ return prev;
+ }
+
+ public LogData convertToLogData(final HTTPAccessLogEntry logEntry,
+ final ServiceMeshMetric.Builder metrics)
throws IOException {
+ final boolean isServerSide = metrics.getDetectPoint() ==
DetectPoint.server;
+ final String svc = isServerSide ? metrics.getDestServiceName() :
metrics.getSourceServiceName();
+ final String svcInst = isServerSide ? metrics.getDestServiceInstance()
: metrics.getSourceServiceInstance();
+
+ return LogData
+ .newBuilder()
+ .setService(svc)
+ .setServiceInstance(svcInst)
+ .setEndpoint(metrics.getEndpoint())
+ .setTimestamp(metrics.getEndTime())
+ .setBody(
+ LogDataBody
+ .newBuilder()
+ .setJson(
+ JSONLog
+ .newBuilder()
+ .setJson(toJSON(logEntry))
+ )
+ )
+ .build();
+ }
+}
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.receiver.envoy.als.ALSHTTPAnalysis
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.receiver.envoy.als.ALSHTTPAnalysis
index bb5a7d9..2664018 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.receiver.envoy.als.ALSHTTPAnalysis
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.receiver.envoy.als.ALSHTTPAnalysis
@@ -19,3 +19,4 @@
org.apache.skywalking.oap.server.receiver.envoy.als.k8s.K8sALSServiceMeshHTTPAnalysis
org.apache.skywalking.oap.server.receiver.envoy.als.mx.MetaExchangeALSHTTPAnalyzer
+org.apache.skywalking.oap.server.receiver.envoy.persistence.LogsPersistence
diff --git
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8SALSServiceMeshHTTPAnalysisTest.java
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8SALSServiceMeshHTTPAnalysisTest.java
index 9832603..2ebf581 100644
---
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8SALSServiceMeshHTTPAnalysisTest.java
+++
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/k8s/K8SALSServiceMeshHTTPAnalysisTest.java
@@ -23,6 +23,7 @@ import
io.envoyproxy.envoy.service.accesslog.v3.StreamAccessLogsMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.util.ArrayList;
import java.util.List;
import org.apache.skywalking.apm.network.common.v3.DetectPoint;
import org.apache.skywalking.apm.network.servicemesh.v3.ServiceMeshMetric;
@@ -77,7 +78,7 @@ public class K8SALSServiceMeshHTTPAnalysisTest {
StreamAccessLogsMessage.Builder requestBuilder =
StreamAccessLogsMessage.newBuilder();
JsonFormat.parser().merge(isr, requestBuilder);
- List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.PROXY);
+ List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(new ArrayList<>(), requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.PROXY);
Assert.assertEquals(2, result.size());
@@ -99,7 +100,7 @@ public class K8SALSServiceMeshHTTPAnalysisTest {
StreamAccessLogsMessage.Builder requestBuilder =
StreamAccessLogsMessage.newBuilder();
JsonFormat.parser().merge(isr, requestBuilder);
- List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.SIDECAR);
+ List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(new ArrayList<>(), requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.SIDECAR);
Assert.assertEquals(1, result.size());
@@ -116,7 +117,7 @@ public class K8SALSServiceMeshHTTPAnalysisTest {
StreamAccessLogsMessage.Builder requestBuilder =
StreamAccessLogsMessage.newBuilder();
JsonFormat.parser().merge(isr, requestBuilder);
- List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.SIDECAR);
+ List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(new ArrayList<>(), requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.SIDECAR);
Assert.assertEquals(1, result.size());
@@ -133,7 +134,7 @@ public class K8SALSServiceMeshHTTPAnalysisTest {
StreamAccessLogsMessage.Builder requestBuilder =
StreamAccessLogsMessage.newBuilder();
JsonFormat.parser().merge(isr, requestBuilder);
- List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.SIDECAR);
+ List<ServiceMeshMetric.Builder> result =
this.analysis.analysis(new ArrayList<>(), requestBuilder.getIdentifier(),
requestBuilder.getHttpLogs().getLogEntry(0), Role.SIDECAR);
Assert.assertEquals(1, result.size());
diff --git
a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-details.yml
b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-details.yml
index d184dc5..22fb285 100644
--- a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-details.yml
+++ b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-details.yml
@@ -15,4 +15,4 @@
endpoints:
- key: not null
- label: /details/0
+ label: GET:/details/0
diff --git
a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-productpage.yml
b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-productpage.yml
index f22e0d2..8d5a970 100644
---
a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-productpage.yml
+++
b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-productpage.yml
@@ -15,4 +15,4 @@
endpoints:
- key: not null
- label: /productpage
+ label: GET:/productpage
diff --git
a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-ratings.yml
b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-ratings.yml
index a7f0c3c..2a74f94 100644
--- a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-ratings.yml
+++ b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-ratings.yml
@@ -15,4 +15,4 @@
endpoints:
- key: not null
- label: /ratings/0
+ label: GET:/ratings/0
diff --git
a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-reviews.yml
b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-reviews.yml
index 1a2f5f8..17a39cf 100644
--- a/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-reviews.yml
+++ b/test/e2e/e2e-test/src/test/resources/expected/als/endpoints-reviews.yml
@@ -15,4 +15,4 @@
endpoints:
- key: not null
- label: /reviews/0
+ label: GET:/reviews/0