This commit is contained in:
Jonathan Allen
2024-01-05 12:46:31 -07:00
16 changed files with 332 additions and 251 deletions

View File

@@ -2,6 +2,7 @@ using LocalModels;
public class RubricMarkdownTests public class RubricMarkdownTests
{ {
[Test] [Test]
public void TestCanParseOneItem() public void TestCanParseOneItem()
{ {
@@ -15,6 +16,7 @@ public class RubricMarkdownTests
rubric.First().Label.Should().Be("this is the task"); rubric.First().Label.Should().Be("this is the task");
rubric.First().Points.Should().Be(2); rubric.First().Points.Should().Be(2);
} }
[Test] [Test]
public void TestCanParseMultipleItems() public void TestCanParseMultipleItems()
{ {
@@ -29,6 +31,7 @@ public class RubricMarkdownTests
rubric.ElementAt(1).Label.Should().Be("this is the other task"); rubric.ElementAt(1).Label.Should().Be("this is the other task");
rubric.ElementAt(1).Points.Should().Be(3); rubric.ElementAt(1).Points.Should().Be(3);
} }
[Test] [Test]
public void TestCanParseSinglePoint() public void TestCanParseSinglePoint()
{ {
@@ -41,6 +44,7 @@ public class RubricMarkdownTests
rubric.First().Label.Should().Be("this is the task"); rubric.First().Label.Should().Be("this is the task");
rubric.First().Points.Should().Be(1); rubric.First().Points.Should().Be(1);
} }
[Test] [Test]
public void TestCanParseSingleExtraCredit_LowerCase() public void TestCanParseSingleExtraCredit_LowerCase()
{ {

View File

@@ -0,0 +1,14 @@
public static class ConfigurationSetup
{
public static void Canvas(WebApplicationBuilder builder)
{
var canvas_token = builder.Configuration["CANVAS_TOKEN"] ?? throw new Exception("CANVAS_TOKEN is null");
var canvas_url = builder.Configuration["CANVAS_URL"];
if (canvas_url == null)
{
Console.WriteLine("CANVAS_URL is null, defaulting to https://snow.instructure.com");
builder.Configuration["CANVAS_URL"] = "https://snow.instructure.com";
}
}
}

View File

@@ -0,0 +1,20 @@
using System.Diagnostics;
using OpenTelemetry;
public class CustomConsoleExporter : BaseExporter<Activity>
{
public override ExportResult Export(in Batch<Activity> batch)
{
using var scope = SuppressInstrumentationScope.Begin();
foreach (var activity in batch)
{
string[] ignoreOperations = [
"Microsoft.AspNetCore.Hosting.HttpRequestIn",
];
if (!ignoreOperations.Contains(activity.OperationName))
Console.WriteLine($"{activity.OperationName}: {activity.DisplayName}");
}
return ExportResult.Success;
}
}

View File

@@ -18,37 +18,30 @@ using OpenTelemetry.Logs;
using OpenTelemetry.Metrics; using OpenTelemetry.Metrics;
using OpenTelemetry.Resources; using OpenTelemetry.Resources;
using OpenTelemetry.Trace; using OpenTelemetry.Trace;
using OpenTelemetry;
DotEnv.Load(); DotEnv.Load();
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
var canvas_token = builder.Configuration["CANVAS_TOKEN"]; ConfigurationSetup.Canvas(builder);
if (canvas_token == null)
throw new Exception("CANVAS_TOKEN is null");
var canvas_url = builder.Configuration["CANVAS_URL"];
if (canvas_url == null)
{
Console.WriteLine("CANVAS_URL is null, defaulting to https://snow.instructure.com");
builder.Configuration["CANVAS_URL"] = "https://snow.instructure.com";
}
const string serviceName = "canvas-management"; const string serviceName = "canvas-management";
// builder.Logging.AddOpenTelemetry(options => builder.Logging.AddOpenTelemetry(options =>
// { {
// options options
// .SetResourceBuilder( .SetResourceBuilder(
// ResourceBuilder ResourceBuilder
// .CreateDefault() .CreateDefault()
// .AddService(serviceName) .AddService(serviceName)
// ) )
// .AddOtlpExporter(o => .AddOtlpExporter(o =>
// { {
// o.Endpoint = new Uri("http://localhost:4317/"); o.Endpoint = new Uri("http://localhost:4317/");
// }) });
// .AddConsoleExporter(); // .AddConsoleExporter();
// }); });
builder.Services.AddOpenTelemetry() builder.Services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService(serviceName)) .ConfigureResource(resource => resource.AddService(serviceName))
@@ -59,15 +52,16 @@ builder.Services.AddOpenTelemetry()
o.Endpoint = new Uri("http://localhost:4317/"); o.Endpoint = new Uri("http://localhost:4317/");
}) })
.AddAspNetCoreInstrumentation() .AddAspNetCoreInstrumentation()
.AddConsoleExporter() .AddProcessor(new BatchActivityExportProcessor(new CustomConsoleExporter()))
); )
// .WithMetrics(metrics => metrics .WithMetrics(metrics => metrics
// .AddOtlpExporter(o => { .AddOtlpExporter(o =>
// o.Endpoint = new Uri("http://localhost:4317/"); {
// }) o.Endpoint = new Uri("http://localhost:4317/");
// .AddAspNetCoreInstrumentation() }
// .AddConsoleExporter() )
// ); .AddAspNetCoreInstrumentation()
);
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
@@ -133,3 +127,4 @@ foreach (var address in addresses)
} }
app.WaitForShutdown(); app.WaitForShutdown();

