Поделиться через


Оркестрация приложений Node.js в .NET Aspire

В этой статье вы узнаете, как использовать приложения Node.js и диспетчер пакетов узлов (npm) в проекте .NET.NET Aspire. Пример приложения в этой статье демонстрирует возможности Angular, Reactи Vueclient. Следующие .NET.NET Aspire API существуют для поддержки этих сценариев, и они входят в Aspire. Пакет NuGet для размещения.NodeJS:

Разница между этими двумя API заключается в том, что первый используется для размещения приложений Node.js, а второй для размещения приложений, выполняемых из пакета . Раздел scripts файлаjson, а также соответствующая команда npm run <script-name>.

Подсказка

Пример исходного кода для этой статьи доступен на GitHub, а дополнительные сведения доступны на странице в разделе Примеры кода: .NET Aspire с Angular, React и Vue.

Важный

Хотя эта статья сосредоточена на фронтенд-компонентах приложения Single-Page (SPA), на странице с примерами кода доступен дополнительный пример Node.js: .NET AspireNode.js пример, демонстрирующий, как использовать Node.js в качестве server приложения с express.

Необходимые условия

Для работы с .NET.NET Aspireвам потребуется следующее установить локально:

Дополнительные сведения см. в разделе .NET.NET Aspire настройки и инструментови .NET.NET Aspire пакета SDK.

Кроме того, необходимо установить Node.js на компьютере. Пример приложения в этой статье создан с Node.js версии 20.12.2 и npm версии 10.5.1. Чтобы проверить ваши версии Node.js и npm, выполните следующие команды:

node --version
npm --version

Чтобы скачать Node.js (включая npm), перейдите на страницу загрузки Node.js.

Клонировать пример исходного кода

Чтобы клонировать пример исходного кода из GitHub, выполните следующую команду:

git clone https://github.com/dotnet/aspire-samples.git

После клонирования репозитория перейдите к папке samples/AspireWithJavaScript:

cd samples/AspireWithJavaScript

В этом каталоге есть шесть дочерних каталогов, описанных в следующем списке:

  • AspireJavaScript.Angular: приложение Angular, которое использует API прогнозирования погоды и отображает данные в таблице.
  • AspireJavaScript.AppHost: проект .NET.NET Aspire, который управляет другими приложениями в этом примере. Для получения дополнительной информации см. обзор оркестрации .NET.NET Aspire.
  • AspireJavaScript.MinimalApi: HTTP API, который возвращает данные прогноза погоды случайным образом.
  • AspireJavaScript.React: приложение React, которое использует API прогнозирования погоды и отображает данные в таблице.
  • AspireJavaScript.ServiceDefaults: общий проект по умолчанию для .NET.NET Aspire проектов. Для получения дополнительной информации см. настройки по умолчанию для службы .NET.NET Aspire.
  • AspireJavaScript.Vue: приложение Vue, которое использует API прогнозирования погоды и отображает данные в таблице.

Установка зависимостей client

В примере приложения показано, как использовать приложения JavaScript client, созданные на основе Node.js. Каждое приложение client было написано с помощью команды шаблона npm create или вручную. В следующей таблице перечислены команды шаблона, используемые для создания каждого приложения client вместе с портом по умолчанию:

Тип приложения Команда создания шаблона Порт по умолчанию
Angular npm create @angular@latest 4200
React Не использовался шаблон. PORT env var
Vue npm create vue@latest 5173

Совет

Вам не нужно выполнять какие-либо из этих команд, так как пример приложения уже включает клиенты. Вместо этого, это отправная точка, от которой были созданы клиенты. Дополнительные сведения см. в разделе npm-init.

Чтобы запустить приложение, сначала необходимо установить зависимости для каждого client. Для этого перейдите к каждой папке client и выполните команды npm install (или псевдоним установки npm i).

Установка зависимостей Angular

npm i ./AspireJavaScript.Angular/

Дополнительные сведения о приложении Angular см. в разделе , который исследует Angularclient.

Установка зависимостей React

npm i ./AspireJavaScript.React/

Дополнительные сведения о приложении React см. в разделе Reactclient.

