Dela via


Samordna Node.js appar i .NET Aspire

I den här artikeln får du lära dig hur du använder Node.js- och Node Package Manager-appar (npm) i ett .NET.NET Aspire projekt. Exempelappen i den här artikeln visar Angular, Reactoch Vue klientupplevelser. Följande .NET.NET Aspire API:er finns för att stödja dessa scenarier – och de ingår i Aspire. Hosting.NodeJS NuGet-paket:

Skillnaden mellan dessa två API:er är att den förra används som värd för Node.js appar, medan den senare används som värd för appar som körs från en package.json fils scripts-avsnitt – och motsvarande npm run <script-name> kommando.

Tips

Exempelkällkoden för den här artikeln finns på GitHuboch det finns information på sidan Code Samples: .NET Aspire med Angular, React och Vue.

Viktig

Den här artikeln fokuserar på frontend-komponenter för Single-Page App (SPA), men det finns ett ytterligare Node.js-exempel på sidan för kodexempel: .NET AspireNode.js exempel, som visar hur du använder Node.js som en serverapp med Express.

Förutsättningar

Om du vill arbeta med .NET.NET Aspirebehöver du följande installerat lokalt:

Mer information finns i .NET.NET Aspire installation och verktygoch .NET.NET Aspire SDK.

Dessutom måste du installera Node.js på datorn. Exempelappen i den här artikeln skapades med Node.js version 20.12.2 och npm version 10.5.1. Kör följande kommandon för att verifiera dina Node.js- och npm-versioner:

node --version
npm --version

För att ladda ned Node.js (inklusive npm), se Node.js nedladdningssidan.

Klona källkodsexempel

Om du vill klona exempelkällkoden från GitHubkör du följande kommando:

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

När du har klonade lagringsplatsen går du till mappen samples/AspireWithJavaScript:

cd samples/AspireWithJavaScript

Från den här katalogen finns det sex underordnade kataloger som beskrivs i följande lista:

  • AspireJavaScript.Angular: En Angular app som använder väderprognos-API:et och visar data i en tabell.
  • AspireJavaScript.AppHost: Ett .NET.NET Aspire projekt som samordnar de andra apparna i det här exemplet. Mer information finns i .NET.NET Aspire översikt över orkestrering.
  • AspireJavaScript.MinimalApi: Ett HTTP-API som returnerar slumpmässigt genererade väderprognosdata.
  • AspireJavaScript.React: En React app som använder väderprognos-API:et och visar data i en tabell.
  • AspireJavaScript.ServiceDefaults: Standarddelade projektet för .NET.NET Aspire projekt. För mer information, se tjänstens standardvärden .NET.NET Aspire.
  • AspireJavaScript.Vue: En Vue app som använder väderprognos-API:et och visar data i en tabell.

Installera klientens beroenden

Exempelappen visar hur du använder JavaScript-klientappar som bygger på Node.js. Varje klientapp skrevs antingen med hjälp av ett npm create-mallkommando eller manuellt. I följande tabell visas de mallkommandon som används för att skapa varje klientapp, tillsammans med standardporten:

Apptyp Kommandot Skapa mall Standardport
Angular npm create @angular@latest 4200
React Det gick inte att använda en mall. PORT env var
Vue npm create vue@latest 5173

Tips

Du behöver inte köra något av dessa kommandon, eftersom exempelappen redan innehåller klienterna. I stället är detta en referenspunkt som klienterna skapades från. Mer information finns i npm-init.

Om du vill köra appen måste du först installera beroendena för varje klient. Det gör du genom att gå till varje klientmapp och köra kommandona npm install (eller installationsaliaset npm i).

Installera Angular beroenden

npm i ./AspireJavaScript.Angular/

Mer information om appen Angular finns i utforska Angular-klienten.

Installera React beroenden

npm i ./AspireJavaScript.React/

Mer information om appen React finns i utforska React-klienten.

Installera Vue beroenden

npm i ./AspireJavaScript.Vue/

Mer information om appen Vue finns i utforska Vue-klienten.

Kör exempelappen

Om du vill köra exempelappen anropar du kommandot dotnet run med orchestrator-applikationsvärden AspireJavaScript.AppHost.csproj som --project parameter:

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

Instrumentpanelen .NET.NET Aspire öppnas i din standardwebbläsare, och varje klientapplikationsslutpunkt visas i kolumnen Slutpunkter på sidan Resurser. Följande bild visar instrumentpanelen för den här exempelappen:

.NET.NET Aspire instrumentpanel med flera JavaScript-klientappar.

Tjänstslutpunkten weatherapi leder till en Swagger UI-sida som dokumenterar HTTP API:et. Varje klientapp använder den här tjänsten för att visa väderprognosdata. Du kan visa varje klientapp genom att navigera till motsvarande slutpunkt på .NET.NET Aspire instrumentpanelen. Deras skärmbilder och de ändringar som görs från mallstartpunkten beskrivs i följande avsnitt.

I samma terminalsession som du använde för att köra appen trycker du på Ctrl + C- för att stoppa appen.

