Building Envoy WASM network filter - c++

I'm trying to build a tcp level WASM filter for Envoy. I'm testing with following filter chain :
filter_chains:
- filters:
- name: envoy.filters.wasm
typed_config:
"#type": type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm
config:
name: "myfilter"
vm_config:
runtime: "envoy.wasm.runtime.v8"
code:
local:
filename: "/opt/envoy/filter.wasm"
allow_precompiled: true
- name: envoy.filters.network.echo
my cpp code compiles ok and envoy starts fine, but even with just
FilterStatus MyFilterContext::onNewConnection() {
LOG_DEBUG("onNewConn");
return FilterStatus::StopIteration;
};
FilterStatus MyFilterContext::onDownstreamData(size_t, bool) {
LOG_DEBUG("onDownstream");
return FilterStatus::StopIteration;
}
I would expect the connection to never reach the echo service, yet it does every time, and there is nothing logged from wasm filter side in envoy logs, apart of trace level logs showing that wasm always returns the same logical value :
[29][trace][wasm] [source/extensions/common/wasm/wasm_vm.cc:40] [host->vm] proxy_on_new_connection(2)
[29][trace][wasm] [source/extensions/common/wasm/wasm_vm.cc:40] [host<-vm] proxy_on_new_connection return: 0
While there are many for HTTP filters, I was unable to locate any examples of a network filter implementation, which makes me wonder if anyone has this working, and if so, how exactly.
I also tried implementing it in rust, to no success as it compiles but then, within envoy it fails with
Function: proxy_on_context_create failed: Uncaught RuntimeError: unreachable
Proxy-Wasm plugin in-VM backtrace:
0: 0x164c - __rust_start_panic
Did anyone actually implemented a working network filter for Envoy ? An example code would be great as all the examples I found are for HTTP filters which do me no good.

Yes, I've implemented a working NETWORK_FILTER for Envoy. https://github.com/solo-io/proxy-runtime/commit/0b7fec73a36a979b53a05393b3868f1661af8dff was required for it to work in AssemblyScript. The commit message describes the YAML configuration I used with an Istio-flavored Envoy, but it depends on which version of Envoy you're using. Each language's runtime may or may not support it, but the C++ runtime certainly does, if you don't want to use AssemblyScript.
See also https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/wasm_filter.html

Related

Vertex Pipeline Metric values not being added to metrics artifact?