Установка зависимостей Vue

npm i ./AspireJavaScript.Vue/

Дополнительные сведения о приложении Vue см. в разделе изучение Vueclient.

Запуск примера приложения

Чтобы запустить пример приложения, вызовите команду dotnet run, для хоста приложения оркестратора AspireJavaScript.AppHost.csproj в качестве параметра --project.

dotnet run --project ./AspireJavaScript.AppHost/AspireJavaScript.AppHost.csproj

Панель управления .NET.NET Aspire запускается в стандартном браузере, и каждая конечная точка приложения client отображается в столбце Endpoints страницы Resources. На следующем рисунке показана панель мониторинга для этого примера приложения:

панель мониторинга .NET Aspire с несколькими приложениями javaScript client.

Конечная точка службы weatherapi перенаправляет на страницу Swagger UI, которая документирует HTTP API. Каждое приложение client использует эту службу для отображения данных прогноза погоды. Вы можете просмотреть каждое приложение client, перейдя к соответствующей конечной точке на панели мониторинга .NET Aspire. Их снимки экрана и изменения, внесенные из начальной точки шаблона, подробно описаны в следующих разделах.

В том же сеансе терминала, который использовался для запуска приложения, нажмите клавиши CTRL + C, чтобы остановить приложение.

Изучение хоста приложения

Чтобы узнать, как управляется каждый ресурс приложения client, ознакомьтесь с проектом узла приложения. Хост приложения требует пакета NuGet Aspire.Hosting.NodeJS для размещения приложений Node.js:

<Project Sdk="Microsoft.NET.Sdk">

  <Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsAspireHost>true</IsAspireHost>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.AppHost" Version="9.0.0" />
    <PackageReference Include="Aspire.Hosting.NodeJs" Version="9.0.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireJavaScript.MinimalApi\AspireJavaScript.MinimalApi.csproj" />
  </ItemGroup>

  <Target Name="RestoreNpm" BeforeTargets="Build" Condition=" '$(DesignTimeBuild)' != 'true' ">
    <ItemGroup>
      <PackageJsons Include="..\*\package.json" />
    </ItemGroup>

    <!-- Install npm packages if node_modules is missing -->
    <Message Importance="Normal" Text="Installing npm packages for %(PackageJsons.RelativeDir)" Condition="!Exists('%(PackageJsons.RootDir)%(PackageJsons.Directory)/node_modules')" />
    <Exec Command="npm install" WorkingDirectory="%(PackageJsons.RootDir)%(PackageJsons.Directory)" Condition="!Exists('%(PackageJsons.RootDir)%(PackageJsons.Directory)/node_modules')" />
  </Target>

</Project>

Файл проекта также определяет целевой объект сборки, обеспечивающий установку зависимостей npm перед сборкой узла приложения. Код узла приложения (Program.cs) объявляет ресурсы приложения client с помощью API AddNpmApp(IDistributedApplicationBuilder, String, String, String, String[]).

var builder = DistributedApplication.CreateBuilder(args);

var weatherApi = builder.AddProject<Projects.AspireJavaScript_MinimalApi>("weatherapi")
    .WithExternalHttpEndpoints();

builder.AddNpmApp("angular", "../AspireJavaScript.Angular")
    .WithReference(weatherApi)
    .WaitFor(weatherApi)
    .WithHttpEndpoint(env: "PORT")
    .WithExternalHttpEndpoints()
    .PublishAsDockerFile();

builder.AddNpmApp("react", "../AspireJavaScript.React")
    .WithReference(weatherApi)
    .WaitFor(weatherApi)
    .WithEnvironment("BROWSER", "none") // Disable opening browser on npm start
    .WithHttpEndpoint(env: "PORT")
    .WithExternalHttpEndpoints()
    .PublishAsDockerFile();

builder.AddNpmApp("vue", "../AspireJavaScript.Vue")
    .WithReference(weatherApi)
    .WaitFor(weatherApi)
    .WithHttpEndpoint(env: "PORT")
    .WithExternalHttpEndpoints()
    .PublishAsDockerFile();