View File

@@ -34,6 +34,9 @@
private string name { get; set; } = String.Empty; private string name { get; set; } = String.Empty;
private bool addingAssignmentToCanvas = false; private bool addingAssignmentToCanvas = false;
private bool deletingAssignmentFromCanvas = false; private bool deletingAssignmentFromCanvas = false;
private bool showHelp = false;
private void toggleHelp() => showHelp = !showHelp;
private void submitHandler() private void submitHandler()
{ {
@@ -157,9 +160,6 @@
deletingAssignmentFromCanvas = false; deletingAssignmentFromCanvas = false;
StateHasChanged(); StateHasChanged();
} }
private bool showHelp { get; set; } = false;
} }
<div class="d-flex flex-column p-2 h-100 w-100" style="height: 100%;" > <div class="d-flex flex-column p-2 h-100 w-100" style="height: 100%;" >
@@ -170,7 +170,7 @@
<section class="flex-grow-1 p-1 border rounded-4 bg-dark-subtle" style="min-height: 0;"> <section class="flex-grow-1 p-1 border rounded-4 bg-dark-subtle" style="min-height: 0;">
@if (assignmentContext.Assignment != null) @if (assignmentContext.Assignment != null)
{ {
@* <AssignmentMarkdownEditor ShowHelp="@showhelp" /> *@ <AssignmentMarkdownEditor ShowHelp=@showHelp />
} }
</section> </section>
@@ -182,7 +182,7 @@
</div> </div>
} }
<button class="btn btn-outline-secondary mx-3" @onclick="() => showHelp = !showHelp"> <button class="btn btn-outline-secondary mx-3" @onclick=toggleHelp>
Toggle Help Toggle Help
</button> </button>
<ConfirmationModal Label="Delete" Class="btn btn-danger" OnConfirmAsync="HandleDelete" /> <ConfirmationModal Label="Delete" Class="btn btn-danger" OnConfirmAsync="HandleDelete" />

View File

