diff --git a/docs/README.md b/docs/README.md
index 69ce9c74..57a036d2 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -16,7 +16,8 @@
|-------|------------|
|**[Using Ingress](recipes/ingress.md)** | Using `tye` with an ingress for serving public traffic.
|**[Using Distributed Tracing](recipes/distributed_tracing.md)** | Using zipkin for distributed tracing.
-|**[Logging with Elastic Stack](recipes/logging.md)** | Using Elastic Stack for logging.
+|**[Logging with Elastic Stack](recipes/logging_elastic.md)** | Using Elastic Stack for logging.
+|**[Logging with Seq](recipes/logging_seq.md)** | Using Seq for logging.
|**[Using Dapr with Tye](recipes/dapr.md)** | Using `tye` for local development and deployment with a [Dapr](https://dapr.io) application.
diff --git a/docs/recipes/logging.md b/docs/recipes/logging_elastic.md
similarity index 100%
rename from docs/recipes/logging.md
rename to docs/recipes/logging_elastic.md
diff --git a/docs/recipes/logging_seq.md b/docs/recipes/logging_seq.md
new file mode 100644
index 00000000..93ec0ac7
--- /dev/null
+++ b/docs/recipes/logging_seq.md
@@ -0,0 +1,50 @@
+# Logging with Seq
+
+Seq is a popular log-aggregation system that gives you a powerful log search and dashboard engine with views across all of your services.
+
+Tye can push logs to Seq easily without the need for any SDKs or code changes in your services.
+
+## Getting started: running locally with Seq
+
+> :bulb: If you want an existing sample to run, the [sample here](https://github.com/dotnet/tye/tree/master/samples/frontend-backend) will do. This recipe will show examples of UI and data based on that sample. You own application will work fine, but the data and examples will look different.
+
+The first step is to add the `seq` extension to your `tye.yaml`. Add the `extensions` node and its children from the example below.
+
+```yaml
+name: frontend-backend
+
+extensions:
+- name: seq
+ logPath: ./.logs
+
+services:
+- name: backend
+ project: backend/backend.csproj
+- name: frontend
+ project: frontend/frontend.csproj
+```
+
+The `logPath` property here configures the path where Seq will store its data.
+
+Now launch the application with Tye:
+
+```sh
+tye run
+```
+
+If you navigate to the Tye dashboard you should see an extra service (`seq`) in the list of services.
+
+
+
+
+Visit the first URI (`http://localhost:5341`) in your browser to access the Seq dashboard.
+
+Now you're ready to view the data! After it loads, it should look like the screenshot below:
+
+
+
+Now you can see the logs from your application with each field broken out into structured format. If you take advantage of [structured logging](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1#log-message-template) then you'll see your own data included in structured form here alongside framework logs.
+
+It should like the screenshot below:
+
+
diff --git a/src/Microsoft.Tye.Extensions/Seq/SeqExtensions.cs b/src/Microsoft.Tye.Extensions/Seq/SeqExtensions.cs
new file mode 100644
index 00000000..d259c98c
--- /dev/null
+++ b/src/Microsoft.Tye.Extensions/Seq/SeqExtensions.cs
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.Tye.Extensions.Seq
+{
+ internal sealed class SeqExtension : Extension
+ {
+ public override Task ProcessAsync(ExtensionContext context, ExtensionConfiguration config)
+ {
+ if (context.Application.Services.Any(s => s.Name == "seq"))
+ {
+ context.Output.WriteDebugLine("seq service already configured. Skipping...");
+ }
+ else
+ {
+ context.Output.WriteDebugLine("Injecting seq service...");
+
+ var seq = new ContainerServiceBuilder("seq", "datalust/seq")
+ {
+ EnvironmentVariables =
+ {
+ new EnvironmentVariableBuilder("ACCEPT_EULA")
+ {
+ Value = "Y"
+ },
+ },
+ Bindings =
+ {
+ new BindingBuilder()
+ {
+ Port = 5341,
+ ContainerPort = 80,
+ Protocol = "http",
+ },
+ },
+ };
+ context.Application.Services.Add(seq);
+
+ if (config.Data.TryGetValue("logPath", out var obj) &&
+ obj is string logPath &&
+ !string.IsNullOrEmpty(logPath))
+ {
+ seq.Volumes.Add(new VolumeBuilder(logPath, "seq-data", "/data"));
+ }
+
+ foreach (var s in context.Application.Services)
+ {
+ if (object.ReferenceEquals(s, seq))
+ {
+ continue;
+ }
+
+ // make seq available as a dependency of everything.
+ if (!s.Dependencies.Contains(seq.Name))
+ {
+ s.Dependencies.Add(seq.Name);
+ }
+ }
+ }
+
+ if (context.Operation == ExtensionContext.OperationKind.LocalRun)
+ {
+ if (context.Options!.LoggingProvider is null)
+ {
+ // For local development we hardcode the port and hostname
+ context.Options.LoggingProvider = "seq=http://localhost:5341";
+ }
+ }
+ else if (context.Operation == ExtensionContext.OperationKind.Deploy)
+ {
+ foreach (var project in context.Application.Services.OfType())
+ {
+ var sidecar = DiagnosticAgent.GetOrAddSidecar(project);
+
+ // Use service discovery to find seq
+ sidecar.Args.Add("--provider:seq=service:seq");
+ sidecar.Dependencies.Add("seq");
+ }
+ }
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/src/Microsoft.Tye.Extensions/WellKnownExtensions.cs b/src/Microsoft.Tye.Extensions/WellKnownExtensions.cs
index 4457b179..ecbe5740 100644
--- a/src/Microsoft.Tye.Extensions/WellKnownExtensions.cs
+++ b/src/Microsoft.Tye.Extensions/WellKnownExtensions.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using Microsoft.Tye.Extensions.Dapr;
using Microsoft.Tye.Extensions.Elastic;
+using Microsoft.Tye.Extensions.Seq;
using Microsoft.Tye.Extensions.Zipkin;
namespace Microsoft.Tye.Extensions
@@ -16,6 +17,7 @@ namespace Microsoft.Tye.Extensions
{
{ "dapr", new DaprExtension() },
{ "elastic", new ElasticStackExtension() },
+ { "seq", new SeqExtension() },
{ "zipkin", new ZipkinExtension() },
};
}
diff --git a/src/Microsoft.Tye.Hosting.Diagnostics/LoggingSink.cs b/src/Microsoft.Tye.Hosting.Diagnostics/LoggingSink.cs
index 394e47e1..01e0de22 100644
--- a/src/Microsoft.Tye.Hosting.Diagnostics/LoggingSink.cs
+++ b/src/Microsoft.Tye.Hosting.Diagnostics/LoggingSink.cs
@@ -170,7 +170,7 @@ namespace Microsoft.Tye.Hosting.Diagnostics
}
// This is the logger factory for application logs. It allows re-routing event pipe collected logs (structured logs)
- // to any of the supported sinks, currently (elastic search and app insights)
+ // to any of the supported sinks, currently (elastic search, console, seq, and app insights)
private void ConfigureLogging(string serviceName, string replicaName, ILoggingBuilder builder)
{
if (string.Equals(_provider.Key, "elastic", StringComparison.OrdinalIgnoreCase) &&