builder.AddNpmApp("reactvite", "../AspireJavaScript.Vite")
    .WithReference(weatherApi)
    .WithEnvironment("BROWSER", "none")
    .WithHttpEndpoint(env: "VITE_PORT")
    .WithExternalHttpEndpoints()
    .PublishAsDockerFile();

builder.Build().Run();

Предыдущий код:

  • Создает объект DistributedApplicationBuilder.
  • Добавляет службу WeatherAPI в качестве проекта на хост приложения.
    • Помечает конечные точки HTTP как внешние.
  • Со ссылкой на службу weatherapi добавляетangular", "react" и "vue" приложения client в виде приложений npm.
    • Каждое приложение client настроено для запуска на другом порту контейнера и использует переменную среды PORT для определения порта.
    • Все приложения client также полагаются на Dockerfile для создания образа контейнера и настроены так, чтобы быть представлены в манифесте публикации как контейнер из API PublishAsDockerFile.

Дополнительные сведения о сети внутреннего цикла см. в .NET.NET Aspire обзоре сети внутреннего цикла. Дополнительные сведения о развертывании приложений см. в формате манифеста .NET.NET Aspire для разработчиков инструментов развертывания.

Когда хост приложения оркеструет запуск каждого client приложения, он использует команду npm run start. Эта команда определена в разделе scripts пакета . Файлjson для каждого приложения client. Скрипт start используется для запуска приложения client на указанном порту. Каждое приложение client использует прокси-сервер для запроса службы weatherapi.

Прокси-сервер настроен в:

  • Файл proxy.conf.js для Angularclient.
  • Файл webpack.config.js для Reactclient.
  • Файл vite.config.ts для Vueclient.

Исследуйте Angularclient

Существует несколько ключевых изменений исходного шаблона Angular. Первым является добавление файла proxy.conf.js. Этот файл используется для прокси-запросов из Angularclient в службу weatherapi.

module.exports = {
  "/api": {
    target:
      process.env["services__weatherapi__https__0"] ||
      process.env["services__weatherapi__http__0"],
    secure: process.env["NODE_ENV"] !== "development",
    pathRewrite: {
      "^/api": "",
    },
  },
};

Узел хостинга приложения .NET.NET Aspire задает переменную среды services__weatherapi__http__0, которая используется для определения адреса конечной точки сервиса weatherapi. Предыдущая конфигурация проксирует HTTP-запросы, начинающиеся с /api, к целевому URL-адресу, указанному в переменной среды.

Второе обновление касается пакета . Файлjson. Этот файл используется для настройки Angularclient для запуска на порте, отличном от порта по умолчанию. Это достигается с помощью переменной среды PORT и пакета npm run-script-os для задания порта.

{
  "name": "angular-weather",
  "version": "0.0.0",
  "engines": {
    "node": ">=20.12"
  },
  "scripts": {
    "ng": "ng",
    "start": "run-script-os",
    "start:win32": "ng serve --port %PORT%",
    "start:default": "ng serve --port $PORT",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^18.1.1",
    "@angular/common": "^18.1.1",
    "@angular/compiler": "^18.1.1",
    "@angular/core": "^18.1.1",
    "@angular/forms": "^18.1.1",
    "@angular/platform-browser": "^18.1.1",
    "@angular/platform-browser-dynamic": "^18.1.1",
    "@angular/router": "^18.1.1",
    "rxjs": "~7.8.0",
    "tslib": "^2.6.3",
    "zone.js": "~0.14.8"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^18.1.1",
    "@angular/cli": "^18.1.1",
    "@angular/compiler-cli": "^18.1.1",
    "@types/jasmine": "~5.1.0",
    "jasmine-core": "~5.2.0",
    "karma": "~6.4.3",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.5.3",
    "run-script-os": "^1.1.6"
  }
}

Раздел scripts пакета .json файл используется для определения скрипта start. Этот скрипт используется командой npm start для запуска приложения Angularclient. Скрипт start настроен на использование пакета run-script-os для задания порта, который делегирует команде ng serve передачу соответствующего переключателя --port, основываясь на синтаксисе, подходящем для ОС.