@@ -1,4 +1,5 @@
@using Markdig @using Markdig
@using Shared.Components.AssignmentForm
@inject CoursePlanner planner @inject CoursePlanner planner
@inject AssignmentEditorContext assignmentContext @inject AssignmentEditorContext assignmentContext
@@ -64,20 +65,30 @@
private MarkupString preview { get => (MarkupString)Markdown.ToHtml(assignmentContext?.Assignment?.Description ?? ""); } private MarkupString preview { get => (MarkupString)Markdown.ToHtml(assignmentContext?.Assignment?.Description ?? ""); }
private string HelpText() private string HelpText()
{ {
var groupNames = string.Join(", " , planner.LocalCourse?.Settings.AssignmentGroups.Select(g => g.Name)); var groupNames = string.Join("\n- " , planner.LocalCourse?.Settings.AssignmentGroups.Select(g => g.Name) ?? []);
return $@" return $@"
SubmissionTypes: SubmissionTypes:
- {AssignmentSubmissionType.ONLINE_TEXT_ENTRY} - {AssignmentSubmissionType.ONLINE_TEXT_ENTRY}
- {AssignmentSubmissionType.ONLINE_UPLOAD} - {AssignmentSubmissionType.ONLINE_UPLOAD}
Assignment Group Names: Assignment Group Names:
{groupNames} - {groupNames}
"; ";
} }
} }
@if(assignmentContext.Assignment != null && planner.LocalCourse != null) <div class="d-flex w-100 h-100 flex-row">
{ @if(ShowHelp)
{
<div class=" rounded rounded-3 bg-black" >
<pre class=" me-3 pe-5 ps-3 rounded rounded-3">
@HelpText()
</pre>
</div>
}
@if(assignmentContext.Assignment != null && planner.LocalCourse != null)
{
<div class="row h-100 w-100"> <div class="row h-100 w-100">
<div class="col-6"> <div class="col-6">
@@ -108,4 +119,5 @@ Assignment Group Names:
<RubricDisplay /> <RubricDisplay />
</div> </div>
</div> </div>
} }
</div>

View File

