department_dev #8
@@ -4,6 +4,7 @@ COPY pom.xml .
|
||||
RUN mvn dependency:go-offline -B
|
||||
COPY src ./src
|
||||
RUN mvn package -DskipTests -B
|
||||
RUN curl -L -o opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
|
||||
FROM eclipse-temurin:17-jre-alpine
|
||||
|
||||
@@ -13,5 +14,6 @@ USER spring:spring
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/target/app.jar app.jar
|
||||
COPY --from=build /app/opentelemetry-javaagent.jar opentelemetry-javaagent.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
ENTRYPOINT ["java", "-javaagent:opentelemetry-javaagent.jar", "-jar", "app.jar"]
|
||||
|
||||
@@ -56,6 +56,13 @@
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- OpenTelemetry API for custom span attributes -->
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-api</artifactId>
|
||||
<version>1.49.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.slf4j.MDC;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
|
||||
/**
|
||||
* Interceptor: извлекает поддомен из Host header и кладёт в TenantContext.
|
||||
@@ -48,6 +50,8 @@ public class TenantInterceptor implements HandlerInterceptor {
|
||||
// (нужно чтобы админ мог добавить тенант даже если его домен не настроен)
|
||||
if (path.startsWith("/api/database")) {
|
||||
TenantContext.setCurrentTenant(tenant);
|
||||
MDC.put("tenant.id", tenant);
|
||||
Span.current().setAttribute("tenant.id", tenant);
|
||||
log.debug("Database API request, tenant '{}' (no strict check)", tenant);
|
||||
return true;
|
||||
}
|
||||
@@ -66,6 +70,8 @@ public class TenantInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
|
||||
TenantContext.setCurrentTenant(tenant);
|
||||
MDC.put("tenant.id", tenant);
|
||||
Span.current().setAttribute("tenant.id", tenant);
|
||||
log.debug("Resolved tenant '{}' from Host '{}'", tenant, host);
|
||||
return true;
|
||||
}
|
||||
@@ -73,6 +79,7 @@ public class TenantInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
TenantContext.clear();
|
||||
MDC.remove("tenant.id");
|
||||
}
|
||||
|
||||
private String resolveTenant(String host) {
|
||||
|
||||
@@ -127,8 +127,7 @@ COMMENT ON TABLE equipments IS 'Оборудование';
|
||||
COMMENT ON TABLE classrooms IS 'Аудитории';
|
||||
COMMENT ON TABLE classroom_equipments IS 'Привязка оборудования к аудиториям';
|
||||
COMMENT ON TABLE teacher_subjects IS 'Привязка преподавателей к дисциплинам';
|
||||
COMMENT ON TABLE equipments IS 'Оборудование';
|
||||
COMMENT ON TABLE equipments IS 'Оборудование';
|
||||
COMMENT ON TABLE teacher_lesson_types IS 'Типы занятий преподавателя';
|
||||
|
||||
|
||||
COMMENT ON COLUMN users.id IS 'ID пользователя';
|
||||
@@ -199,4 +198,26 @@ COMMENT ON COLUMN lessons.type_lesson IS 'Тип урока';
|
||||
COMMENT ON COLUMN lessons.classroom_id IS 'ID аудитории, в которой проходит урок';
|
||||
COMMENT ON COLUMN lessons.day IS 'День недели, в который проходит урок';
|
||||
COMMENT ON COLUMN lessons.week IS 'Номер недели, в которой проходит урок';
|
||||
COMMENT ON COLUMN lessons.time IS 'Время урока';
|
||||
COMMENT ON COLUMN lessons.time IS 'Время урока';
|
||||
|
||||
COMMENT ON COLUMN departments.id IS 'ID кафедры';
|
||||
COMMENT ON COLUMN departments.name IS 'Название кафедры';
|
||||
COMMENT ON COLUMN departments.code IS 'Код кафедры';
|
||||
|
||||
COMMENT ON COLUMN specialties.id IS 'ID специальности';
|
||||
COMMENT ON COLUMN specialties.name IS 'Название специальности';
|
||||
COMMENT ON COLUMN specialties.specialty_code IS 'Код специальности';
|
||||
|
||||
COMMENT ON COLUMN teacher_lesson_types.user_id IS 'ID преподавателя';
|
||||
COMMENT ON COLUMN teacher_lesson_types.subject_id IS 'ID предмета';
|
||||
COMMENT ON COLUMN teacher_lesson_types.lesson_type_id IS 'ID типа занятия';
|
||||
|
||||
COMMENT ON COLUMN schedule_data.id IS 'ID записи данных расписания';
|
||||
|
||||
COMMENT ON COLUMN subjects.department_id IS 'ID кафедры';
|
||||
|
||||
COMMENT ON COLUMN student_groups.department_id IS 'ID кафедры';
|
||||
|
||||
COMMENT ON COLUMN users.full_name IS 'ФИО пользователя';
|
||||
COMMENT ON COLUMN users.job_title IS 'Должность пользователя';
|
||||
COMMENT ON COLUMN users.department_id IS 'ID кафедры';
|
||||
@@ -1,6 +1,32 @@
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
// --- OpenTelemetry Frontend Instrumentation ---
|
||||
// Загружаем OTel Web SDK динамически через esm.sh, чтобы не ломать старый Vanilla JS (без type="module")
|
||||
import('https://esm.sh/@opentelemetry/sdk-trace-web').then(async ({ WebTracerProvider, BatchSpanProcessor }) => {
|
||||
const { OTLPTraceExporter } = await import('https://esm.sh/@opentelemetry/exporter-trace-otlp-http');
|
||||
const { getWebAutoInstrumentations } = await import('https://esm.sh/@opentelemetry/auto-instrumentations-web');
|
||||
const { registerInstrumentations } = await import('https://esm.sh/@opentelemetry/instrumentation');
|
||||
const { Resource } = await import('https://esm.sh/@opentelemetry/resources');
|
||||
|
||||
const exporter = new OTLPTraceExporter({
|
||||
url: window.location.origin + '/otel/v1/traces' // Трафик пойдет через ваш Caddy Proxy
|
||||
});
|
||||
|
||||
const provider = new WebTracerProvider({
|
||||
resource: new Resource({ 'service.name': 'magistr-frontend' }),
|
||||
});
|
||||
|
||||
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
|
||||
provider.register();
|
||||
|
||||
registerInstrumentations({
|
||||
instrumentations: [getWebAutoInstrumentations()]
|
||||
});
|
||||
console.log("SigNoz (OpenTelemetry) инициализирован во фронтенде.");
|
||||
}).catch(e => console.error("Ошибка загрузки OTel:", e));
|
||||
// ----------------------------------------------
|
||||
|
||||
const form = document.getElementById('login-form');
|
||||
const usernameInput = document.getElementById('username');
|
||||
const passwordInput = document.getElementById('password');
|
||||
|
||||
Reference in New Issue
Block a user