From 5ed457078847d6927728e27f9a8e2e53945b0925 Mon Sep 17 00:00:00 2001 From: deleteLater Date: Thu, 8 Feb 2024 01:33:40 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=F0=9F=A7=B9=20refactor:=20unify=20otel?= =?UTF-8?q?=20configuration=20environment=20variables=20(#588)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * unify otel configuration environment variables * remove unused settings * fix * revert wrong change * fix * fix * use grpc by default * use trace filter * update script --- infra/otel/env/otel-api.env | 27 ++++++++++++-------- infra/otel/env/otel-das.env | 22 +++++++++------- infra/otel/env/otel-els.env | 27 ++++++++++++-------- infra/otel/otel-collector-config.yml | 26 +++---------------- infra/otel/utils/otel-env-vars.ps1 | 3 ++- modules/back-end/src/Api/Api.csproj | 1 + modules/data-analytics/gunicorn.conf.py | 2 +- modules/evaluation-server/src/Api/Api.csproj | 2 ++ 8 files changed, 57 insertions(+), 53 deletions(-) diff --git a/infra/otel/env/otel-api.env b/infra/otel/env/otel-api.env index a8a594fce..9e50ad43c 100644 --- a/infra/otel/env/otel-api.env +++ b/infra/otel/env/otel-api.env @@ -1,6 +1,10 @@ +# Tells our app that the OpenTelemetry is enabled ENABLE_OPENTELEMETRY=true -# OpenTelemetry .NET Automatic Instrumentation +# OpenTelemetry .NET Automatic Instrumentation environment variables +# The following environment variables are the most commonly used ones +# For the full list of supported environment variables, please refer to the documentation at +# https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/blob/main/docs/config.md CORECLR_ENABLE_PROFILING="1" CORECLR_PROFILER='{918728DD-259F-4A6A-AC2B-B85E1B658318}' CORECLR_PROFILER_PATH="/app/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so" @@ -8,17 +12,20 @@ DOTNET_ADDITIONAL_DEPS="/app/AdditionalDeps" DOTNET_SHARED_STORE="/app/store" DOTNET_STARTUP_HOOKS="/app/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll" OTEL_DOTNET_AUTO_HOME="/app" + +OTEL_SERVICE_NAME=featbit-api +OTEL_TRACES_EXPORTER=otlp +OTEL_METRICS_EXPORTER=otlp +OTEL_LOGS_EXPORTER=otlp +OTEL_EXPORTER_OTLP_PROTOCOL=grpc +OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 + # Uncomment the following lines to enable verbose logging of OpenTelemetry itself # OTEL_LOG_LEVEL="debug" # COREHOST_TRACE=1 # COREHOST_TRACEFILE=corehost_verbose_tracing.log -OTEL_SERVICE_NAME=featbit-api -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 -OTEL_EXPORTER_OTLP_ENDPOINT_GRPC=http://otel-collector:4317 -OTEL_EXPORTER_OTLP_ENDPOINT_HTTP=http://otel-collector:4318 -OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED="true" -OTEL_DOTNET_AUTO_METRICS_CONSOLE_EXPORTER_ENABLED="true" -OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED="true" -OTEL_DOTNET_AUTO_TRACES_ADDITIONAL_SOURCES="Api" -OTEL_DOTNET_AUTO_METRICS_ADDITIONAL_SOURCES="Api" +# Uncomment the following lines to enable console exporter for development +# OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED="true" +# OTEL_DOTNET_AUTO_METRICS_CONSOLE_EXPORTER_ENABLED="true" +# OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED="true" diff --git a/infra/otel/env/otel-das.env b/infra/otel/env/otel-das.env index 7f197a9ea..eff8c453b 100644 --- a/infra/otel/env/otel-das.env +++ b/infra/otel/env/otel-das.env @@ -1,15 +1,19 @@ +# Tells our app that the OpenTelemetry is enabled ENABLE_OPENTELEMETRY=true -OTEL_SERVICE_NAME=featbit-das -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 - -OTEL_EXPORTER_OTLP_INSECURE=true - -OTEL_TRACES_EXPORTER=otlp -OTEL_METRICS_EXPORTER=otlp -OTEL_LOGS_EXPORTER=otlp - +# OpenTelemetry Python Automatic Instrumentation environment variables +# The following environment variables are the most commonly used ones +# For the full list of supported environment variables, please refer to the documentation at +# https://opentelemetry-python.readthedocs.io/en/latest/sdk/environment_variables.html OTEL_PYTHON_LOG_CORRELATION=true OTEL_PYTHON_LOG_FORMAT="%(msg)s [span_id=%(span_id)s]" OTEL_PYTHON_LOG_LEVEL=debug OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true + +OTEL_SERVICE_NAME=featbit-das +OTEL_TRACES_EXPORTER=otlp +OTEL_METRICS_EXPORTER=otlp +OTEL_LOGS_EXPORTER=otlp +OTEL_EXPORTER_OTLP_PROTOCOL=grpc +OTEL_EXPORTER_OTLP_INSECURE=true +OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 diff --git a/infra/otel/env/otel-els.env b/infra/otel/env/otel-els.env index da7373aea..d25215857 100644 --- a/infra/otel/env/otel-els.env +++ b/infra/otel/env/otel-els.env @@ -1,6 +1,10 @@ +# Tells our app that the OpenTelemetry is enabled ENABLE_OPENTELEMETRY=true -# OpenTelemetry .NET Automatic Instrumentation +# OpenTelemetry .NET Automatic Instrumentation environment variables +# The following environment variables are the most commonly used ones +# For the full list of supported environment variables, please refer to the documentation at +# https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/blob/main/docs/config.md CORECLR_ENABLE_PROFILING="1" CORECLR_PROFILER='{918728DD-259F-4A6A-AC2B-B85E1B658318}' CORECLR_PROFILER_PATH="/app/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so" @@ -8,17 +12,20 @@ DOTNET_ADDITIONAL_DEPS="/app/AdditionalDeps" DOTNET_SHARED_STORE="/app/store" DOTNET_STARTUP_HOOKS="/app/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll" OTEL_DOTNET_AUTO_HOME="/app" + +OTEL_SERVICE_NAME=featbit-els +OTEL_TRACES_EXPORTER=otlp +OTEL_METRICS_EXPORTER=otlp +OTEL_LOGS_EXPORTER=otlp +OTEL_EXPORTER_OTLP_PROTOCOL=grpc +OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 + # Uncomment the following lines to enable verbose logging of OpenTelemetry itself # OTEL_LOG_LEVEL="debug" # COREHOST_TRACE=1 # COREHOST_TRACEFILE=corehost_verbose_tracing.log -OTEL_SERVICE_NAME=featbit-els -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 -OTEL_EXPORTER_OTLP_ENDPOINT_GRPC=http://otel-collector:4317 -OTEL_EXPORTER_OTLP_ENDPOINT_HTTP=http://otel-collector:4318 -OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED="true" -OTEL_DOTNET_AUTO_METRICS_CONSOLE_EXPORTER_ENABLED="true" -OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED="true" -OTEL_DOTNET_AUTO_TRACES_ADDITIONAL_SOURCES="Api" -OTEL_DOTNET_AUTO_METRICS_ADDITIONAL_SOURCES="Api" +# Uncomment the following lines to enable console exporter for development +# OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED="true" +# OTEL_DOTNET_AUTO_METRICS_CONSOLE_EXPORTER_ENABLED="true" +# OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED="true" diff --git a/infra/otel/otel-collector-config.yml b/infra/otel/otel-collector-config.yml index 3fdc7ec51..ef0303333 100644 --- a/infra/otel/otel-collector-config.yml +++ b/infra/otel/otel-collector-config.yml @@ -36,32 +36,14 @@ processors: - favicon\.ico enabled_regex_matching: true invert_match: true - # use the following to filter out traces from the api service - filter/api: + # exclude traces from otel-collector + filter/trace-denylist: spans: - include: - match_type: strict - services: - - featbit-api exclude: - match_type: regexp + match_type: strict attributes: - key: net.peer.name value: otel-collector - # use the following to filter out traces from the das service - filter/das: - spans: - include: - match_type: strict - services: - - featbit-das - # use the following to filter out traces from the els service - filter/els: - spans: - include: - match_type: strict - services: - - featbit-els exporters: @@ -134,7 +116,7 @@ service: pipelines: traces: receivers: [otlp] - processors: [batch, tail_sampling, attributes/dev] + processors: [batch, tail_sampling, filter/trace-denylist, attributes/dev] exporters: [file/traces, otlp/jaeger] metrics: receivers: [otlp] diff --git a/infra/otel/utils/otel-env-vars.ps1 b/infra/otel/utils/otel-env-vars.ps1 index 3ca563cb0..1e13a3e78 100644 --- a/infra/otel/utils/otel-env-vars.ps1 +++ b/infra/otel/utils/otel-env-vars.ps1 @@ -9,4 +9,5 @@ $ENV:DOTNET_ADDITIONAL_DEPS="$INSTALL_DIR\AdditionalDeps" $ENV:DOTNET_SHARED_STORE="$INSTALL_DIR\store" $ENV:DOTNET_STARTUP_HOOKS="$INSTALL_DIR\net\OpenTelemetry.AutoInstrumentation.StartupHook.dll" $ENV:OTEL_DOTNET_AUTO_HOME="$INSTALL_DIR" -$ENV:OTEL_EXPORTER_OTLP_ENDPOINT_GRPC="http://localhost:4317" \ No newline at end of file +$ENV:OTEL_EXPORTER_OTLP_PROTOCOL="grpc" +$ENV:OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" \ No newline at end of file diff --git a/modules/back-end/src/Api/Api.csproj b/modules/back-end/src/Api/Api.csproj index 3b9b9df86..e8732ad37 100644 --- a/modules/back-end/src/Api/Api.csproj +++ b/modules/back-end/src/Api/Api.csproj @@ -23,6 +23,7 @@ + diff --git a/modules/data-analytics/gunicorn.conf.py b/modules/data-analytics/gunicorn.conf.py index 0a8fe6178..c08df7be9 100644 --- a/modules/data-analytics/gunicorn.conf.py +++ b/modules/data-analytics/gunicorn.conf.py @@ -23,7 +23,7 @@ threads = 4 worker_tmp_dir = os.getenv('GUNICORN_WORKER_TMP_DIR', '/tmp') -otel_endpoint = os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://otel-collector:4318') +otel_endpoint = os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://otel-collector:4317') otel_service_name = os.getenv('OTEL_SERVICE_NAME', 'featbit-das') otel_python_log_level = os.getenv('OTEL_PYTHON_LOG_LEVEL', 'info') otel_log_format = os.getenv('OTEL_PYTHON_LOG_FORMAT', '%(msg)s [span_id=%(span_id)s]') diff --git a/modules/evaluation-server/src/Api/Api.csproj b/modules/evaluation-server/src/Api/Api.csproj index 2fa7403f5..4aff0d328 100644 --- a/modules/evaluation-server/src/Api/Api.csproj +++ b/modules/evaluation-server/src/Api/Api.csproj @@ -9,6 +9,8 @@ + + From 599a09cab3e1c45a84915535ae4b7f198a0fec98 Mon Sep 17 00:00:00 2001 From: deleteLater Date: Thu, 8 Feb 2024 14:37:46 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=93=96=20doc:=20add=20otel=20integr?= =?UTF-8?q?ation=20link=20(#589)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ff8dfc1c6..15ace07af 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,8 @@ FeatBit offers a range of features including: - **[ChatGPT Tech Debt Reduction](https://github.com/featbit/featbit/tree/main/llm)** (experimental features): Utilize ChatGPT4 and FeatBit's VSCode extension to minimize technical debt associated with feature flagging. +- **[OpenTelemetry Integration](https://docs.featbit.co/integrations/observability/opentelemetry)**: Enhance system visibility with OpenTelemetry for logs, traces, and metrics. + - **[Helm Charts Installation](https://github.com/featbit/featbit-charts/)**, FeatBit can be installed on-premises, in the cloud, or in a hybrid environment through Helm Charts. ![featbit-readme-new-2](https://user-images.githubusercontent.com/68597908/211645725-391777fa-b5c0-4a0c-88e9-df9f05af9c61.gif) From 4167b3b29d72727d8525a811cc43b7cb3435a9b8 Mon Sep 17 00:00:00 2001 From: deleteLater Date: Thu, 8 Feb 2024 18:08:26 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20serilog=20otel=20in?= =?UTF-8?q?tegration=20(#590)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/back-end/src/Api/Program.cs | 7 ++++++- modules/evaluation-server/src/Api/Program.cs | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/back-end/src/Api/Program.cs b/modules/back-end/src/Api/Program.cs index 4b611c0d2..44bf73e97 100644 --- a/modules/back-end/src/Api/Program.cs +++ b/modules/back-end/src/Api/Program.cs @@ -39,7 +39,12 @@ void InitializeSerilog() configuration.WriteTo.OpenTelemetry(options => { options.Endpoint = - Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT_GRPC") ?? "http://otel-collector:4317"; + Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://otel-collector:4318"; + options.Protocol = + Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_PROTOCOL") == "grpc" + ? OtlpProtocol.Grpc + : OtlpProtocol.HttpProtobuf; + options.IncludedData = IncludedData.MessageTemplateTextAttribute | IncludedData.TraceIdField | IncludedData.SpanIdField; diff --git a/modules/evaluation-server/src/Api/Program.cs b/modules/evaluation-server/src/Api/Program.cs index c137f853e..844e61e17 100644 --- a/modules/evaluation-server/src/Api/Program.cs +++ b/modules/evaluation-server/src/Api/Program.cs @@ -37,7 +37,11 @@ void InitializeSerilog() configuration.WriteTo.OpenTelemetry(options => { options.Endpoint = - Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT_GRPC") ?? "http://otel-collector:4317"; + Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://otel-collector:4318"; + options.Protocol = + Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_PROTOCOL") == "grpc" + ? OtlpProtocol.Grpc + : OtlpProtocol.HttpProtobuf; options.IncludedData = IncludedData.MessageTemplateTextAttribute | IncludedData.TraceIdField From ff9a9acd8cc865ff2c805064957f38dc0d4059f9 Mon Sep 17 00:00:00 2001 From: rbrennan <128187904+wss-rbrennan@users.noreply.github.com> Date: Fri, 16 Feb 2024 03:03:48 -0500 Subject: [PATCH 04/10] fix date formatting in experimentation to conform with date-fns (#592) --- .../experimentation/experimentation.component.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/front-end/src/app/features/safe/feature-flags/details/experimentation/experimentation.component.ts b/modules/front-end/src/app/features/safe/feature-flags/details/experimentation/experimentation.component.ts index c01122031..508576ee0 100644 --- a/modules/front-end/src/app/features/safe/feature-flags/details/experimentation/experimentation.component.ts +++ b/modules/front-end/src/app/features/safe/feature-flags/details/experimentation/experimentation.component.ts @@ -118,7 +118,7 @@ export class ExperimentationComponent implements OnInit, OnDestroy { expt.selectedIteration = this.processIteration({ ...expt.selectedIteration }, expt.baselineVariation.id); if (iteration.updatedAt) { expt.selectedIteration.updatedAt = iteration.updatedAt; - expt.selectedIteration.updatedAtStr = format(iteration.updatedAt, 'YYYY-MM-DD HH:mm'); + expt.selectedIteration.updatedAtStr = format(iteration.updatedAt, 'yyyy-mm-dd hh:mm'); } // update experiment original iterations @@ -204,7 +204,7 @@ export class ExperimentationComponent implements OnInit, OnDestroy { this.experimentService.stopIteration(expt.id, expt.selectedIteration.id).subscribe(res => { if (res) { expt.selectedIteration.endTime = res.endTime; - expt.selectedIteration.dateTimeInterval = `${format(expt.selectedIteration.startTime, 'YYYY-MM-DD HH:mm')} - ${format(expt.selectedIteration.endTime, 'YYYY-MM-DD HH:mm')}` + expt.selectedIteration.dateTimeInterval = `${format(expt.selectedIteration.startTime, 'yyyy-mm-dd hh:mm')} - ${format(expt.selectedIteration.endTime, 'yyyy-mm-dd hh:mm')}` expt.status = ExperimentStatus.Paused; } @@ -244,7 +244,7 @@ export class ExperimentationComponent implements OnInit, OnDestroy { expt.selectedIteration = this.processIteration({...expt.selectedIteration , ...res[0]}, expt.baselineVariation.id); if (res[0].updatedAt) { expt.selectedIteration.updatedAt = res[0].updatedAt; - expt.selectedIteration.updatedAtStr = format(res[0].updatedAt, 'YYYY-MM-DD HH:mm'); + expt.selectedIteration.updatedAtStr = format(res[0].updatedAt, 'yyyy-mm-dd hh:mm'); } this.setExptStatus(expt, res[0]); @@ -299,10 +299,10 @@ export class ExperimentationComponent implements OnInit, OnDestroy { const winnerVariation = !!iterationResults.find(e => e.isWinner); const nowStr = (iteration.isFinish === true) ? "" : "(" + ($localize `:@@common.now:Now`) + ")"; - const startStr = `${format(iteration.startTime, 'YYYY-MM-DD HH:mm')}`; + const startStr = `${format(iteration.startTime, 'yyyy-mm-dd hh:mm')}`; const endStr = `${iteration.endTime ? - format(iteration.endTime, 'YYYY-MM-DD HH:mm') : - format(new Date(), 'YYYY-MM-DD HH:mm')} ${nowStr}` + format(iteration.endTime, 'yyyy-mm-dd hh:mm') : + format(new Date(), 'yyyy-mm-dd hh:mm')} ${nowStr}` return { ...iteration, @@ -368,7 +368,7 @@ export class ExperimentationComponent implements OnInit, OnDestroy { name: xAxisName, position: 'end', field: 'time', - scale: {type: "timeCat", nice: true, range: [0.05, 0.95], mask: 'YYYY-MM-DD HH:mm'} + scale: {type: "timeCat", nice: true, range: [0.05, 0.95], mask: 'yyyy-mm-dd hh:mm'} }, yAxis: { name: yAxisName, From 56fe4dfec6dc0c6af0d4de95e7e284216a9c59de Mon Sep 17 00:00:00 2001 From: cosmos-explorer <88151306+cosmos-explorer@users.noreply.github.com> Date: Fri, 16 Feb 2024 09:50:55 +0100 Subject: [PATCH 05/10] fix date formatting in remote config UI to conform with date-fns (#593) --- .../safe/data-sync/remote-sync/remote-sync.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/front-end/src/app/features/safe/data-sync/remote-sync/remote-sync.component.ts b/modules/front-end/src/app/features/safe/data-sync/remote-sync/remote-sync.component.ts index a58f8aa45..37355202a 100644 --- a/modules/front-end/src/app/features/safe/data-sync/remote-sync/remote-sync.component.ts +++ b/modules/front-end/src/app/features/safe/data-sync/remote-sync/remote-sync.component.ts @@ -65,7 +65,7 @@ export class RemoteSyncComponent implements OnInit { const success = remark.split(',')[0] === 'true'; const timestamp = remark.split(',')[1]; - const time = format(parseInt(timestamp), 'YYYY-MM-DD HH:mm'); + const time = format(parseInt(timestamp), 'yyyy-mm-dd hh:mm'); return { success, time }; } From 0735aa1a94679e638c10d44295aa8d86f554787d Mon Sep 17 00:00:00 2001 From: Comiscience <68597908+cosmic-flood@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:32:25 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=F0=9F=93=96=20doc:=20add=20LinkedIn=20li?= =?UTF-8?q?nk=20(#596)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 70 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 15ace07af..2750c0942 100644 --- a/README.md +++ b/README.md @@ -3,35 +3,55 @@
-🙏 If you are using FeatBit, we have launched the [**FeatBit Usage Survey**](https://forms.gle/gZT715wE9aMPpoBw8). It would be greatly appreciated and incredibly helpful if you could take the time to fill it out (5 questions). ## Try FeatBit Online @@ -117,6 +137,8 @@ The above sections show you how to get up and running quickly and easily. When y [Join our Online Slack Support & Community](https://join.slack.com/t/featbit/shared_invite/zt-1ew5e2vbb-x6Apan1xZOaYMnFzqZkGNQ) +[Connect with FeatBit on LinkedIn](https://www.linkedin.com/company/featbit) + Email us at [contact@featbit.co](mailto:contact@featbit.co) if Slack isn't your thing. [Official Website](https://www.featbit.co) From 596f66c67a39f544b2f7bab1d9cc171e541cf773 Mon Sep 17 00:00:00 2001 From: qixiaojian310 <62613977+qixiaojian310@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:46:40 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=90=9B=20Fix:=20While=20editing=20a?= =?UTF-8?q?=20flag=20rule,=20when=20some=20operation=20(is=20one=20of,=20n?= =?UTF-8?q?ot=20one=20of=20etc.)=20is=20selected,=20property=20cannot=20be?= =?UTF-8?q?=20selected.=20(#583)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: When operation is selected, property cannot be selected. * small changes --------- Co-authored-by: cosmos-explorer --- .../find-rule/rule/rule.component.ts | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts b/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts index 15fc416fe..3e0f228d2 100644 --- a/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts +++ b/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts @@ -58,30 +58,47 @@ export class RuleComponent { get currentUserProp(): IUserProp { const userProp = this.userProps.find(prop => prop.name === this.condition.property); - // adapt to existing value that preset values don't contain - if (userProp.usePresetValuesOnly) { - if (this.condition.value && userProp.presetValues.findIndex(x => x.value === this.condition.value) === -1) { - userProp.presetValues.push({ - id: '', - value: this.condition.value, - description: this.condition.value - }) + if(!userProp) { + const newProp: IUserProp = { + id: uuidv4(), + name: "", + presetValues: [], + isBuiltIn: false, + usePresetValuesOnly: false, + isDigestField: false, + remark: '', + isNew: true } - - if (this.condition.multipleValue) { - this.condition.multipleValue.forEach(value => { - if (userProp.presetValues.findIndex(x => x.value === value) === -1) { - userProp.presetValues.push({ - id: '', - value: value, - description: value - }) - } - }); + + return newProp; + }else{ + // adapt to existing value that preset values don't contain + if (userProp.usePresetValuesOnly) { + if (this.condition.value && userProp.presetValues.findIndex(x => x.value === this.condition.value) === -1) { + userProp.presetValues.push({ + id: '', + value: this.condition.value, + description: this.condition.value + }) + } + + if (this.condition.multipleValue) { + this.condition.multipleValue.forEach(value => { + if (userProp.presetValues.findIndex(x => x.value === value) === -1) { + userProp.presetValues.push({ + id: '', + value: value, + description: value + }) + } + }); + } } + + return userProp; } - return userProp; + } get multiSelectMode(): 'multiple' | 'tags' { return this.currentUserProp.usePresetValuesOnly ? 'multiple' : 'tags'; From bf917b1696ec6d4973fb82acc6eb7cf27875c851 Mon Sep 17 00:00:00 2001 From: s2002a <38680131+dsun0720@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:33:01 +0100 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20da-server=20otel=20?= =?UTF-8?q?integration=20(#595)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix otel in das server * add logs to record request path * clean code * optimize api and els dockerfile * clean up * fix * clean up da server Dockerfile * fix metric collection error * use latest image --------- Co-authored-by: deleteLater --- .gitignore | 5 +- .../docker-compose-otel-collector-contrib.yml | 13 +- docker/composes/docker-compose-otel.yml | 16 ++- infra/otel/env/otel-api.env | 31 ----- infra/otel/env/otel-das.env | 19 --- infra/otel/env/otel-els.env | 31 ----- infra/otel/otel-collector-config.yml | 9 +- modules/back-end/deploy/Dockerfile | 38 ++++-- modules/back-end/start.sh | 37 ++++++ modules/data-analytics/.dockerignore | 3 +- modules/data-analytics/.vscode/launch.json | 2 +- modules/data-analytics/.vscode/settings.json | 5 +- modules/data-analytics/Dockerfile | 114 ++++++------------ modules/data-analytics/README.md | 2 + modules/data-analytics/app/commands.py | 1 - .../app/experimentation/views.py | 1 + modules/data-analytics/app/health/__init__.py | 2 +- modules/data-analytics/app/health/views.py | 2 + modules/data-analytics/app/main/views.py | 3 + modules/data-analytics/app/setting.py | 2 + modules/data-analytics/gunicorn.conf.py | 91 ++++++-------- modules/data-analytics/requirements.txt | 9 +- modules/data-analytics/start.bat | 7 -- modules/data-analytics/start.sh | 33 ++++- modules/evaluation-server/deploy/Dockerfile | 38 ++++-- modules/evaluation-server/start.sh | 37 ++++++ 26 files changed, 289 insertions(+), 262 deletions(-) delete mode 100644 infra/otel/env/otel-api.env delete mode 100644 infra/otel/env/otel-das.env delete mode 100644 infra/otel/env/otel-els.env create mode 100644 modules/back-end/start.sh delete mode 100644 modules/data-analytics/start.bat create mode 100644 modules/evaluation-server/start.sh diff --git a/.gitignore b/.gitignore index a533b5c1e..4a5483aed 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,7 @@ benchmark/k6-scripts/test-results/ /.vs/featbit/v17/.wsuo #Ignore dev logs -.logs/ \ No newline at end of file +.logs/ + +#Ignore IntelliJ IDEA files +.idea/ \ No newline at end of file diff --git a/docker/composes/docker-compose-otel-collector-contrib.yml b/docker/composes/docker-compose-otel-collector-contrib.yml index 9e07045ee..1bfb4e73f 100644 --- a/docker/composes/docker-compose-otel-collector-contrib.yml +++ b/docker/composes/docker-compose-otel-collector-contrib.yml @@ -2,7 +2,7 @@ name: featbit-otel-collector version: "3" services: otel-collector: - image: otel/opentelemetry-collector-contrib + image: otel/opentelemetry-collector-contrib:latest container_name: otel-collector volumes: - ./infra/otel/otel-collector-config.yml:/etc/otelcol-contrib/config.yaml @@ -25,7 +25,7 @@ services: seq: condition: service_started jaeger: - image: jaegertracing/all-in-one:1.46.0 + image: jaegertracing/all-in-one:latest container_name: jaeger environment: - COLLECTOR_OTLP_ENABLED=true @@ -38,10 +38,11 @@ services: - "14250" prometheus: - image: prom/prometheus:v2.42.0 + image: prom/prometheus:latest container_name: prometheus volumes: - ./infra/otel/prometheus.yml:/etc/prometheus/prometheus.yml + - prometheus:/prometheus networks: - featbit-network ports: @@ -54,6 +55,8 @@ services: ports: - 8082:80 - 5341:5341 + volumes: + - seq:/data environment: - ACCEPT_EULA=Y networks: @@ -63,3 +66,7 @@ networks: ipam: config: - subnet: 172.10.0.0/16 + +volumes: + prometheus: + seq: \ No newline at end of file diff --git a/docker/composes/docker-compose-otel.yml b/docker/composes/docker-compose-otel.yml index 1abfc69b8..51962db47 100644 --- a/docker/composes/docker-compose-otel.yml +++ b/docker/composes/docker-compose-otel.yml @@ -27,8 +27,9 @@ services: dockerfile: ./deploy/Dockerfile environment: - SSOEnabled=true - env_file: - - ./infra/otel/env/otel-api.env + - ENABLE_OPENTELEMETRY=true + - OTEL_SERVICE_NAME=featbit-api + - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 depends_on: - mongodb - redis @@ -47,8 +48,10 @@ services: depends_on: - mongodb - redis - env_file: - - ./infra/otel/env/otel-els.env + environment: + - ENABLE_OPENTELEMETRY=true + - OTEL_SERVICE_NAME=featbit-els + - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 ports: - "5100:5100" networks: @@ -73,8 +76,9 @@ services: MONGO_URI: mongodb://admin:password@mongodb:27017 MONGO_INITDB_DATABASE: featbit MONGO_HOST: mongodb - env_file: - - ./infra/otel/env/otel-das.env + ENABLE_OPENTELEMETRY: true + OTEL_SERVICE_NAME: featbit-das + OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4317 mongodb: image: mongo:5.0.14 diff --git a/infra/otel/env/otel-api.env b/infra/otel/env/otel-api.env deleted file mode 100644 index 9e50ad43c..000000000 --- a/infra/otel/env/otel-api.env +++ /dev/null @@ -1,31 +0,0 @@ -# Tells our app that the OpenTelemetry is enabled -ENABLE_OPENTELEMETRY=true - -# OpenTelemetry .NET Automatic Instrumentation environment variables -# The following environment variables are the most commonly used ones -# For the full list of supported environment variables, please refer to the documentation at -# https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/blob/main/docs/config.md -CORECLR_ENABLE_PROFILING="1" -CORECLR_PROFILER='{918728DD-259F-4A6A-AC2B-B85E1B658318}' -CORECLR_PROFILER_PATH="/app/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so" -DOTNET_ADDITIONAL_DEPS="/app/AdditionalDeps" -DOTNET_SHARED_STORE="/app/store" -DOTNET_STARTUP_HOOKS="/app/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll" -OTEL_DOTNET_AUTO_HOME="/app" - -OTEL_SERVICE_NAME=featbit-api -OTEL_TRACES_EXPORTER=otlp -OTEL_METRICS_EXPORTER=otlp -OTEL_LOGS_EXPORTER=otlp -OTEL_EXPORTER_OTLP_PROTOCOL=grpc -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 - -# Uncomment the following lines to enable verbose logging of OpenTelemetry itself -# OTEL_LOG_LEVEL="debug" -# COREHOST_TRACE=1 -# COREHOST_TRACEFILE=corehost_verbose_tracing.log - -# Uncomment the following lines to enable console exporter for development -# OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED="true" -# OTEL_DOTNET_AUTO_METRICS_CONSOLE_EXPORTER_ENABLED="true" -# OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED="true" diff --git a/infra/otel/env/otel-das.env b/infra/otel/env/otel-das.env deleted file mode 100644 index eff8c453b..000000000 --- a/infra/otel/env/otel-das.env +++ /dev/null @@ -1,19 +0,0 @@ -# Tells our app that the OpenTelemetry is enabled -ENABLE_OPENTELEMETRY=true - -# OpenTelemetry Python Automatic Instrumentation environment variables -# The following environment variables are the most commonly used ones -# For the full list of supported environment variables, please refer to the documentation at -# https://opentelemetry-python.readthedocs.io/en/latest/sdk/environment_variables.html -OTEL_PYTHON_LOG_CORRELATION=true -OTEL_PYTHON_LOG_FORMAT="%(msg)s [span_id=%(span_id)s]" -OTEL_PYTHON_LOG_LEVEL=debug -OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true - -OTEL_SERVICE_NAME=featbit-das -OTEL_TRACES_EXPORTER=otlp -OTEL_METRICS_EXPORTER=otlp -OTEL_LOGS_EXPORTER=otlp -OTEL_EXPORTER_OTLP_PROTOCOL=grpc -OTEL_EXPORTER_OTLP_INSECURE=true -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 diff --git a/infra/otel/env/otel-els.env b/infra/otel/env/otel-els.env deleted file mode 100644 index d25215857..000000000 --- a/infra/otel/env/otel-els.env +++ /dev/null @@ -1,31 +0,0 @@ -# Tells our app that the OpenTelemetry is enabled -ENABLE_OPENTELEMETRY=true - -# OpenTelemetry .NET Automatic Instrumentation environment variables -# The following environment variables are the most commonly used ones -# For the full list of supported environment variables, please refer to the documentation at -# https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/blob/main/docs/config.md -CORECLR_ENABLE_PROFILING="1" -CORECLR_PROFILER='{918728DD-259F-4A6A-AC2B-B85E1B658318}' -CORECLR_PROFILER_PATH="/app/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so" -DOTNET_ADDITIONAL_DEPS="/app/AdditionalDeps" -DOTNET_SHARED_STORE="/app/store" -DOTNET_STARTUP_HOOKS="/app/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll" -OTEL_DOTNET_AUTO_HOME="/app" - -OTEL_SERVICE_NAME=featbit-els -OTEL_TRACES_EXPORTER=otlp -OTEL_METRICS_EXPORTER=otlp -OTEL_LOGS_EXPORTER=otlp -OTEL_EXPORTER_OTLP_PROTOCOL=grpc -OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 - -# Uncomment the following lines to enable verbose logging of OpenTelemetry itself -# OTEL_LOG_LEVEL="debug" -# COREHOST_TRACE=1 -# COREHOST_TRACEFILE=corehost_verbose_tracing.log - -# Uncomment the following lines to enable console exporter for development -# OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED="true" -# OTEL_DOTNET_AUTO_METRICS_CONSOLE_EXPORTER_ENABLED="true" -# OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED="true" diff --git a/infra/otel/otel-collector-config.yml b/infra/otel/otel-collector-config.yml index ef0303333..049078778 100644 --- a/infra/otel/otel-collector-config.yml +++ b/infra/otel/otel-collector-config.yml @@ -44,6 +44,13 @@ processors: attributes: - key: net.peer.name value: otel-collector + # temporary measure until description is fixed in Python + # see: https://github.com/open-telemetry/opentelemetry-demo/pull/738 + transform: + metric_statements: + - context: metric + statements: + - set(description, "Measures the duration of inbound HTTP requests") where name == "http.server.duration" exporters: @@ -120,7 +127,7 @@ service: exporters: [file/traces, otlp/jaeger] metrics: receivers: [otlp] - processors: [batch, attributes/dev] + processors: [batch, transform, attributes/dev] exporters: [file/metrics, prometheus] logs: receivers: [otlp] diff --git a/modules/back-end/deploy/Dockerfile b/modules/back-end/deploy/Dockerfile index aed4adb5b..e3629bc37 100644 --- a/modules/back-end/deploy/Dockerfile +++ b/modules/back-end/deploy/Dockerfile @@ -1,5 +1,7 @@ # build stage # https://hub.docker.com/_/microsoft-dotnet +ARG INSTALL_DIR=/app + FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /source @@ -22,27 +24,49 @@ RUN dotnet build -c Release --no-restore && dotnet test # publish stage FROM build AS publish +ARG INSTALL_DIR WORKDIR /source/src/Api -RUN dotnet publish -c Release --no-build -o /app +RUN dotnet publish -c Release --no-build -o $INSTALL_DIR # final stage/image FROM mcr.microsoft.com/dotnet/aspnet:6.0 RUN apt-get update && apt-get install -y curl unzip && rm -rf /var/lib/apt/lists/* +ARG INSTALL_DIR ARG OTEL_VERSION=1.1.0 + +# ensure we listen on any IP Address +ENV ASPNETCORE_URLS=http://*:5000 \ + INSTALL_DIR=$INSTALL_DIR \ + DOTNET_ADDITIONAL_DEPS=$INSTALL_DIR/AdditionalDeps \ + DOTNET_SHARED_STORE=$INSTALL_DIR/store \ + ENABLE_OPENTELEMETRY=false \ + OTEL_DOTNET_AUTO_HOME=$INSTALL_DIR \ + OTEL_SERVICE_NAME=featbit-els \ + OTEL_TRACES_EXPORTER=otlp \ + OTEL_METRICS_EXPORTER=otlp \ + OTEL_LOGS_EXPORTER=otlp \ + OTEL_EXPORTER_OTLP_ENDPOINT=http://locahost:4317 \ + OTEL_EXPORTER_OTLP_PROTOCOL=grpc \ + OTEL_EXPORTER_OTLP_INSECURE=true + ADD https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/v${OTEL_VERSION}/otel-dotnet-auto-install.sh otel-dotnet-auto-install.sh RUN chmod +x otel-dotnet-auto-install.sh -RUN export OTEL_DOTNET_AUTO_HOME="/app" && ./otel-dotnet-auto-install.sh +RUN ./otel-dotnet-auto-install.sh -WORKDIR /app -COPY --from=publish /app ./ -# ensure we listen on any IP Address -ENV ASPNETCORE_URLS=http://*:5000 +# temporal workaround for Automatic Instrumentation in ARM arch +RUN mkdir -p $DOTNET_SHARED_STORE/arm64 && \ + cp -a $DOTNET_SHARED_STORE/x64/. $DOTNET_SHARED_STORE/arm64 + +WORKDIR $INSTALL_DIR +COPY --from=publish $INSTALL_DIR ./ +COPY --from=build /source/start.sh ./start.sh +RUN chmod +x ./start.sh EXPOSE 5000 # health check HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD curl --fail --silent http://localhost:5000/health/liveness || exit 1 -ENTRYPOINT ["dotnet", "Api.dll"] \ No newline at end of file +ENTRYPOINT ["./start.sh"] \ No newline at end of file diff --git a/modules/back-end/start.sh b/modules/back-end/start.sh new file mode 100644 index 000000000..87b44fa49 --- /dev/null +++ b/modules/back-end/start.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + +ARCH=$(uname -m) + +if [ "$ENABLE_OPENTELEMETRY" = "true" ]; then + if [ "$OTEL_TRACES_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_TRACES_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_TRACES_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + + if [ "$OTEL_METRICS_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_METRICS_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_METRICS_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + + if [ "$OTEL_LOGS_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_LOGS_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_LOGS_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + export DOTNET_STARTUP_HOOKS="$INSTALL_DIR/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll" + if [ "$ARCH" = "arm64" ]; then + export CORECLR_ENABLE_PROFILING="0" + else + export CORECLR_ENABLE_PROFILING="1" + export CORECLR_PROFILER="{918728DD-259F-4A6A-AC2B-B85E1B658318}" + export CORECLR_PROFILER_PATH="$INSTALL_DIR/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so" + fi +fi + +dotnet Api.dll diff --git a/modules/data-analytics/.dockerignore b/modules/data-analytics/.dockerignore index 0fa0d0976..174297aec 100644 --- a/modules/data-analytics/.dockerignore +++ b/modules/data-analytics/.dockerignore @@ -1,6 +1,5 @@ * !app -!integration_tests !utils !.env !flasky.py @@ -10,4 +9,4 @@ !supervisord.conf !nginx.conf !docker-entrypoint.sh -!wait-for-it.sh \ No newline at end of file +!wait-for-it.sh diff --git a/modules/data-analytics/.vscode/launch.json b/modules/data-analytics/.vscode/launch.json index 50f31dcc2..82f9e4d52 100644 --- a/modules/data-analytics/.vscode/launch.json +++ b/modules/data-analytics/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { "name": "Python: current file", - "type": "python", + "type": "debugpy", "request": "launch", "program": "${file}", "console": "integratedTerminal", diff --git a/modules/data-analytics/.vscode/settings.json b/modules/data-analytics/.vscode/settings.json index ae153c235..64dd62b29 100644 --- a/modules/data-analytics/.vscode/settings.json +++ b/modules/data-analytics/.vscode/settings.json @@ -21,5 +21,8 @@ ".vscode test": true }, "python.analysis.typeCheckingMode": "basic", - "editor.formatOnSave": true + "editor.formatOnSave": true, + "[python]": { + "editor.defaultFormatter": "ms-python.autopep8" + } } \ No newline at end of file diff --git a/modules/data-analytics/Dockerfile b/modules/data-analytics/Dockerfile index fff76090e..c7fec0088 100644 --- a/modules/data-analytics/Dockerfile +++ b/modules/data-analytics/Dockerfile @@ -1,86 +1,50 @@ FROM python:3.9-slim-buster -ARG KAFKA_HOSTS=kafka:9092 -ARG KAFKA_SECURITY_PROTOCOL=PLAINTEXT -ARG KAFKA_SASL_MECHANISM= -ARG KAFKA_SASL_USER= -ARG KAFKA_SASL_PASSWORD= -ARG CLICKHOUSE_HOST=clickhouse-server -ARG CLICKHOUSE_ALT_HOST= -ARG CLICKHOUSE_PORT=9000 -ARG CLICKHOUSE_HTTP_PORT=8123 -ARG CLICKHOUSE_KAFKA_HOSTS=kafka:9092 -ARG CLICKHOUSE_USER=default -ARG CLICKHOUSE_PASSWORD= -ARG CLICKHOUSE_DATABASE=featbit -ARG CLICKHOUSE_CLUSTER=featbit_ch_cluster -ARG CLICKHOUSE_REPLICATION=true -ARG CLICKHOUSE_SECURE=false -ARG CLICKHOUSE_VERIFY=true -ARG TEST=false -ARG SUFFIX= -ARG CACHE_TYPE=RedisCache -ARG REDIS_USER= -ARG REDIS_PASSWORD= -ARG REDIS_DB=0 -ARG REDIS_SSL=false -ARG REDIS_HOST=localhost -ARG REDIS_PORT=6379 -ARG REDIS_CLUSTER_HOST_PORT_PAIRS=localhost:6379 -ARG REDIS_SENTINEL_HOST_PORT_PAIRS=localhost:26379 -ARG REDIS_SENTINEL_PASSWORD= -ARG REDIS_SENTINEL_MASTER_SET=mymaster -ARG MONGO_HOST=mongodb -ARG MONGO_PORT=27017 -ARG MONGO_URI=mongodb://admin:password@mongodb:27017 -ARG MONGO_INITDB_DATABASE=featbit -ARG IS_PRO=false -ARG CHECK_DB_LIVNESS=true -ENV KAFKA_HOSTS=${KAFKA_HOSTS} \ - KAFKA_SECURITY_PROTOCOL=${KAFKA_SECURITY_PROTOCOL} \ - KAFKA_SASL_MECHANISM=${KAFKA_SASL_MECHANISM} \ - KAFKA_SASL_USER=${KAFKA_SASL_USER} \ - KAFKA_SASL_PASSWORD=${KAFKA_SASL_PASSWORD} \ - CLICKHOUSE_USER=${CLICKHOUSE_USER} \ - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD} \ - CLICKHOUSE_HOST=${CLICKHOUSE_HOST} \ - CLICKHOUSE_ALT_HOST=${CLICKHOUSE_ALT_HOST} \ - CLICKHOUSE_PORT=${CLICKHOUSE_PORT} \ - CLICKHOUSE_HTTP_PORT=${CLICKHOUSE_HTTP_PORT} \ - CLICKHOUSE_KAFKA_HOSTS=${CLICKHOUSE_KAFKA_HOSTS} \ - CLICKHOUSE_DATABASE=${CLICKHOUSE_DATABASE} \ - CLICKHOUSE_CLUSTER=${CLICKHOUSE_CLUSTER} \ - CLICKHOUSE_REPLICATION=${CLICKHOUSE_REPLICATION} \ - CLICKHOUSE_SECURE=${CLICKHOUSE_SECURE} \ - CLICKHOUSE_VERIFY=${CLICKHOUSE_VERIFY} \ - CACHE_TYPE=${CACHE_TYPE} \ - REDIS_USER=${REDIS_USER} \ - REDIS_PASSWORD=${REDIS_PASSWORD} \ - REDIS_DB=${REDIS_DB} \ - REDIS_SSL=${REDIS_SSL} \ - REDIS_HOST=${REDIS_HOST} \ - REDIS_PORT=${REDIS_PORT} \ - REDIS_CLUSTER_HOST_PORT_PAIRS=${REDIS_CLUSTER_HOST_PORT_PAIRS} \ - REDIS_SENTINEL_HOST_PORT_PAIRS=${REDIS_SENTINEL_HOST_PORT_PAIRS} \ - REDIS_SENTINEL_PASSWORD=${REDIS_SENTINEL_PASSWORD} \ - REDIS_SENTINEL_MASTER_SET=${REDIS_SENTINEL_MASTER_SET} \ - TEST=${TEST} \ - SUFFIX=${SUFFIX} \ - MONGO_HOST=${MONGO_HOST} \ - MONGO_PORT=${MONGO_PORT} \ - MONGO_URI=${MONGO_URI} \ - MONGO_DB=${MONGO_INITDB_DATABASE} \ - IS_PRO=${IS_PRO} \ - CHECK_DB_LIVNESS=${CHECK_DB_LIVNESS} -RUN apt update && apt install -y nginx && apt install -y supervisor && apt install -y git +ENV TEST=false \ + KAFKA_HOSTS=kafka:9092 \ + KAFKA_SECURITY_PROTOCOL=PLAINTEXT \ + KAFKA_SASL_MECHANISM=PLAIN \ + CLICKHOUSE_USER=default \ + CLICKHOUSE_HOST=clickhouse-server \ + CLICKHOUSE_PORT=9000 \ + CLICKHOUSE_HTTP_PORT=8123 \ + CLICKHOUSE_KAFKA_HOSTS=kafka:9092 \ + CLICKHOUSE_DATABASE=featbit \ + CLICKHOUSE_CLUSTER=featbit_ch_cluster \ + CLICKHOUSE_REPLICATION=true \ + CLICKHOUSE_SECURE=false \ + CLICKHOUSE_VERIFY=true \ + CACHE_TYPE=RedisCache \ + REDIS_DB=0 \ + REDIS_SSL=false \ + REDIS_HOST=redis \ + REDIS_PORT=6379 \ + MONGO_HOST=mongodb \ + MONGO_PORT=27017 \ + MONGO_URI=mongodb://admin:password@mongodb:27017 \ + MONGO_DB=featbit \ + IS_PRO=false \ + CHECK_DB_LIVNESS=true \ + ENABLE_OPENTELEMETRY=false \ + OTEL_SERVICE_NAME=featbit-das \ + OTEL_TRACES_EXPORTER=otlp \ + OTEL_METRICS_EXPORTER=otlp \ + OTEL_LOGS_EXPORTER=otlp \ + OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 +RUN apt update && \ + apt install -y nginx && \ + apt install -y supervisor && \ + apt install -y git && \ + rm -rf /var/lib/apt/lists/* RUN mkdir -p /var/log/nginx && \ touch /var/log/nginx/access.log && \ touch /var/log/nginx/error.log -EXPOSE 80 COPY nginx.conf /etc/nginx/nginx.conf COPY . /featbit_da WORKDIR /featbit_da RUN chmod +x start.sh docker-entrypoint.sh wait-for-it.sh -RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt +RUN pip install --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt RUN opentelemetry-bootstrap -a install +EXPOSE 80 ENTRYPOINT ["./docker-entrypoint.sh"] CMD ["/usr/bin/supervisord","-c","supervisord.conf"] diff --git a/modules/data-analytics/README.md b/modules/data-analytics/README.md index 13ba73c61..b35d85bee 100644 --- a/modules/data-analytics/README.md +++ b/modules/data-analytics/README.md @@ -25,6 +25,8 @@ docker compose up da-server -d | `CACHE_TYPE` | Type of cache used | `"RedisCache"` | | `TEST` | If `true`, runs the application in test mode | `"false"` | +Note that set CHECK_DB_LIVNESS to **false** if you use external mongodb or clickhouse + ### Kafka Settings | Name | Description | Value | diff --git a/modules/data-analytics/app/commands.py b/modules/data-analytics/app/commands.py index 84617ae13..bb054ee54 100644 --- a/modules/data-analytics/app/commands.py +++ b/modules/data-analytics/app/commands.py @@ -21,7 +21,6 @@ @with_appcontext def migrate_clickhouse(upto, check, plan, print_sql): migrate_ch(upto, check, plan, print_sql) - migrate_mongo() @click.command() diff --git a/modules/data-analytics/app/experimentation/views.py b/modules/data-analytics/app/experimentation/views.py index 521f2f788..3d3a1c644 100644 --- a/modules/data-analytics/app/experimentation/views.py +++ b/modules/data-analytics/app/experimentation/views.py @@ -14,6 +14,7 @@ @expt.route('/results', methods=['POST']) def get_result(): + current_app.logger.info(f'POST {request.path}') json_str = request.get_data() try: if not json_str: diff --git a/modules/data-analytics/app/health/__init__.py b/modules/data-analytics/app/health/__init__.py index e3798f88a..29087dbee 100644 --- a/modules/data-analytics/app/health/__init__.py +++ b/modules/data-analytics/app/health/__init__.py @@ -9,4 +9,4 @@ def get_health_blueprint() -> Blueprint: if not __blueprint: __blueprint = Blueprint('health', __name__) from app.health import views - return __blueprint \ No newline at end of file + return __blueprint diff --git a/modules/data-analytics/app/health/views.py b/modules/data-analytics/app/health/views.py index 208f49252..1e84ad9a3 100644 --- a/modules/data-analytics/app/health/views.py +++ b/modules/data-analytics/app/health/views.py @@ -5,10 +5,12 @@ health = get_health_blueprint() health.register_error_handler(500, internal_error_handler) + @health.route('/liveness', methods=['GET']) def get_liveness(): return jsonify(code=200, error='', data={'state': f'{current_app.config["ENV"]} OK'}) + @health.route('/readiness', methods=['GET']) def get_readiness(): return jsonify(code=200, error='', data={'state': f'{current_app.config["ENV"]} OK'}) \ No newline at end of file diff --git a/modules/data-analytics/app/main/views.py b/modules/data-analytics/app/main/views.py index a5083a8a3..9fc2953d6 100644 --- a/modules/data-analytics/app/main/views.py +++ b/modules/data-analytics/app/main/views.py @@ -20,12 +20,14 @@ @main.route('', methods=['GET']) def index(): + current_app.logger.info(f'GET {request.path}') return jsonify(code=200, error='', data={'state': f'{current_app.config["ENV"]} OK'}) @main.route('/events', methods=['POST']) def create_events(): # this api is only for internal test, not use in prod + current_app.logger.info(f'POST {request.path}') json_str = request.get_data() try: if not json_str: @@ -47,6 +49,7 @@ def _create_events(json_events: Union[str, bytes]) -> None: @main.route('/events/stat/', methods=['POST']) def get_event_stat(event: str): + current_app.logger.info(f'POST {request.path}') json_str = request.get_data() try: if not json_str: diff --git a/modules/data-analytics/app/setting.py b/modules/data-analytics/app/setting.py index e26b48a37..27e00d101 100644 --- a/modules/data-analytics/app/setting.py +++ b/modules/data-analytics/app/setting.py @@ -78,3 +78,5 @@ 'handlers': ['wsgi'] } } + +ENABLE_OPENTELEMETRY = get_from_env("ENABLE_OPENTELEMETRY", False, type_cast=str_to_bool) diff --git a/modules/data-analytics/gunicorn.conf.py b/modules/data-analytics/gunicorn.conf.py index c08df7be9..f288be39d 100644 --- a/modules/data-analytics/gunicorn.conf.py +++ b/modules/data-analytics/gunicorn.conf.py @@ -1,59 +1,52 @@ -import os import logging +import os -from opentelemetry import metrics, trace, _logs -from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter -from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter +from opentelemetry import metrics, trace +from opentelemetry._logs import set_logger_provider +from opentelemetry.exporter.otlp.proto.grpc._log_exporter import \ + OTLPLogExporter +from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import \ + OTLPMetricExporter +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import \ + OTLPSpanExporter +from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler +from opentelemetry.sdk._logs.export import BatchLogRecordProcessor from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor -from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter -from opentelemetry._logs import LoggerProvider -from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler -from opentelemetry.sdk._logs.export import BatchLogRecordProcessor -from opentelemetry.instrumentation.logging import LoggingInstrumentor +from app.setting import ENABLE_OPENTELEMETRY bind = '0.0.0.0:10000' +wsgi_app = 'flasky:app' +# workers and threads workers = 2 worker_class = 'gthread' threads = 4 worker_tmp_dir = os.getenv('GUNICORN_WORKER_TMP_DIR', '/tmp') -otel_endpoint = os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://otel-collector:4317') -otel_service_name = os.getenv('OTEL_SERVICE_NAME', 'featbit-das') -otel_python_log_level = os.getenv('OTEL_PYTHON_LOG_LEVEL', 'info') -otel_log_format = os.getenv('OTEL_PYTHON_LOG_FORMAT', '%(msg)s [span_id=%(span_id)s]') - +# request settings limit_request_line = 0 limit_request_field_size = 0 limit_request_fields = 1000 -loglevel = otel_python_log_level -errorlog = '-' +# logging accesslog = "-" -access_log_format = ( - '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' -) +access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' +errorlog = '-' +loglevel = 'info' raw_env = ['WSGI=y'] -LoggingInstrumentor().instrument(set_logging_format=True) - -logging.basicConfig() def post_fork(server, worker): - if os.getenv('ENABLE_OPENTELEMETRY', 'false').lower() != 'true': + if not ENABLE_OPENTELEMETRY: return - - server.log.info("Worker spawned (pid: %s)", worker.pid) - resource = Resource.create( attributes={ - "service.name": otel_service_name, # If workers are not distinguished within attributes, traces and # metrics exported from each worker will be indistinguishable. While # not necessarily an issue for traces, it is confusing for almost @@ -64,34 +57,20 @@ def post_fork(server, worker): "worker": worker.pid, } ) + # Sets the global default tracer provider + provider = TracerProvider(resource=resource) + span_processor = BatchSpanProcessor(OTLPSpanExporter()) + provider.add_span_processor(span_processor) + trace.set_tracer_provider(provider) - # traces - trace.set_tracer_provider(TracerProvider(resource=resource)) - - # This uses insecure connection for the purpose of example. Please see the - # OTLP Exporter documentation for other options. - span_processor = BatchSpanProcessor( - OTLPSpanExporter(endpoint=otel_endpoint, insecure=True) - ) - trace.get_tracer_provider().add_span_processor(span_processor) - - # metrics - reader = PeriodicExportingMetricReader( - OTLPMetricExporter(endpoint=otel_endpoint, insecure=True) - ) - metrics.set_meter_provider( - MeterProvider( - resource=resource, - metric_readers=[reader], - ) - ) + # Sets the global default metric provider + reader = PeriodicExportingMetricReader(OTLPMetricExporter()) + metrics.set_meter_provider(MeterProvider(resource=resource, metric_readers=[reader])) - # logs - logging_provider = LoggerProvider(resource=resource) - _logs.set_logger_provider(logging_provider) - log_processor = BatchLogRecordProcessor( - OTLPLogExporter(endpoint=otel_endpoint, insecure=True) - ) - _logs.get_logger_provider().add_log_record_processor(log_processor) - handler = LoggingHandler(level=logging.DEBUG, logger_provider=logging_provider) - logging.getLogger('gunicorn.error').addHandler(handler) \ No newline at end of file + # Attach OTLP handler to root logger + logger_provider = LoggerProvider(resource=resource) + exporter = OTLPLogExporter() + logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter)) + set_logger_provider(logger_provider) + handler = LoggingHandler(level=logging.getLevelName(loglevel.upper()), logger_provider=logger_provider) + logging.getLogger('gunicorn.error').addHandler(handler) diff --git a/modules/data-analytics/requirements.txt b/modules/data-analytics/requirements.txt index 1bc192270..535ca9843 100644 --- a/modules/data-analytics/requirements.txt +++ b/modules/data-analytics/requirements.txt @@ -18,10 +18,5 @@ Flask-Caching >= 2.0.2 Flask-PyMongo Flask-APScheduler python-dotenv -pytest -opentelemetry-api==1.20.0 -opentelemetry-exporter-otlp==1.20.0 -opentelemetry-instrumentation==0.41b0 -opentelemetry-instrumentation-flask==0.41b0 -opentelemetry-instrumentation-wsgi==0.41b0 -opentelemetry-sdk==1.20.0 \ No newline at end of file +opentelemetry-distro[otlp] +opentelemetry-instrumentation \ No newline at end of file diff --git a/modules/data-analytics/start.bat b/modules/data-analytics/start.bat deleted file mode 100644 index 47fb162d9..000000000 --- a/modules/data-analytics/start.bat +++ /dev/null @@ -1,7 +0,0 @@ -@echo on - -set FLASK_APP='flasky:app' - -flask migrate-database - -flask run \ No newline at end of file diff --git a/modules/data-analytics/start.sh b/modules/data-analytics/start.sh index 8ae388ee2..d8399a866 100755 --- a/modules/data-analytics/start.sh +++ b/modules/data-analytics/start.sh @@ -1,12 +1,35 @@ #!/bin/bash set -e -export FLASK_APP='flasky:app' - flask migrate-database if [ "$ENABLE_OPENTELEMETRY" = "true" ]; then - opentelemetry-instrument gunicorn 'flasky:app' + if [ "$OTEL_TRACES_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_TRACES_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_TRACES_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + + if [ "$OTEL_METRICS_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_METRICS_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_METRICS_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + + if [ "$OTEL_LOGS_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_LOGS_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_LOGS_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + # otel python log settings + export OTEL_PYTHON_LOG_CORRELATION=true + export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true + export OTEL_PYTHON_FLASK_EXCLUDED_URLS="/health/*" + + opentelemetry-instrument gunicorn else - gunicorn 'flasky:app' -fi \ No newline at end of file + gunicorn +fi diff --git a/modules/evaluation-server/deploy/Dockerfile b/modules/evaluation-server/deploy/Dockerfile index 293dc0cb0..26134e656 100644 --- a/modules/evaluation-server/deploy/Dockerfile +++ b/modules/evaluation-server/deploy/Dockerfile @@ -1,5 +1,7 @@ # build stage # https://hub.docker.com/_/microsoft-dotnet +ARG INSTALL_DIR=/app + FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /source @@ -26,27 +28,49 @@ RUN dotnet build -c Release --no-restore && dotnet test # publish stage FROM build AS publish +ARG INSTALL_DIR WORKDIR /source/src/Api -RUN dotnet publish -c Release --no-build -o /app +RUN dotnet publish -c Release --no-build -o $INSTALL_DIR # final stage/image FROM mcr.microsoft.com/dotnet/aspnet:6.0 RUN apt-get update && apt-get install -y curl unzip && rm -rf /var/lib/apt/lists/* +ARG INSTALL_DIR ARG OTEL_VERSION=1.1.0 + +# ensure we listen on any IP Address +ENV ASPNETCORE_URLS=http://*:5100 \ + INSTALL_DIR=$INSTALL_DIR \ + DOTNET_ADDITIONAL_DEPS=$INSTALL_DIR/AdditionalDeps \ + DOTNET_SHARED_STORE=$INSTALL_DIR/store \ + ENABLE_OPENTELEMETRY=false \ + OTEL_DOTNET_AUTO_HOME=$INSTALL_DIR \ + OTEL_SERVICE_NAME=featbit-els \ + OTEL_TRACES_EXPORTER=otlp \ + OTEL_METRICS_EXPORTER=otlp \ + OTEL_LOGS_EXPORTER=otlp \ + OTEL_EXPORTER_OTLP_ENDPOINT=http://locahost:4317 \ + OTEL_EXPORTER_OTLP_PROTOCOL=grpc \ + OTEL_EXPORTER_OTLP_INSECURE=true + ADD https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/download/v${OTEL_VERSION}/otel-dotnet-auto-install.sh otel-dotnet-auto-install.sh RUN chmod +x otel-dotnet-auto-install.sh -RUN export OTEL_DOTNET_AUTO_HOME="/app" && sh otel-dotnet-auto-install.sh +RUN ./otel-dotnet-auto-install.sh -WORKDIR /app -COPY --from=publish /app ./ -# ensure we listen on any IP Address -ENV ASPNETCORE_URLS=http://*:5100 +WORKDIR $INSTALL_DIR +COPY --from=publish $INSTALL_DIR ./ +COPY --from=build /source/start.sh ./start.sh +RUN chmod +x ./start.sh EXPOSE 5100 +# temporal workaround for Automatic Instrumentation in ARM arch +RUN mkdir -p $DOTNET_SHARED_STORE/arm64 && \ + cp -a $DOTNET_SHARED_STORE/x64/. $DOTNET_SHARED_STORE/arm64 + # health check HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD curl --fail --silent http://localhost:5100/health/liveness || exit 1 -ENTRYPOINT ["dotnet", "Api.dll"] \ No newline at end of file +ENTRYPOINT ["./start.sh"] \ No newline at end of file diff --git a/modules/evaluation-server/start.sh b/modules/evaluation-server/start.sh new file mode 100644 index 000000000..87b44fa49 --- /dev/null +++ b/modules/evaluation-server/start.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + +ARCH=$(uname -m) + +if [ "$ENABLE_OPENTELEMETRY" = "true" ]; then + if [ "$OTEL_TRACES_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_TRACES_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_TRACES_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + + if [ "$OTEL_METRICS_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_METRICS_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_METRICS_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + + if [ "$OTEL_LOGS_EXPORTER" = "otlp" ]; then + export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + export OTEL_EXPORTER_OTLP_LOGS_TIMEOUT=${OTEL_EXPORTER_OTLP_TIMEOUT:-10000} + export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL:-grpc} + export OTEL_EXPORTER_OTLP_LOGS_INSECURE=${OTEL_EXPORTER_OTLP_INSECURE:-true} + fi + export DOTNET_STARTUP_HOOKS="$INSTALL_DIR/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll" + if [ "$ARCH" = "arm64" ]; then + export CORECLR_ENABLE_PROFILING="0" + else + export CORECLR_ENABLE_PROFILING="1" + export CORECLR_PROFILER="{918728DD-259F-4A6A-AC2B-B85E1B658318}" + export CORECLR_PROFILER_PATH="$INSTALL_DIR/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so" + fi +fi + +dotnet Api.dll From b0d3456aca9ae20d0a4df0b0d8200799f98846d1 Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:28:18 +0100 Subject: [PATCH 09/10] doc: fix typos (#600) * fix typos * fix typos * fix typo --- CONTRIBUTING.md | 6 +++--- Development.md | 6 +++--- kubernetes/pro/Readme.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3761547b6..4a8c4b66c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,11 +67,11 @@ But of course, you can finish your contribution and create a PR without notifyin - **Step 1** - [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks) this repository. - **Step 2** - Clone the repository to your local machine. - **Step 3** - Add the changes to your repository. -- **Step 4** - Create a PULL Request from forked project to FeatBit. We may ask for changes to be made before a PR can be merge. +- **Step 4** - Create a PULL Request from forked project to FeatBit. We may ask for changes to be made before a PR can be merged. - **Step 5** - Congratulations 🎉🎉 Your PR is approved and Merged !!! -- **Step 6** - FeatBit team thanks you. You becomes one of the contributor of FeatBit 🎉🎉 . +- **Step 6** - FeatBit team thanks you. You become one of the contributors of FeatBit 🎉🎉 . -If the steps above isn't very clear, you can search ["GitHub Forks and Pull Requests" on Youtube](https://www.youtube.com/watch?v=a_FLqX3vGR4). +If the steps above aren't very clear, you can search ["GitHub Forks and Pull Requests" on Youtube](https://www.youtube.com/watch?v=a_FLqX3vGR4). ---------------------------------------------------- diff --git a/Development.md b/Development.md index f40697f98..6624f92a4 100644 --- a/Development.md +++ b/Development.md @@ -72,7 +72,7 @@ npm run start:zh // Chinese, available at localhost:4201 FeatBit should be available to everyone everywhere, and we don't want language to be a barrier. So for this reason we have implemented internationalization features into our codebase. -FeatBit UI uses offical [@angular/localize +FeatBit UI uses official [@angular/localize ](https://www.npmjs.com/package/@angular/localize) package to implement the i18n, please read the [official doc](https://angular.io/guide/i18n-overview) for how to use it. The language resource files are under * *modules/front-end/src/locale** folder, with following format messages.xx.xlf, xx is the language code. @@ -81,8 +81,8 @@ Currently only English and Chinese are available, we would be very grateful to h too. If you put a text in the UI, at the end of the developing work, you need to put its translations into the corresponding -resource file. This work could be very tedius, we created -a [library](https://github.com/featbit/angular-locales-generator) to faciliate the job, you need to run the command +resource file. This work could be very tedious, we created +a [library](https://github.com/featbit/angular-locales-generator) to facilitate the job, you need to run the command ```bash npm run i18n diff --git a/kubernetes/pro/Readme.md b/kubernetes/pro/Readme.md index 8db18051f..c6c598e8a 100644 --- a/kubernetes/pro/Readme.md +++ b/kubernetes/pro/Readme.md @@ -16,7 +16,7 @@ A working Kubernetes Cluster such as - These files use known usernames and passwords as well as very basic configurations to facilitate an easy way to evaluate Featbit Professional on kubernetes, they should be changed for any other uses. DO NOT deploy to a production or otherwise public cluster without customizing them. -- The infrastructure folder contains manifests needed to setup single instances of mongodb, clickhouse, kafka, and redis, with the exception of the *-configMap files which are derived from the configuration files found in featbit/infra/ directory of the repo. These manifests are provided as a convenience, if you have support, installation, maintanance, configuration, clustering, or any other questions regarding infrastructure components, please check with those projects respectively. +- The infrastructure folder contains manifests needed to setup single instances of mongodb, clickhouse, kafka, and redis, with the exception of the *-configMap files which are derived from the configuration files found in featbit/infra/ directory of the repo. These manifests are provided as a convenience, if you have support, installation, maintenance, configuration, clustering, or any other questions regarding infrastructure components, please check with those projects respectively. - The manifests in the ingress folder are provided as a convenience and assume that traefik is installed and properly configured. As such configurations are highly custom, we cannot support your specific configuration. If you need help with traefik, please seek support from that community and their documentation. From 6dc8f8e5a888823fba54f46db8c2db1c36a58bb1 Mon Sep 17 00:00:00 2001 From: deleteLater Date: Mon, 26 Feb 2024 22:40:40 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=A7=B9=20refactor:=20restructure=20?= =?UTF-8?q?get=20`currentUserProp`=20method=20(#601)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * clean code * update --- .../find-rule/rule/rule.component.ts | 69 +++++++++---------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts b/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts index 3e0f228d2..65db837d7 100644 --- a/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts +++ b/modules/front-end/src/app/core/components/find-rule/rule/rule.component.ts @@ -1,19 +1,19 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core'; -import {isSegmentCondition, uuidv4} from '@utils/index'; +import { isSegmentCondition, uuidv4 } from '@utils/index'; import { Subject } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; -import { IRuleOp, ruleOps, findIndex } from '../ruleConfig'; +import { findIndex, IRuleOp, ruleOps } from '../ruleConfig'; import { ISegment, ISegmentListModel, SegmentListFilter } from '@features/safe/segments/types/segments-index'; import { SegmentService } from '@services/segment.service'; import { IUserProp } from "@shared/types"; -import {ICondition} from "@shared/rules"; +import { ICondition } from "@shared/rules"; @Component({ selector: 'app-rule', templateUrl: './rule.component.html', styleUrls: ['./rule.component.less'] }) -export class RuleComponent { +export class RuleComponent { private inputs = new Subject(); @@ -51,15 +51,13 @@ export class RuleComponent { this.selectedProp = this.userProps.find(prop => prop.name === this.condition.property); } - userProps: IUserProp[] = []; filteredProps: IUserProp[] = []; get currentUserProp(): IUserProp { const userProp = this.userProps.find(prop => prop.name === this.condition.property); - - if(!userProp) { - const newProp: IUserProp = { + if (!userProp) { + return { id: uuidv4(), name: "", presetValues: [], @@ -68,38 +66,35 @@ export class RuleComponent { isDigestField: false, remark: '', isNew: true - } - - return newProp; - }else{ - // adapt to existing value that preset values don't contain - if (userProp.usePresetValuesOnly) { - if (this.condition.value && userProp.presetValues.findIndex(x => x.value === this.condition.value) === -1) { - userProp.presetValues.push({ - id: '', - value: this.condition.value, - description: this.condition.value - }) - } - - if (this.condition.multipleValue) { - this.condition.multipleValue.forEach(value => { - if (userProp.presetValues.findIndex(x => x.value === value) === -1) { - userProp.presetValues.push({ - id: '', - value: value, - description: value - }) - } - }); - } + }; + } + + // adapt to existing value that preset values don't contain + if (userProp.usePresetValuesOnly) { + if (this.condition.value && userProp.presetValues.findIndex(x => x.value === this.condition.value) === -1) { + userProp.presetValues.push({ + id: '', + value: this.condition.value, + description: this.condition.value + }) } - return userProp; + if (this.condition.multipleValue) { + this.condition.multipleValue.forEach(value => { + if (userProp.presetValues.findIndex(x => x.value === value) === -1) { + userProp.presetValues.push({ + id: '', + value: value, + description: value + }) + } + }); + } } - + return userProp; } + get multiSelectMode(): 'multiple' | 'tags' { return this.currentUserProp.usePresetValuesOnly ? 'multiple' : 'tags'; } @@ -136,7 +131,7 @@ export class RuleComponent { }); } - onSearchSegments(value: string = ''){ + onSearchSegments(value: string = '') { this.isLoadingSegments = true; this.inputs.next(value); } @@ -185,7 +180,7 @@ export class RuleComponent { public onPropertyChange() { if (this.selectedProp.isNew) { - this.addProperty.emit({...this.selectedProp, isNew: false}); + this.addProperty.emit({ ...this.selectedProp, isNew: false }); } this.condition.property = this.selectedProp.name;