@@ -98,7 +98,12 @@
</div> </div>
</div> </div>
@if(existsInCanvas && NeedsToBeUpdatedInCanvas) @if(
planner.LocalCourse != null
&& existsInCanvas
&& NeedsToBeUpdatedInCanvas
&& assignmentInCanvas != null
)
{ {
<div class="mx-3 text-body-tertiary"> <div class="mx-3 text-body-tertiary">
@Assignment.GetUpdateReason( @Assignment.GetUpdateReason(

View File

@@ -2,7 +2,7 @@
"DetailedErrors": true, "DetailedErrors": true,
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Error",
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Trace", "Default": "Error",
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },

View File

@@ -0,0 +1,10 @@
namespace LocalModels;
public class RubricMarkdownParseException : Exception
{
public RubricMarkdownParseException(string message) : base(message) { }
}
public class AssignmentMarkdownParseException : Exception
{
public AssignmentMarkdownParseException(string message) : base(message) { }
}

View File

@@ -40,7 +40,6 @@ public record LocalAssignment
public string GetDescriptionHtml() public string GetDescriptionHtml()
{ {
var rubricHtml = GetRubricHtml(); var rubricHtml = GetRubricHtml();
return Markdig.Markdown.ToHtml(Description) + "<hr>" + rubricHtml; return Markdig.Markdown.ToHtml(Description) + "<hr>" + rubricHtml;
} }
@@ -49,170 +48,8 @@ public record LocalAssignment
.FirstOrDefault(g => g.Name == LocalAssignmentGroupName)? .FirstOrDefault(g => g.Name == LocalAssignmentGroupName)?
.CanvasId; .CanvasId;
public string ToMarkdown() => this.AssignmentToMarkdown();
public string ToYaml() public string RubricToMarkdown() => this.AssignmentRubricToMarkdown();
{ public static LocalAssignment ParseMarkdown(string input) => LocalAssignmentMarkdownParser.ParseMarkdown(input);
var serializer = new SerializerBuilder().DisableAliases().Build(); public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown) => LocalAssignmentMarkdownParser.ParseRubricMarkdown(rawMarkdown);
var yaml = serializer.Serialize(this);
return yaml;
}
public static LocalAssignment ParseMarkdown(string input)
{
var settingsString = input.Split("---")[0];
var (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt) = parseSettings(settingsString);
var description = input.Split("---\n")[1].Split("## Rubric")[0];
var rubricString = input.Split("## Rubric\n")[1];
var rubric = ParseRubricMarkdown(rubricString);
return new LocalAssignment()
{
Name = name.Trim(),
LocalAssignmentGroupName = localAssignmentGroupName.Trim(),
SubmissionTypes = submissionTypes,
DueAt = dueAt,
LockAt = lockAt,
Rubric = rubric,
Description = description.Trim()
};
}
private static (string name, string assignmentGroupName, List<string> submissionTypes, DateTime dueAt, DateTime? lockAt) parseSettings(string input)
{
var name = extractLabelValue(input, "Name");
var rawLockAt = extractLabelValue(input, "LockAt");
var rawDueAt = extractLabelValue(input, "DueAt");
var localAssignmentGroupName = extractLabelValue(input, "AssignmentGroupName");
var submissionTypes = parseSubmissionTypes(input);
DateTime? lockAt = DateTime.TryParse(rawLockAt, out DateTime parsedLockAt)
? parsedLockAt
: null;
var dueAt = DateTime.TryParse(rawDueAt, out DateTime parsedDueAt)
? parsedDueAt
: throw new QuizMarkdownParseException($"Error with DueAt: {rawDueAt}");
return (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt);
}
private static List<string> parseSubmissionTypes(string input)
{
input = input.Replace("\r\n", "\n");
List<string> submissionTypes = new List<string>();
// Define a regular expression pattern to match the bulleted list items
string startOfTypePattern = @"- (.+)";
Regex regex = new Regex(startOfTypePattern);
var words = input.Split("SubmissionTypes:");
var inputAfterSubmissionTypes = words[1];
string[] lines = inputAfterSubmissionTypes.Split("\n", StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
string trimmedLine = line.Trim();
Match match = regex.Match(trimmedLine);
if (!match.Success)
break;
string type = match.Groups[1].Value.Trim();
submissionTypes.Add(type);
}
return submissionTypes;
}
static string extractLabelValue(string input, string label)
{
string pattern = $@"{label}: (.*?)\n";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
return match.Groups[1].Value;
}
return string.Empty;
}
public string ToMarkdown()
{
var settingsMarkdown = settingsToMarkdown();
var rubricMarkdown = RubricToMarkdown();
var assignmentMarkdown =
settingsMarkdown + "\n"
+ "---\n\n"
+ Description + "\n\n"
+ "## Rubric\n\n"
+ rubricMarkdown;
return assignmentMarkdown;
}
public string RubricToMarkdown()
{
var builder = new StringBuilder();
foreach (var item in Rubric)
{
var pointLabel = item.Points > 1 ? "pts" : "pt";
builder.Append($"- {item.Points}{pointLabel}: {item.Label}" + "\n");
}
return builder.ToString();
}
private string settingsToMarkdown()
{
var builder = new StringBuilder();
builder.Append($"Name: {Name}" + "\n");
builder.Append($"LockAt: {LockAt}" + "\n");
builder.Append($"DueAt: {DueAt}" + "\n");
builder.Append($"AssignmentGroupName: {LocalAssignmentGroupName}" + "\n");
builder.Append($"SubmissionTypes:" + "\n");
foreach (var submissionType in SubmissionTypes)
{
builder.Append($"- {submissionType}" + "\n");
}
return builder.ToString();
}
public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown)
{
if (rawMarkdown.Trim() == string.Empty)
return [];
var lines = rawMarkdown.Trim().Split("\n");
var items = lines.Select(parseIndividualRubricItemMarkdown).ToArray();
return items;
}
private static RubricItem parseIndividualRubricItemMarkdown(string rawMarkdown)
{
var pointsPattern = @"\s*-\s*(\d+)\s*pt(s)?:";
var match = Regex.Match(rawMarkdown, pointsPattern);
if (!match.Success)
throw new RubricMarkdownParseException($"points not found: {rawMarkdown}");
var points = int.Parse(match.Groups[1].Value);
var label = string.Join(": ", rawMarkdown.Split(": ").Skip(1));
return new RubricItem()
{
Points = points,
Label = label
};
}
}
public class RubricMarkdownParseException : Exception
{
public RubricMarkdownParseException(string message) : base(message) { }
}
public class AssignmentMarkdownParseException : Exception
{
public AssignmentMarkdownParseException(string message) : base(message) { }
} }

View File

