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


Управление приложениями Node.js в .NET Aspire

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

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

Подсказка

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

Важный

Хотя эта статья посвящена частям интерфейса приложения (SPA) Single-Page, на странице Node.js представлен дополнительный пример Node.js, который демонстрирует, как серверное приложение с использованием 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 прогнозирования погоды и отображает данные в таблице.

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

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

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

Подсказка

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

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

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

npm i ./AspireJavaScript.Angular/

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

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

npm i ./AspireJavaScript.React/

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

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

npm i ./AspireJavaScript.Vue/

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

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

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

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

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

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

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

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

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

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

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

  <Sdk Name="Aspire.AppHost.Sdk" Version="9.1.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.1.0" />
    <PackageReference Include="Aspire.Hosting.NodeJs" Version="9.1.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) объявляет ресурсы клиентского приложения с помощью 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 как приложения npm.
    • Каждое клиентское приложение настроено для запуска на другом порту контейнера и использует переменную среды PORT для определения порта.
    • Все клиентские приложения также используют Dockerfile для создания контейнерного образа и настроены отображаться в манифесте публикации как контейнер из API PublishAsDockerFile.

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

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

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

  • Файл proxy.conf.js для клиента Angular.
  • Файл webpack.config.js для клиента React.
  • Файл vite.config.ts для клиента Vue.

Изучение клиента Angular

Существует несколько ключевых изменений исходного шаблона Angular. Первым является добавление файла proxy.conf.js. Этот файл используется для прокси-запросов от клиента Angular к службе 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-адресу, указанному в переменной среды.

Затем добавьте прокси-файл в файл angular.json. Обновите целевой объект serve, чтобы включить параметр proxyConfig, ссылаясь на созданный файл proxy.conf.js. Теперь Angular CLI будет использовать конфигурацию прокси-сервера при обслуживании клиентского приложения Angular.

"serve": {
  "builder": "@angular-devkit/build-angular:dev-server",
  "configurations": {
    "production": {
      "buildTarget": "weather:build:production"
    },
    "development": {
      "buildTarget": "weather:build:development"
    }
  },
  "defaultConfiguration": "development",
  "options": {
    "proxyConfig": "proxy.conf.js"
  }
},

Третье обновление — это файл package.json. Этот файл используется для настройки Angular клиента для запуска на порте, отличном от порта по умолчанию. Это достигается с помощью переменной среды 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": "^19.2.1",
    "@angular/common": "^19.2.1",
    "@angular/compiler": "^19.2.1",
    "@angular/core": "^19.2.1",
    "@angular/forms": "^19.2.1",
    "@angular/platform-browser": "^19.2.1",
    "@angular/platform-browser-dynamic": "^19.2.1",
    "@angular/router": "^19.2.1",
    "rxjs": "~7.8.2",
    "tslib": "^2.8.1",
    "zone.js": "~0.15.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^19.2.1",
    "@angular/cli": "^19.2.1",
    "@angular/compiler-cli": "^19.2.1",
    "@types/jasmine": "~5.1.7",
    "jasmine-core": "~5.6.0",
    "karma": "~6.4.4",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.1",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.8.2",
    "run-script-os": "^1.1.6"
  }
}

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

Чтобы выполнить HTTP-вызовы к службе weatherapi, необходимо настроить клиентское приложение Angular для предоставления 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()
  ]
};

Наконец, клиентское приложение Angular должно вызвать конечную точку /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 приложение работает

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

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

Изучение клиента React

Приложение React не было написано с помощью шаблона и вместо этого было написано вручную. Полный исходный код можно найти в репозитории dotnet/aspire-samples. Некоторые ключевые моменты интереса находятся в файле 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 — это точка входа для клиентского приложения React. Он использует 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 заключается в наличии папки dist с файлом bundle.js.
  • plugins установил файл src/index.html в качестве шаблона и открыл файл favicon.ico.

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

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

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

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

Изучение клиента Vue

Существует несколько ключевых изменений исходного шаблона Vue. Основными обновлениями были добавление вызова fetch в файле TheWelcome.vue для получения данных прогноза погоды из конечной точки /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. Чтобы задать порт сервера, клиентское приложение Vue использует переменную среды 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 приложение работает

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

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

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

Пример исходного кода для этой статьи предназначен для локального запуска. Каждое клиентское приложение развертывается как образ контейнера. Для создания образа контейнера используется 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;"]

Клиентские приложения в настоящее время настроены для запуска в качестве истинных SPA-приложений и не настроены для работы в режиме отрисовки на стороне сервера (SSR). Они сидят за 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.js

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

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

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

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

Полный пример серверного приложения Node.js с использованием пакета SDK для JavaScript OpenTelemetry можно найти на странице Примеры кода: .NET AspireNode.js. Рассмотрим файл примера 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 и Node Package Manager (npm). Вы также узнали, как использовать API AddNpmApp для размещения Node.js приложений и приложений, выполняемых из файла package.json соответственно. Наконец, вы узнали, как использовать интерфейс командной строки npm для создания Angular, Reactи Vue клиентских приложений, а также настройки их работы на разных портах.

См. также