Skip to content
This repository has been archived by the owner on Nov 20, 2023. It is now read-only.

Seq Extension #513

Merged
merged 8 commits into from
Jun 13, 2020
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
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.


Expand Down
File renamed without changes.
50 changes: 50 additions & 0 deletions docs/recipes/logging_seq.md
Original file line number Diff line number Diff line change
@@ -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.


<img width="1103" alt="image" src="https://user-images.githubusercontent.com/1769935/83251452-f26ffa00-a1ec-11ea-9642-29e4ec579178.png">

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:

<img width="1515" alt="image" src="https://user-images.githubusercontent.com/1769935/83251005-4cbc8b00-a1ec-11ea-9c76-b7e6db2ef73b.png">

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:

<img width="1101" alt="image" src="https://user-images.githubusercontent.com/1769935/83252026-e46ea900-a1ed-11ea-9b96-38695c42dab4.png">
88 changes: 88 additions & 0 deletions src/Microsoft.Tye.Extensions/Seq/SeqExtensions.cs
Original file line number Diff line number Diff line change
@@ -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<DotnetProjectServiceBuilder>())
{
var sidecar = DiagnosticAgent.GetOrAddSidecar(project);

// Use service discovery to find seq
sidecar.Args.Add("--provider:seq=service:seq");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn’t find much information on how this sidecar is implemented. (Maybe the code is in the repository and I totally overlooked it?)

However, I followed the existing patterns from the Elastic extensions and the logs did indeed get pushed into Seq.

—-

I did test this using the Frontend-backend example and that is how I provided the screenshots.

I will have a 2nd look to see if I can write up some sort of test to verify more of this functionality

Copy link
Contributor Author

@razfriman razfriman May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you deploy and see if it worked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't have a Kubernetes cluster set up (locally or cloud). Is there any other way to test to see if this works?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not today, we don't support other deployment targets nor do we have CI tests which run with kubernetes. We are working on getting some of that bootstrapped soon.

See https://github.com/dotnet/tye/blob/master/docs/tutorials/hello-tye/01_deploy.md#getting-started-with-deployment for some guidance on how to a cluster setup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code for the sidecar is here if you want to peep it: https://github.com/dotnet/tye/tree/master/src/tye-diag-agent

sidecar.Dependencies.Add("seq");
}
}

return Task.CompletedTask;
}
}
}
2 changes: 2 additions & 0 deletions src/Microsoft.Tye.Extensions/WellKnownExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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
Expand All @@ -16,6 +17,7 @@ public static class WellKnownExtensions
{
{ "dapr", new DaprExtension() },
{ "elastic", new ElasticStackExtension() },
{ "seq", new SeqExtension() },
{ "zipkin", new ZipkinExtension() },
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Tye.Hosting.Diagnostics/LoggingSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public IDisposable Attach(EventPipeEventSource source, ReplicaInfo replicaInfo)
}

// 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) &&
Expand Down