Чтобы осуществлять HTTP-вызовы к службе weatherapi, приложение Angularclient должно быть настроено для предоставления AngularHttpClient для внедрения зависимостей. Это достигается с помощью вспомогательной функции provideHttpClient при настройке приложения в файле app.config.ts.

import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient()
  ]
};

Наконец, приложению Angularclient необходимо вызвать конечную точку /api/WeatherForecast, чтобы получить данные прогноза погоды. Существует несколько обновлений HTML, CSS и TypeScript, все из которых выполняются в следующие файлы:

import { Component, Injectable } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { WeatherForecasts } from '../types/weatherForecast';

@Injectable()
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = 'weather';
  forecasts: WeatherForecasts = [];

  constructor(private http: HttpClient) {
    http.get<WeatherForecasts>('api/weatherforecast').subscribe({
      next: result => this.forecasts = result,
      error: console.error
    });
  }
}

Angular приложение работает

Чтобы визуализировать приложение Angularclient, перейдите к конечной точкеangularна панели мониторинга .NET Aspire. На следующем рисунке показано приложение Angularclient:

Angularclient приложение с поддельными данными о погоде прогноза, отображаемыми в виде таблицы.

Изучите Reactclient

Приложение React не было написано с помощью шаблона и вместо этого было написано вручную. Полный исходный код можно найти в dotnet/aspireрепозитория примеров. Некоторые ключевые моменты интереса находятся в файле src/App.js:

import { useEffect, useState } from "react";
import "./App.css";