We are trying to return some metrics from our Vertex Pipeline, such that they are visible in the Run Comparison and Metadata tools in the Vertex UI.
I saw here that we can use this output type Output[Metrics], and the subsequent metrics.log_metric("metric_name", metric_val) method to add the metrics, and it seemed from the available documentation that this would be enough.
We want to use the reusable component method as opposed to python function based components, around which the example is based. So we implemented it within our component code like so:
We added the output in the component.yaml:
outputs:
- name: metrics
type: Metrics
description: evaluation metrics path
then added the output to the command in the implemenation:
command: [
python3, main.py,
--gcs-test-data-path, {inputValue: gcs_test_data_path},
--gcs-model-path, {inputValue: gcs_model_path},
--gcs-output-bucket-id, {inputValue: gcs_output_bucket_id},
--project-id, {inputValue: project_id},
--timestamp, {inputValue: timestamp},
--batch-size, {inputValue: batch_size},
--img-height, {inputValue: img_height},
--img-width, {inputValue: img_width},
--img-depth, {inputValue: img_depth},
--metrics, {outputPath: metrics},
]
Next in the components main python script, we parse this argument with argparse:
PARSER.add_argument('--metrics',
type=Metrics,
required=False,
help='evaluation metrics output')
and pass it to the components main function:
if __name__ == '__main__':
ARGS = PARSER.parse_args()
evaluation(gcs_test_data_path=ARGS.gcs_test_data_path,
gcs_model_path=ARGS.gcs_model_path,
gcs_output_bucket_id=ARGS.gcs_output_bucket_id,
project_id=ARGS.project_id,
timestamp=ARGS.timestamp,
batch_size=ARGS.batch_size,
img_height=ARGS.img_height,
img_width=ARGS.img_width,
img_depth=ARGS.img_depth,
metrics=ARGS.metrics,
)
in the declaration of the component function, we then typed this metrics parameter as Output[Metrics]
from kfp.v2.dsl import Output, Metrics
def evaluation(gcs_test_data_path: str,
gcs_model_path: str,
gcs_output_bucket_id: str,
metrics: Output[Metrics],
project_id: str,
timestamp: str,
batch_size: int,
img_height: int,
img_width: int,
img_depth: int):
finally, we implement the log_metric method within this evaluation function:
metrics.log_metric('accuracy', acc)
metrics.log_metric('precision', prec)
metrics.log_metric('recall', recall)
metrics.log_metric('f1-score', f_1)
When we run this pipeline, we can see this metric artifact materialised in the DAG:
And Metrics Artifacts are listed in the Metadata UI in Vertex:
However, clicking through to view the artifacts JSON, there is no Metadata listed:
In addition, No Metadata is visible when comparing runs in the pipeline UI:
Finally, navigating to the Objects URI in GCS, we are met with 'Requested entity was not found.', which I assume indicates that nothing was written to GCS:
Are we doing something wrong with this implementation of metrics in the reusable components? From what I can tell, this all seems right to me, but it's hard to tell given the docs at this point seem to focus primarily on examples with Python Function based components.
Do we perhaps need to proactively write this Metrics object to an OutputPath?
Any helps is appreciated.
----- UPDATE ----
I have since been able to get artifact metadata and URI To update. In the end we used kfp sdk to generate a yaml file based on a #component decorated python function, we then adapted this format for our reusable components.
Our component.yaml now looks like this:
name: predict
description: Prepare and create predictions request
implementation:
container:
args:
- --executor_input
- executorInput: null
- --function_to_execute
- predict
command:
- python3
- -m
- kfp.v2.components.executor_main
- --component_module_path
- predict.py
image: gcr.io/PROJECT_ID/kfp/components/predict:latest
inputs:
- name: input_1
type: String
- name: intput_2
type: String
outputs:
- name: output_1
type: Dataset
- name: output_2
type: Dataset
with this change to the yaml, we can now successfully update the artifacts metadata dictionary, and uri through artifact.path = '/path/to/file'. These updates are displayed in the Vertex UI.
I am still unsure why the component.yaml format specified in the Kubeflow documentation does not work - I think this may be a bug with Vertex Pipelines.
As I can see in the code you are running, everything should work without a problem; but, as you commented, I would recommend you to write the metrics object into a path so that it can reach somewhere within your project.

How to configure OpenTelemetry agent for an Akka application

I am trying to export metrics and traces from my Akka app written in Scala using OpenTelemetry agent with the purpose of consuming the data in OpenSearch.
Technology stack for my application:
Akka - 2.6.*
RabbitMQ (amqp client 5.12.*)
PostgreSQL (jdbc 42.2.*)
I've added OpenTelemetry instrumentation runtime dependency to build.sbt:
val runtimeDependencies: Seq[ModuleID] = Seq(
"io.opentelemetry.instrumentation" % "opentelemetry-instrumentation-api" % otelInstrumentationVersion % "runtime"
)
...
libraryDependencies ++= compileDependencies ++ testDependencies ++ runtimeDependencies,
I am passing OpenTelemetry configurations in a properties file:
export JAVA_OPTS="... \
-javaagent:lib/opentelemetry/opentelemetry-javaagent-all-v1.6.0.jar \
-Dotel.javaagent.configuration-file=lib/opentelemetry/otel.properties"
The only other related piece in my code is the properties file:
otel.service.name=my-app
otel.traces.exporter=jaeger
otel.propagators=jaeger
I do receive some traces in OpenSearch, but they are disparate and unrelated whereas I would expect them to be linked. For example a message is received on RabbitMQ topic, it makes it's way into an actor, the latter eventually issues a SQL query. As a result I could see for each execution how much time did each step take.
This is an approximate view that I get in OpenSearch:
I would love to be able to follow documentation, but I find that OpenTelemetry's configuration guide is scarce at this point.
Update:
Not sure whether this is relevant, but I get a warning on datapreper:
2021-09-29T16:50:50,861 [raw-pipeline-prepper-worker-5-thread-1] WARN com.amazon.dataprepper.plugins.prepper.oteltrace.OTelTraceRawPrepper - Missing trace group for SpanId: 922097e31cf96c72
Ok so I got around by running across this issue and then reading about how to surpress specific instrumentations.
So to reduce clutter in tracing dashboard, one would add something as following to the properties file (or equivalent via environment variables):
otel.instrumentation.rabbitmq.enabled=false
otel.instrumentation.grpc.enabled=false
Note that I removed the two cluttering instrumentation libraries peculiar for my use case. For another application one wold choose other libraries from link # 2 above. In this way the spans that you as application developer declare will become roots.