Utforska appvärden

Om du vill veta hur varje klientappresurs samordnas kan du titta på appvärdprojektet. Appvärden kräver NuGet-paketet Aspire.Hosting.NodeJS för att vara värd för apparna 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>

Projektfilen definierar också ett byggmål som säkerställer att npm-beroendena installeras innan appvärden skapas. Appens värdkod (Program.cs) deklarerar klientappresurserna med hjälp av AddNpmApp(IDistributedApplicationBuilder, String, String, String, String[]) API:t.

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();

Föregående kod:

  • Skapar en DistributedApplicationBuilder.
  • Lägger till tjänsten "weatherapi" som ett projekt till appvärden.
    • Markerar HTTP-slutpunkterna som externa.
  • Med en referens till "weatherapi"-tjänsten lägger till klientapparna "angular", "react" och "vue" som npm-appar.
    • Varje klientapp är konfigurerad att köras på en annan containerport och använder PORT miljövariabeln för att fastställa porten.
    • Alla klientappar förlitar sig också på en Dockerfile för att skapa sin containeravbildning och är konfigurerade för att uttrycka sig i publiceringsmanifestet som en container från PublishAsDockerFile-API:et.

Mer information om nätverk i inre loopar finns i .NET.NET Aspire översikt över inre loopnätverk. Mer information om hur du distribuerar appar finns i .NET.NET Aspire manifestformat för distributionsverktygsbyggare.

När appvärden samordnar lanseringen av varje klientapp använder den kommandot npm run start. Det här kommandot definieras i avsnittet scripts i package.json-filen för varje klientapp. Skriptet start används för att starta klientappen på den angivna porten. Varje klientapp förlitar sig på en proxy för att begära "weatherapi"-tjänsten.

Proxyn har konfigurerats i:

  • Filen proxy.conf.js för Angular-klienten.
  • Filen webpack.config.js för React-klienten.
  • Den vite.config.ts fil för Vue-klienten.

Utforska Angular-klienten

Det finns flera viktiga ändringar från den ursprungliga Angular mallen. Den första är tillägget av en proxy.conf.js fil. Den här filen används för proxybegäranden från Angular-klienten till tjänsten "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 appvärden anger services__weatherapi__http__0-miljövariabeln som används för att anropa tjänstslutpunkten "weatherapi". Den föregående konfigurationen dirigerar om HTTP-begäranden som börjar med /api till måladressen som anges i miljövariabeln.

Den andra uppdateringen är till filen package.json. Den här filen används för att konfigurera den Angular klienten så att den körs på en annan port än standardporten. Detta uppnås med hjälp av miljövariabeln PORT och run-script-os npm-paketet för att ange porten.

{
  "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.1.4",
    "@angular/common": "^19.1.4",
    "@angular/compiler": "^19.1.4",
    "@angular/core": "^19.1.4",
    "@angular/forms": "^19.1.4",
    "@angular/platform-browser": "^19.1.4",
    "@angular/platform-browser-dynamic": "^19.1.4",
    "@angular/router": "^19.1.4",
    "rxjs": "~7.8.1",
    "tslib": "^2.8.1",
    "zone.js": "~0.15.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^19.1.4",
    "@angular/cli": "^19.1.4",
    "@angular/compiler-cli": "^19.1.4",
    "@types/jasmine": "~5.1.5",
    "jasmine-core": "~5.5.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.7.3",
    "run-script-os": "^1.1.6"
  }
}

Avsnittet scripts i package.json-filen används för att definiera skriptet start. Det här skriptet används av kommandot npm start för att starta Angular-klientappen. Skriptet start är konfigurerat att använda run-script-os-paketet för att ställa in porten, vilket delegerar till ng serve-kommandot genom att skicka den passande --port-växeln baserat på OS-lämplig syntax.

För att kunna göra HTTP-anrop till tjänsten "weatherapi" måste Angular-klientappen konfigureras för att tillhandahålla AngularHttpClient för beroendeinjektion. Detta uppnås med hjälp av hjälpfunktionen provideHttpClient när programmet konfigureras i app.config.ts-filen.

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()
  ]
};

Slutligen måste Angular-klientappen anropa /api/WeatherForecast slutpunkten för att hämta väderprognosdata. Det finns flera HTML-, CSS- och TypeScript-uppdateringar, som alla görs till följande filer:

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 appen är igång

För att visualisera Angular-klientappen, navigera till 'angular'-slutpunkten i .NET Aspire:s instrumentpanel. Följande bild visar Angular-klientappen:

Angular klientapp med falska prognostiserade väderdata som visas som en tabell.

Utforska React-klienten

Den React appen skrevs inte med hjälp av en mall och skrevs i stället manuellt. Den fullständiga källkoden finns på lagringsplatsen dotnet/aspire-samples. Några av de viktigaste intressanta punkterna finns i filen 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;

Funktionen App är startpunkten för React-klientappen. Den använder hookar useState och useEffect för att hantera tillståndet av de väderprognosdata. fetch-API:et används för att göra en HTTP-begäran till /api/WeatherForecast slutpunkten. Svaret konverteras sedan till JSON och anges som tillstånd för väderprognosdata.

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"],
        },
      ],
    },
  };
};