function App() {
  const [forecasts, setForecasts] = useState([]);

  const requestWeather = async () => {
    const weather = await fetch("api/weatherforecast");
    console.log(weather);

    const weatherJson = await weather.json();
    console.log(weatherJson);

    setForecasts(weatherJson);
  };

  useEffect(() => {
    requestWeather();
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <h1>React Weather</h1>
        <table>
          <thead>
            <tr>
              <th>Date</th>
              <th>Temp. (C)</th>
              <th>Temp. (F)</th>
              <th>Summary</th>
            </tr>
          </thead>
          <tbody>
            {(
              forecasts ?? [
                {
                  date: "N/A",
                  temperatureC: "",
                  temperatureF: "",
                  summary: "No forecasts",
                },
              ]
            ).map((w) => {
              return (
                <tr key={w.date}>
                  <td>{w.date}</td>
                  <td>{w.temperatureC}</td>
                  <td>{w.temperatureF}</td>
                  <td>{w.summary}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </header>
    </div>
  );
}

export default App;

Функция App — это точка входа для приложения Reactclient. Он использует useState и useEffect крючки для управления состоянием данных прогноза погоды. API fetch используется для выполнения HTTP-запроса к конечной точке /api/WeatherForecast. Затем ответ преобразуется в JSON и задает состояние данных прогноза погоды.

const HTMLWebpackPlugin = require("html-webpack-plugin");

module.exports = (env) => {
  return {
    entry: "./src/index.js",
    devServer: {
      port: env.PORT || 4001,
      allowedHosts: "all",
      proxy: [
        {
          context: ["/api"],
          target:
            process.env.services__weatherapi__https__0 ||
            process.env.services__weatherapi__http__0,
          pathRewrite: { "^/api": "" },
          secure: false,
        },
      ],
    },
    output: {
      path: `${__dirname}/dist`,
      filename: "bundle.js",
    },
    plugins: [
      new HTMLWebpackPlugin({
        template: "./src/index.html",
        favicon: "./src/favicon.ico",
      }),
    ],
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader",
            options: {
              presets: [
                "@babel/preset-env",
                ["@babel/preset-react", { runtime: "automatic" }],
              ],
            },
          },
        },
        {
          test: /\.css$/,
          exclude: /node_modules/,
          use: ["style-loader", "css-loader"],
        },
      ],
    },
  };
};

Приведенный выше код определяет module.exports следующим образом:

  • Свойство entry установлено на src/index.js-файл.
  • devServer использует прокси-сервер для пересылки запросов в сервис weatherapi, устанавливает порт в переменную среды PORT и разрешает всем хостам.
  • Результат output содержится в папке с файловым дистрибутивом и файлом bundle.js.
  • plugins установил файл src/index.html в качестве шаблона и открыл файл favicon.ico.

Последние обновления относятся к следующим файлам:

React приложение работает

Чтобы визуализировать приложение Reactclient, перейдите к конечной точкеreactна панели мониторинга .NET Aspire. На следующем рисунке показано приложение Reactclient:

Reactclient приложение с поддельными данными о погоде прогноза, отображаемыми в виде таблицы.

Изучение Vueclient

Существует несколько ключевых изменений исходного шаблона Vue. Основными обновлениями были добавление вызова fetch в TheWelcomevue файл для получения данных прогноза погоды из конечной точки /api/WeatherForecast. Следующий фрагмент кода демонстрирует вызов fetch:

<script lang="ts">
interface WeatherForecast {
  date: string
  temperatureC: number
  temperatureF: number
  summary: string
};

type Forecasts = WeatherForecast[];

export default {
  name: 'TheWelcome',
  data() {
    return {
      forecasts: [],
      loading: true,
      error: null
    }
  },
  mounted() {
    fetch('api/weatherforecast')
      .then(response => response.json())
      .then(data => {
        this.forecasts = data
      })
      .catch(error => {
        this.error = error
      })
      .finally(() => (this.loading = false))
  }
}
</script>

<template>
  <table>
    <thead>
      <tr>
        <th>Date</th>
        <th>Temp. (C)</th>
        <th>Temp. (F)</th>
        <th>Summary</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="forecast in (forecasts as Forecasts)">
        <td>{{ forecast.date }}</td>
        <td>{{ forecast.temperatureC }}</td>
        <td>{{ forecast.temperatureF }}</td>
        <td>{{ forecast.summary }}</td>
      </tr>
    </tbody>
  </table>
</template>

<style>
table {
  border: none;
  border-collapse: collapse;
}

th {
  font-size: x-large;
  font-weight: bold;
  border-bottom: solid .2rem hsla(160, 100%, 37%, 1);
}

th,
td {
  padding: 1rem;
}

td {
  text-align: center;
  font-size: large;
}

tr:nth-child(even) {
  background-color: var(--vt-c-black-soft);
}
</style>

Поскольку интеграция TheWelcome находится в состоянии mounted, она обращается к конечной точке /api/weatherforecast для получения данных прогноза погоды. Затем ответ задается в качестве свойства данных forecasts. Чтобы задать порт server, приложение Vueclient использует переменную среды PORT. Это достигается путем обновления файла vite.config.ts:

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  server: {
    host: true,
    port: parseInt(process.env.PORT ?? "5173"),
    proxy: {
      '/api': {
        target: process.env.services__weatherapi__https__0 || process.env.services__weatherapi__http__0,
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, ''),
        secure: false
      }
    }
  }
})

Кроме того, конфигурация Vite указывает свойство server.proxy для пересылки запросов в службу weatherapi. Это достигается с помощью переменной среды services__weatherapi__http__0, которая устанавливается узлом приложения .NET.NET Aspire.

Окончательное обновление в шаблоне внесено в файл TheWelcome.vue. Этот файл вызывает конечную точку /api/WeatherForecast для получения данных прогноза погоды и отображения данных в таблице. Он включает обновления CSS, HTML и TypeScript.

Vue запуск приложения

Чтобы визуализировать приложение Vueclient, перейдите к конечной точкеvueна панели мониторинга .NET Aspire. На следующем рисунке показано приложение Vueclient:

Vueclient приложение с поддельными данными о погоде прогноза, отображаемыми в виде таблицы.

Рекомендации по развертыванию

Пример исходного кода для этой статьи предназначен для локального запуска. Каждое приложение client разворачивается в виде контейнерного образа. Для каждого приложения client используется Dockerfile для создания образа контейнера. Каждая Dockerfile идентична, создается путем использования многоэтапной сборки для получения образа контейнера, готового к производственной эксплуатации.

FROM node:20 as build

WORKDIR /app

COPY package.json package.json
COPY package-lock.json package-lock.json

RUN npm install

COPY . .

RUN npm run build

FROM nginx:alpine

