Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/docker-and-compose/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ One multi-stage `Dockerfile` does everything the pipeline needs:
| `publish` | Publishes the Presentation project |
| `run` | The runtime image: non-root `$APP_UID`, `WORKDIR /app`, data in `/app/data`, a `HEALTHCHECK` on `/health/live` |

`docker-compose.yml` runs the app with `DOTNET_ENVIRONMENT=docker`, the `movie-reviews-data` volume a pinned OpenTelemetry Collector that receives the app's OTLP logs, traces and metrics, configured by `otel-collector.yaml`, and a pinned Aspire dashboard the collector forwards them to (`telemetry`). The dashboard UI is at <http://localhost:18888>, and the collector's OTLP ports are published on 4317 and 4318 so a `dotnet run` can send to it too. Images are built by CI but not pushed anywhere; the template ships the Dockerfile so users can.
`docker-compose.yml` runs the app with `DOTNET_ENVIRONMENT=docker`, the `movie-reviews-data` volume a pinned OpenTelemetry Collector that receives the app's OTLP logs, traces and metrics, configured by `otel-collector.yaml`, and a pinned Aspire dashboard the collector forwards them to (`telemetry`). The dashboard UI is at <http://localhost:18888>, and the collector's OTLP ports are published on 4317 and 4318 so a `dotnet run` can send to it too. The dashboard runs with `ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS` and the collector's OTLP ports take anything sent to them, on purpose: the compose file is for a developer's machine, with nothing to sign in to. Keep it that way rather than adding sign-in, and don't offer the compose file for a shared or deployed environment. Images are built by CI but not pushed anywhere; the template ships the Dockerfile so users can.

The Lambda template's `run` stage is the AWS Lambda .NET base image instead. It runs as user `65534` from `/var/task`, keeps its database in `/tmp`, and has no `HEALTHCHECK`. Its compose file runs the collector and the Aspire dashboard as well. Compose maps the runtime interface emulator to port 9000, so the function can be invoked with a `POST` to `/2015-03-31/functions/function/invocations`.

Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/template-authoring/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The package includes `src/`, `tests/`, `docs/RUN.md`, the root build files, `AGE

## Don't

- Change `identity` or `shortName`; existing installs and docs depend on them.
- Change `identity` or the first `shortName`; existing installs and docs depend on them. Adding a shorter alias after it is fine.
- Make a primary output that isn't a project visible to the CLI. The restore post action restores every primary output it can see, so `docs/RUN.md` carries the same `HostIdentifier` condition as the action that opens it.
- Add a `.sln`. The solution is `.slnx` only, and `primaryOutputs`, the Dockerfile and the package all point at it.
- Reuse a short flag across options, or give one to `--no-restore`; the `dotnet new` templates from Microsoft leave it long, and so do we.
Expand Down
8 changes: 8 additions & 0 deletions NUGET.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ A `dotnet new` template for an [AWS Lambda function](https://docs.aws.amazon.com

It's one of five [Lean Mean Clean Apps](https://leanmeancleanapps.github.io/) templates, for Minimal APIs, Model Context Protocol, GraphQL, Web API controllers and AWS Lambda. They share the same Application and Infrastructure layers and differ only in how they face the world. The full docs live at [leanmeancleanapps.github.io/lambda](https://leanmeancleanapps.github.io/lambda/).

| Template | Presentation | Package | Docs |
| --- | --- | --- | --- |
| Clean Minimal API | ASP.NET Core Minimal APIs | [CleanMinimalApi.Template](https://www.nuget.org/packages/CleanMinimalApi.Template) | [Docs](https://leanmeancleanapps.github.io/minimalapi/) |
| Clean Model Context Protocol | Model Context Protocol server | [CleanModelContextProtocol.Template](https://www.nuget.org/packages/CleanModelContextProtocol.Template) | [Docs](https://leanmeancleanapps.github.io/mcp/) |
| Clean GraphQL API | GraphQL with Hot Chocolate | [CleanGraphQLApi.Template](https://www.nuget.org/packages/CleanGraphQLApi.Template) | [Docs](https://leanmeancleanapps.github.io/graphql/) |
| Clean Web API | ASP.NET Core controllers | [CleanWebApi.Template](https://www.nuget.org/packages/CleanWebApi.Template) | [Docs](https://leanmeancleanapps.github.io/webapi/) |
| **Clean Lambda Function** | AWS Lambda, you are here | [CleanLambdaFunction.Template](https://www.nuget.org/packages/CleanLambdaFunction.Template) | [Docs](https://leanmeancleanapps.github.io/lambda/) |

## Get started

You need the [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0). [Docker](https://www.docker.com/products/docker-desktop) is optional, but it's how you run the function locally.
Expand Down
2 changes: 1 addition & 1 deletion docs/RUN.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The function always collects [OpenTelemetry](https://opentelemetry.io) traces an

Each invocation is one trace: a span for the function from the [OpenTelemetry Lambda wrapper](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/tree/main/src/OpenTelemetry.Instrumentation.AWSLambda), and one for the use case. Traces and metrics are flushed before the function returns, because Lambda can freeze the environment the moment it does.

`docker-compose.yml` also starts an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) and the [Aspire dashboard](https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone). The function sends everything to the collector, and the collector forwards it to the dashboard at <http://localhost:18888>. The dashboard is only a container that receives OTLP; nothing in the solution depends on Aspire. `otel-collector.yaml` is the collector's configuration: an OTLP receiver, the memory limiter and batch processors, and one exporter to swap for your backend.
`docker-compose.yml` also starts an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) and the [Aspire dashboard](https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone). The function sends everything to the collector, and the collector forwards it to the dashboard at <http://localhost:18888>. The dashboard is only a container that receives OTLP; nothing in the solution depends on Aspire. The dashboard has no login and the collector accepts OTLP from anyone on ports 4317 and 4318. That's on purpose for a developer's machine, so don't run this compose file anywhere other people can reach. `otel-collector.yaml` is the collector's configuration: an OTLP receiver, the memory limiter and batch processors, and one exporter to swap for your backend.

In AWS, send the function's telemetry to a collector rather than straight to a backend. Lambda container images can't use layers, so either build the [AWS Distro for OpenTelemetry](https://aws-otel.github.io/docs/getting-started/lambda) collector extension into the image, or run a collector as a gateway and point `OTEL_EXPORTER_OTLP_ENDPOINT` at it. Either way, the collector owns batching, retries and the choice of backend, X-Ray included, and changing any of that never touches the function.

Expand Down
Loading