GWT application crawler error undefined.cache.js

I have a GWT application http://islamart.tn which fails on google crawling :
The 'fetch as google' feature fails with a 'partial' status saying that it can't find undefined.cache.js
After some research, I found that this js is the app js when the user.agent is not recognized
I therefore changed my
UserAgentPropertyGenerator.UserAgent
enum value for gecko to recognize google bot:
gecko1_8("return (ua.indexOf('Googlebot') || ua.indexOf('gecko') != -1 || docMode >= 11);");
In my core GWT module I naturally added the line :
<property-provider name="user.agent" generator="fr.onevu.vume.client.common.UserAgentPropertyGenerator"/>
I installed 'Chrome UA spoofer" to emulate the Googlebot user.agent request, and what happened is that now I have a warning at startup saying that the runtime value safari is different than the compile time gecko_18
I still see some checking runtime code in the generated js
{$stackDepth_0=stackIndex_0-1;return 'gecko1_8'}$stackDepth_0=stackIndex_0-1;return 'unknown'}
but those files are very large, and I don't know from which classes they are generated.
Additionally, I had to fall back to the version 2.6.1 since compilation with 2.8.1RC1 and 2.7.0 don't finish the job (for some reason I don't have the time to investigate now)
Any ideas please?...
I need an answer to one of these questions :
How to personalize the runtime user agent check generated code ?
How to make googlebot use the gecko_18 version of my app ?

libPusher pod issues - Disconnection during channel subscription

I'm using the libPusher pod in a Ruby Motion project but running into an issue where my code works when used in the REPL but not in the app itself.
When I try this code in a viewDidAppear method it connects successfully and then disconnects during the channel subscription call.
When I try it in the console, it connects and subscribes perfectly. (same code)
I'm trying to figure out:
Why this is happening
What should I change to alleviate the issue?
I'm using v 1.5 of the pod v2.31 of Ruby Motion
For reference, I'm also using ProMotion framework but I doubt that has anything to do with the issue.
Here's my code:
client = PTPusher.pusherWithKey("my_pusher_key_here", delegate:self, encrypted:true)
client.connect
channel = client.subscribeToChannelNamed("test_channel_1")
channel.bindToEventNamed('status', target: self, action: 'test_method:')
Well I got it working by separating the connection and subscription calls into separate lifecycle methods.
I put:
client = PTPusher.pusherWithKey("my_pusher_key_here", delegate:self, encrypted:true)
client.connect
into the viewDidLoad method
and:
channel = client.subscribeToChannelNamed("test_channel_1")
channel.bindToEventNamed('status', target: self, action: 'test_method:')
into the viewDidAppear method.
I can't say I know exactly why this worked but I assume it has to do with the time between the calls. The connection process must need a little time to complete.

How to determine which packages are missing when running a Windows service on a Elastic Beanstalk instance?