COPY --from=build /app/default.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/dist/weather/browser /usr/share/nginx/html

# Expose the default nginx port
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

В настоящее время приложения client настроены для запуска в качестве истинных SPA-приложений и не настроены для запуска в режиме отрисовки на стороне сервера (SSR) server. Они сидят за nginx, который используется для обслуживания статических файлов. Они используют файл default.conf.template для настройки nginx для прокси-запросов к приложению .

server {
    listen       ${PORT};
    listen  [::]:${PORT};
    server_name  localhost;

    access_log  /var/log/nginx/server.access.log  main;

    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass ${services__weatherapi__https__0};
        proxy_http_version 1.1;
        proxy_ssl_server_name on;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        rewrite ^/api(/.*)$ $1 break;
    }
}

рекомендации по Node.jsserver приложениям

Хотя эта статья посвящена client приложениям, возможно, вам потребуется разместить приложение Node.jsserver. Для размещения приложения Node.jsserver в качестве приложения spa client требуется та же семантика. Для хоста приложения .NET.NET Aspire требуется ссылка на пакет Aspire.Hosting.NodeJS NuGet, и коду необходимо вызвать либо AddNodeApp, либо AddNpmApp. Эти API полезны для добавления существующих приложений JavaScript в контейнер приложений .NET.NET Aspire.

При настройке секретов и передаче переменных среды в приложения на основе JavaScript, независимо от того, являются ли они client или server приложениями, используйте параметры. Дополнительные сведения см. в разделе .NET.NET Aspire: внешние параметры — секреты.

Используйте SDK JavaScript OpenTelemetry

Чтобы экспортировать журналы OpenTelemetry, трассировки и метрики из приложения Node.jsserver, используйте JavaScript SDK OpenTelemetry.

Полный пример приложения Node.jsserver с помощью пакета SDK для JavaScript OpenTelemetry вы можете найти на странице примеров кода : .NET AspireNode.js sample. Рассмотрим файл примера instrumentation.js, который демонстрирует, как настроить SDK JavaScript OpenTelemetry для экспорта журналов, трассировок и метрик.

import { env } from 'node:process';
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc';
import { SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis-4';
import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api';
import { credentials } from '@grpc/grpc-js';

const environment = process.env.NODE_ENV || 'development';

// For troubleshooting, set the log level to DiagLogLevel.DEBUG
//diag.setLogger(new DiagConsoleLogger(), environment === 'development' ? DiagLogLevel.INFO : DiagLogLevel.WARN);

const otlpServer = env.OTEL_EXPORTER_OTLP_ENDPOINT;

if (otlpServer) {
    console.log(`OTLP endpoint: ${otlpServer}`);

    const isHttps = otlpServer.startsWith('https://');
    const collectorOptions = {
        credentials: !isHttps
            ? credentials.createInsecure()
            : credentials.createSsl()
    };

    const sdk = new NodeSDK({
        traceExporter: new OTLPTraceExporter(collectorOptions),
        metricReader: new PeriodicExportingMetricReader({
            exportIntervalMillis: environment === 'development' ? 5000 : 10000,
            exporter: new OTLPMetricExporter(collectorOptions),
        }),
        logRecordProcessor: new SimpleLogRecordProcessor({
            exporter: new OTLPLogExporter(collectorOptions)
        }),
        instrumentations: [
            new HttpInstrumentation(),
            new ExpressInstrumentation(),
            new RedisInstrumentation()
        ],
    });

    sdk.start();
}

Совет

Чтобы настроить параметры OTEL CORS панели мониторинга .NET.NET Aspire, см. страницу .NET.NET Aspire параметров OTEL CORS панели мониторинга.

Сводка

Хотя существует несколько рекомендаций, которые выходят за рамки этой статьи, вы узнали, как создавать проекты .NET Aspire, использующие диспетчер пакетов Node.js и узел (npm). Вы также узнали, как использовать API AddNpmApp для размещения приложений Node.js и приложений, выполняемых из пакета , а также файлjsonи соответственно. Наконец, вы узнали, как использовать интерфейс командной строки npm для создания Angular, Reactи Vueclient приложений и настройки их работы на разных портах.

См. также