Koden ovan definierar module.exports enligt följande:

  • Egenskapen entry är inställd på filen src/index.js.
  • devServer förlitar sig på en proxy för att vidarebefordra begäranden till tjänsten "weatherapi", anger porten till PORT miljövariabel och tillåter alla värdar.
  • output resulterar i en dist mapp med en bundle.js fil.
  • plugins ange filen src/index.html som mall och exponera favicon.ico-filen.

De sista uppdateringarna gäller följande filer:

React appen är igång

Om du vill visualisera React-klientappen, gå till slutpunkten "react" i .NET Aspire:s instrumentpanel. Följande bild visar React-klientappen:

React klientapp med falska prognostiserade väderdata som visas som en tabell.

Utforska Vue-klienten

Det finns flera viktiga ändringar från den ursprungliga Vue mallen. De primära uppdateringarna inkluderade tillägget av fetch-anropet i filen TheWelcome.vue för att hämta väderprognosdata från slutpunkten /api/WeatherForecast. Följande kodfragment visar fetch-anropet:

<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>

Eftersom TheWelcome integration är mounted, så anropas /api/weatherforecast slutpunkten för att hämta väderprognosdata. Svaret ställs sedan in som dataegenskapen forecasts. För att ange serverporten använder Vue-klientappen PORT miljövariabeln. Detta uppnås genom att uppdatera vite.config.ts-filen:

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
      }
    }
  }
})

Dessutom anger Vite-konfigurationen egenskapen server.proxy för att vidarebefordra begäranden till tjänsten "weatherapi". Detta uppnås med hjälp av miljövariabeln services__weatherapi__http__0, som anges av .NET.NET Aspire appvärd.

Den sista uppdateringen från mallen görs till filen TheWelcome.vue. Den här filen anropar /api/WeatherForecast slutpunkten för att hämta väderprognosdata och visar data i en tabell. Den innehåller CSS-, HTML- och TypeScript-uppdateringar.

Vue appen är igång

Om du vill visualisera Vue-klientappen, navigera till slutpunkten "vue" i .NET Aspire-instrumentpanelen. Följande bild visar Vue-klientappen:

Vue klientapp med falska prognostiserade väderdata som visas som en tabell.

Distributionsöverväganden

Exempelprogramkoden för den här artikeln är utformad för att köras lokalt. Varje klientapp distribueras som en containeravbildning. Dockerfile för varje klientapp används för att skapa containeravbildningen. Varje Dockerfile är identisk och använder en flerstegsbyggprocess för att skapa en produktionsklar containerbild.

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;"]

Klientapparna är för närvarande konfigurerade att köras som sanna SPA-appar och är inte konfigurerade att köras i ett återgivet läge på serversidan (SSR). De sitter bakom nginx, som används för att hantera statiska filer. De använder en default.conf.template-fil för att konfigurera nginx för att skicka vidare förfrågningar till klientappen.

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-serverapp överväganden

Även om den här artikeln fokuserar på klientappar kan du ha scenarier där du behöver vara värd för en Node.js serverapp. Samma semantik krävs för att vara värd för en Node.js serverapp som en SPA-klientapp. .NET .NET Aspire-appvärden kräver en paketreferens till Aspire.Hosting.NodeJS NuGet-paketet och koden måste anropa antingen AddNodeApp eller AddNpmApp. Dessa API:erna är användbara för att lägga till befintliga JavaScript-appar till .NET.NET Aspire appvärdsmiljö.

När du konfigurerar hemligheter och skickar miljövariabler till JavaScript-baserade appar, oavsett om de är klient- eller serverappar, använder du parametrar. Mer information finns i .NET.NET Aspire: Externa parametrar – hemligheter.

Använda OpenTelemetry JavaScript SDK

Om du vill exportera OpenTelemetry loggar, spårningar och mått från en Node.js serverapp använder du OpenTelemetry JavaScript SDK.

Ett komplett exempel på en Node.js-serverapp med OpenTelemetry JavaScript SDK kan du hitta på Kodexempel: .NET AspireNode.js exempel sidan. Överväg exemplets instrumentation.js-fil, som visar hur du konfigurerar OpenTelemetry JavaScript SDK för att exportera loggar, spårningar och mått:

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();
}

Tips

För att konfigurera OTEL CORS-inställningarna för .NET.NET Aspire instrumentpanelen, se sidan för .NET.NET Aspire OTEL CORS-inställningar på instrumentpanelen.

Sammanfattning

Det finns flera saker som ligger utanför den här artikelns omfång, men du har lärt dig hur du skapar .NET Aspire projekt som använder Node.js och Node Package Manager (npm). Du har också lärt dig hur du använder AddNpmApp API:er som värd för Node.js appar och appar som körs från en package.json fil. Slutligen lärde du dig hur du använder npm CLI för att skapa Angular, Reactoch Vue klientappar och hur du konfigurerar dem att köras på olika portar.

Se även