I originally posted this question asking about logging due to an unexplained error. I have now found the log info and have made a small amount of progress with the error. I am re-writing the question to be more specific to the error.
I am trying to run a .NET (4.0) worker process (reads from an SQS queue and writes the results to an RDS database) on AWS "Elastic Beanstalk". To deploy a worker like this, it has to be built as a Windows service (see previous question: Deploying a .NET worker app with Elastic Beanstalk ). My Windows service starts a new thread which wraps my main processing loop. This works fine on my Win7 PC.
Deployment to Elastic Beanstalk (Win Server 2013) appears to be working fine, but as soon as the service hits my thread method, I get a FileNotFoundException. This was puzzling because the exception appeared to occur as soon as it hit my MainProcessingMethod() and before any diagnostics could be produced. After a bit of web searching, I found that missing packages & assemblies in Windows services can produce a FileNotFoundException, and often without any information as to what the missing assembly is.
I believe I have confirmed this. The following processing method that only consists of diagnostics:
public void MainProcessingMethod()
{
EmailSender.SendExceptionEmail("Main started", null, new Exception("main started"));
EventLog.WriteEntry("WebPlagiarismService", "MainProcessingMethod running", EventLogEntryType.Information);
EmailSender.SendExceptionEmail("Main finishing", null, new Exception("main finished"));
}
Produces the expected diagnostics (two emails and an EventLog entry) and no FileNotFoundException (the exception in the email method is just an dummy object- my email method is intended to automatically email exceptions to my mailbox).
This confirms the missing assembly/package hypothesis - something in my commented code is using a package that is missing. How can I determine what?
How can I determine what assemblies&packages are present?
My application does include quite a few DLLs but it looks like these are being found - the above email method is defined in one of the DLLs.
Debug mode does not add any further information. Here's the exception / stack: (app renamed to MyTestService)
Analysis symbol:
Rechecking for solution: 0
Report Id: 51a8153f-3d92-11e3-9426-22000aeb1e73
Report Status: 4
Hashed bucket:
2013-10-25T16:27:20.000Z Error 100:Application Crashing Events Application Error - Faulting application name: MyTestService.exe, version: 1.0.0.0, time stamp: 0x526a97a6
Faulting module name: KERNELBASE.dll, version: 6.2.9200.16451, time stamp: 0x50988aa6
Exception code: 0xe0434352
Fault offset: 0x000000000003811c
Faulting process id: 0x76c
Faulting application start time: 0x01ced19f12e04665
Faulting application path: c:\Data\TestApp\MyTestService.exe
Faulting module path: C:\Windows\system32\KERNELBASE.dll
Report Id: 51a8153f-3d92-11e3-9426-22000aeb1e73
Faulting package full name:
Faulting package-relative application ID:
2013-10-25T16:27:19.000Z Error 0:(0) .NET Runtime - Application: MyTestService.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
Stack:
at MyTestService.MyTestService.MainProcessingMethod()
at
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()
I am also seeing errors 'Deployment package did not contain an iisApp' which makes sense as this is just a service and not a true web app (I see something similar with my Python worker app)
The trick is to add a wrapper method, and enclose the main processing method with a try...catch. Then this catches the assembly load at the beginning of the main processing method, e.g.:
try
{
MainProcessingMethod_internal();
}
catch (Exception e)
{
EmailSender.SendExceptionEmail("Main_intern", null, e);
}
Note that I am using my existing exception email method.
And the result? It is the AWSSDK of all things that is missing!
Exception: Could not load file or assembly 'AWSSDK, Version=1.5.36.0, Culture=neutral, PublicKeyToken=9f476d3089b52be3' or one of its dependencies. The system cannot find the file specified.
at WebPlagiarismService.WebPlagiarismService.MainProcessingMethod_intern()
at WebPlagiarismService.WebPlagiarismService.MainProcessingMethod()
Source: WebPlagiarismService
Target: Void MainProcessingMethod_internal()