@@ -0,0 +1,50 @@
using System.Text;
using LocalModels;
namespace LocalModels;
public static class LocalAssignmentMarkdownCreator
{
public static string AssignmentToMarkdown(this LocalAssignment assignment)
{
var settingsMarkdown = assignment.settingsToMarkdown();
var rubricMarkdown = assignment.RubricToMarkdown();
var assignmentMarkdown =
settingsMarkdown + "\n"
+ "---\n\n"
+ assignment.Description + "\n\n"
+ "## Rubric\n\n"
+ rubricMarkdown;
return assignmentMarkdown;
}
public static string AssignmentRubricToMarkdown(this LocalAssignment assignment)
{
var builder = new StringBuilder();
foreach (var item in assignment.Rubric)
{
var pointLabel = item.Points > 1 ? "pts" : "pt";
builder.Append($"- {item.Points}{pointLabel}: {item.Label}" + "\n");
}
return builder.ToString();
}
private static string settingsToMarkdown(this LocalAssignment assignment)
{
var printableDueDate = assignment.DueAt.ToString().Replace('\u202F', ' ');
var printableLockAt = assignment.LockAt?.ToString().Replace('\u202F', ' ') ?? "";
var builder = new StringBuilder();
builder.Append($"Name: {assignment.Name}" + "\n");
builder.Append($"LockAt: {printableLockAt}" + "\n");
builder.Append($"DueAt: {printableDueDate}" + "\n");
builder.Append($"AssignmentGroupName: {assignment.LocalAssignmentGroupName}" + "\n");
builder.Append($"SubmissionTypes:" + "\n");
foreach (var submissionType in assignment.SubmissionTypes)
{
builder.Append($"- {submissionType}" + "\n");
}
return builder.ToString();
}
}

View File

@@ -0,0 +1,120 @@
using System.Text.RegularExpressions;
namespace LocalModels;
public static class LocalAssignmentMarkdownParser
{
public static LocalAssignment ParseMarkdown(string input)
{
var settingsString = input.Split("---")[0];
var (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt) = parseSettings(settingsString);
var description = input.Split("---\n")[1].Split("## Rubric")[0];
var rubricString = input.Split("## Rubric\n")[1];
var rubric = ParseRubricMarkdown(rubricString);
return new LocalAssignment()
{
Name = name.Trim(),
LocalAssignmentGroupName = localAssignmentGroupName.Trim(),
SubmissionTypes = submissionTypes,
DueAt = dueAt,
LockAt = lockAt,
Rubric = rubric,
Description = description.Trim()
};
}
private static (string name, string assignmentGroupName, List<string> submissionTypes, DateTime dueAt, DateTime? lockAt) parseSettings(string input)
{
var name = extractLabelValue(input, "Name");
var rawLockAt = extractLabelValue(input, "LockAt");
var rawDueAt = extractLabelValue(input, "DueAt");
var localAssignmentGroupName = extractLabelValue(input, "AssignmentGroupName");
var submissionTypes = parseSubmissionTypes(input);
DateTime? lockAt = DateTime.TryParse(rawLockAt, out DateTime parsedLockAt)
? parsedLockAt
: null;
var dueAt = DateTime.TryParse(rawDueAt, out DateTime parsedDueAt)
? parsedDueAt
: throw new QuizMarkdownParseException($"Error with DueAt: {rawDueAt}");
return (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt);
}
private static List<string> parseSubmissionTypes(string input)
{
input = input.Replace("\r\n", "\n");
List<string> submissionTypes = [];
// Define a regular expression pattern to match the bulleted list items
string startOfTypePattern = @"- (.+)";
Regex regex = new(startOfTypePattern);
var words = input.Split("SubmissionTypes:");
var inputAfterSubmissionTypes = words[1];
string[] lines = inputAfterSubmissionTypes.Split("\n", StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
string trimmedLine = line.Trim();
Match match = regex.Match(trimmedLine);
if (!match.Success)
break;
string type = match.Groups[1].Value.Trim();
submissionTypes.Add(type);
}
return submissionTypes;
}
private static string extractLabelValue(string input, string label)
{
string pattern = $@"{label}: (.*?)\n";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
return match.Groups[1].Value;
}
return string.Empty;
}
public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown)
{
if (rawMarkdown.Trim() == string.Empty)
return [];
var lines = rawMarkdown.Trim().Split("\n");
var items = lines.Select(parseIndividualRubricItemMarkdown).ToArray();
return items;
}
private static RubricItem parseIndividualRubricItemMarkdown(string rawMarkdown)
{
var pointsPattern = @"\s*-\s*(\d+)\s*pt(s)?:";
var match = Regex.Match(rawMarkdown, pointsPattern);
if (!match.Success)
throw new RubricMarkdownParseException($"points not found: {rawMarkdown}");
var points = int.Parse(match.Groups[1].Value);
var label = string.Join(": ", rawMarkdown.Split(": ").Skip(1));
return new RubricItem()
{
Points = points,
Label = label
};
}
}

View File

@@ -2,7 +2,7 @@
MAJOR_VERSION="1" MAJOR_VERSION="1"
MINOR_VERSION="3" MINOR_VERSION="4"
VERSION="$MAJOR_VERSION.$MINOR_VERSION" VERSION="$MAJOR_VERSION.$MINOR_VERSION"
dotnet publish Management.Web/ \ dotnet publish Management.Web/ \

View File

@@ -16,6 +16,7 @@ services:
- ~/projects/faculty/1400/2024_spring_alex/modules:/app/storage/1400 - ~/projects/faculty/1400/2024_spring_alex/modules:/app/storage/1400
- ~/projects/faculty/1405/2024_spring_alex/modules:/app/storage/1405 - ~/projects/faculty/1405/2024_spring_alex/modules:/app/storage/1405
- ~/projects/faculty/4620_Distributed/2024Spring/modules:/app/storage/distributed - ~/projects/faculty/4620_Distributed/2024Spring/modules:/app/storage/distributed
- ~/projects/faculty/3840_Telemetry/2024Spring_alex/modules:/app/storage/telemetry_and_operations
collector: collector:
image: otel/opentelemetry-collector-contrib image: otel/opentelemetry-collector-contrib
@@ -30,22 +31,12 @@ services:
- 4318:4318 # OTLP http receiver - 4318:4318 # OTLP http receiver
- 55679:55679 # zpages extension - 55679:55679 # zpages extension
# The zipkin process services the UI, and also exposes a POST endpoint that
# instrumentation can send trace data to.
zipkin: zipkin:
image: ghcr.io/openzipkin/zipkin-slim image: ghcr.io/openzipkin/zipkin-slim
container_name: zipkin container_name: zipkin
# Environment settings are defined here https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#environment-variables # Environment settings are defined here https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#environment-variables
environment: environment:
- STORAGE_TYPE=mem - STORAGE_TYPE=mem
# Point the zipkin at the storage backend
# - MYSQL_HOST=mysql
# Uncomment to enable self-tracing
# - SELF_TRACING_ENABLED=true
# Uncomment to increase heap size
# - JAVA_OPTS=-Xms128m -Xmx128m -XX:+ExitOnOutOfMemoryError
ports: ports:
# Port used for the Zipkin UI and HTTP Api
- 9411:9411 - 9411:9411
# Uncomment to enable debug logging
# command: --logging.level.zipkin2=DEBUG # command: --logging.level.zipkin2=DEBUG

View File

@@ -0,0 +1,23 @@
services:
collector:
image: otel/opentelemetry-collector-contrib
volumes:
- ../otel-collector-config.yml:/etc/otelcol-contrib/config.yaml
ports:
- 1888:1888 # pprof extension
- 8888:8888 # Prometheus metrics exposed by the Collector
- 8889:8889 # Prometheus exporter metrics
- 13133:13133 # health_check extension
- 4317:4317 # OTLP gRPC receiver
- 4318:4318 # OTLP http receiver
- 55679:55679 # zpages extension
zipkin:
image: ghcr.io/openzipkin/zipkin-slim
container_name: zipkin
# Environment settings are defined here https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#environment-variables
environment:
- STORAGE_TYPE=mem
ports:
- 9411:9411
# command: --logging.level.zipkin2=DEBUG